@vuu-ui/vuu-ui-controls 0.13.44 → 0.13.45-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/context-panel-provider/ContextPanelProvider.js +9 -11
- package/cjs/context-panel-provider/ContextPanelProvider.js.map +1 -1
- package/cjs/time-input/useTimeInput.js +7 -3
- package/cjs/time-input/useTimeInput.js.map +1 -1
- package/cjs/vuu-typeahead-input/VuuTypeaheadInput.js +2 -0
- package/cjs/vuu-typeahead-input/VuuTypeaheadInput.js.map +1 -1
- package/cjs/vuu-typeahead-input/useVuuTypeaheadInput.js +25 -7
- package/cjs/vuu-typeahead-input/useVuuTypeaheadInput.js.map +1 -1
- package/esm/context-panel-provider/ContextPanelProvider.js +9 -11
- package/esm/context-panel-provider/ContextPanelProvider.js.map +1 -1
- package/esm/time-input/useTimeInput.js +7 -3
- package/esm/time-input/useTimeInput.js.map +1 -1
- package/esm/vuu-typeahead-input/VuuTypeaheadInput.js +2 -0
- package/esm/vuu-typeahead-input/VuuTypeaheadInput.js.map +1 -1
- package/esm/vuu-typeahead-input/useVuuTypeaheadInput.js +25 -7
- package/esm/vuu-typeahead-input/useVuuTypeaheadInput.js.map +1 -1
- package/package.json +10 -10
- package/types/context-panel-provider/ContextPanelProvider.d.ts +8 -3
- package/types/vuu-typeahead-input/VuuTypeaheadInput.d.ts +3 -2
|
@@ -31,24 +31,22 @@ const ContextPanelProvider = ({
|
|
|
31
31
|
}, []);
|
|
32
32
|
const hideContextPanel = hideContextPanelProp ?? inheritedHideContextPanel;
|
|
33
33
|
const showContextPanel = React.useCallback(
|
|
34
|
-
(
|
|
34
|
+
(elementOrComponentType, title, props) => {
|
|
35
35
|
if (showContextPanelProp) {
|
|
36
|
-
showContextPanelProp(
|
|
36
|
+
showContextPanelProp(elementOrComponentType, title, props);
|
|
37
37
|
} else if (inheritedShowContextPanel !== UndefinedShowContextPanel) {
|
|
38
|
-
inheritedShowContextPanel(
|
|
38
|
+
inheritedShowContextPanel(elementOrComponentType, title, props);
|
|
39
39
|
} else if (!vuuLayout.isUnconfiguredProperty(showComponentInContextPanel)) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
} else {
|
|
45
|
-
const component = vuuLayout.layoutFromJson(
|
|
40
|
+
const component = typeof elementOrComponentType === "string" ? { type: elementOrComponentType, props } : elementOrComponentType;
|
|
41
|
+
showComponentInContextPanel(component, title);
|
|
42
|
+
} else if (typeof elementOrComponentType === "string") {
|
|
43
|
+
const component = typeof elementOrComponentType === "string" ? vuuLayout.layoutFromJson(
|
|
46
44
|
{
|
|
47
|
-
type:
|
|
45
|
+
type: elementOrComponentType,
|
|
48
46
|
props
|
|
49
47
|
},
|
|
50
48
|
""
|
|
51
|
-
);
|
|
49
|
+
) : elementOrComponentType;
|
|
52
50
|
setDialog(
|
|
53
51
|
/* @__PURE__ */ jsxRuntime.jsxs(core.Dialog, { open: true, onOpenChange: handleOpenChange, children: [
|
|
54
52
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextPanelProvider.js","sources":["../../../../packages/vuu-ui-controls/src/context-panel-provider/ContextPanelProvider.tsx"],"sourcesContent":["import {\n createContext,\n ReactElement,\n ReactNode,\n useCallback,\n useContext,\n useState,\n} from \"react\";\nimport {\n isUnconfiguredProperty,\n layoutFromJson,\n useLayoutOperation,\n} from \"@vuu-ui/vuu-layout\";\nimport { LayoutJSON } from \"@vuu-ui/vuu-utils\";\nimport {\n Dialog,\n DialogCloseButton,\n DialogContent,\n DialogHeader,\n} from \"@salt-ds/core\";\n\nexport type ShowContextPanel = (\n
|
|
1
|
+
{"version":3,"file":"ContextPanelProvider.js","sources":["../../../../packages/vuu-ui-controls/src/context-panel-provider/ContextPanelProvider.tsx"],"sourcesContent":["import React, {\n createContext,\n ReactElement,\n ReactNode,\n useCallback,\n useContext,\n useState,\n} from \"react\";\nimport {\n isUnconfiguredProperty,\n layoutFromJson,\n useLayoutOperation,\n} from \"@vuu-ui/vuu-layout\";\nimport { LayoutJSON } from \"@vuu-ui/vuu-utils\";\nimport {\n Dialog,\n DialogCloseButton,\n DialogContent,\n DialogHeader,\n} from \"@salt-ds/core\";\n\n/**\n * If component is a string, the component will be read from the\n * comoponent registry. In that case, componentProps can be used\n * to pass props to the component.\n */\nexport type ShowContextPanel = (\n component: string | ReactElement,\n title: string,\n componentProps?: unknown,\n) => void;\n\nexport interface ContextPanelProps {\n hideContextPanel?: () => void;\n showContextPanel: ShowContextPanel;\n}\n\nconst UndefinedShowContextPanel = () => {\n console.warn(\n \"[ContextPanelContext] no implementation for showContextPanel, you need to add a ContextPanelProvider\",\n );\n};\n\nexport const ContextPanelContext = createContext<ContextPanelProps>({\n showContextPanel: UndefinedShowContextPanel,\n});\n\nexport const ContextPanelProvider = ({\n children,\n hideContextPanel: hideContextPanelProp,\n showContextPanel: showContextPanelProp,\n}: Partial<ContextPanelProps> & {\n children: ReactNode;\n}) => {\n const {\n hideContextPanel: inheritedHideContextPanel,\n showContextPanel: inheritedShowContextPanel,\n } = useContext(ContextPanelContext);\n const { showComponentInContextPanel } = useLayoutOperation();\n const [dialog, setDialog] = useState<ReactElement | null>(null);\n\n const handleOpenChange = useCallback((isOpen: boolean) => {\n if (!isOpen) {\n setDialog(null);\n }\n }, []);\n\n const hideContextPanel = hideContextPanelProp ?? inheritedHideContextPanel;\n\n const showContextPanel = useCallback<ShowContextPanel>(\n (elementOrComponentType, title, props) => {\n if (showContextPanelProp) {\n showContextPanelProp(elementOrComponentType, title, props);\n } else if (inheritedShowContextPanel !== UndefinedShowContextPanel) {\n inheritedShowContextPanel(elementOrComponentType, title, props);\n } else if (!isUnconfiguredProperty(showComponentInContextPanel)) {\n const component =\n typeof elementOrComponentType === \"string\"\n ? ({ type: elementOrComponentType, props } as LayoutJSON)\n : elementOrComponentType;\n showComponentInContextPanel(component, title);\n } else if (typeof elementOrComponentType === \"string\") {\n const component =\n typeof elementOrComponentType === \"string\"\n ? layoutFromJson(\n {\n type: elementOrComponentType,\n props,\n } as LayoutJSON,\n \"\",\n )\n : elementOrComponentType;\n\n setDialog(\n <Dialog open={true} onOpenChange={handleOpenChange}>\n <DialogCloseButton\n appearance=\"transparent\"\n data-embedded\n data-icon=\"close\"\n onClick={() => setDialog(null)}\n sentiment=\"neutral\"\n />\n <DialogHeader header={title} />\n <DialogContent>{component}</DialogContent>\n </Dialog>,\n );\n }\n },\n [\n handleOpenChange,\n inheritedShowContextPanel,\n showComponentInContextPanel,\n showContextPanelProp,\n ],\n );\n\n return (\n <ContextPanelContext.Provider\n value={{ hideContextPanel, showContextPanel }}\n >\n {children}\n {dialog}\n </ContextPanelContext.Provider>\n );\n};\n\nexport function useContextPanel() {\n const { showContextPanel } = useContext(ContextPanelContext);\n return showContextPanel;\n}\n\nexport function useHideContextPanel() {\n const { hideContextPanel } = useContext(ContextPanelContext);\n return hideContextPanel;\n}\n"],"names":["createContext","useContext","useLayoutOperation","useState","useCallback","isUnconfiguredProperty","layoutFromJson","jsxs","Dialog","jsx","DialogCloseButton","DialogHeader","DialogContent"],"mappings":"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"}
|
|
@@ -96,9 +96,13 @@ const useTimeInput = ({
|
|
|
96
96
|
const handleMouseDown = React.useCallback(() => {
|
|
97
97
|
mousedDownRef.current = true;
|
|
98
98
|
}, []);
|
|
99
|
-
const handleMouseUp = React.useCallback(
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
const handleMouseUp = React.useCallback(
|
|
100
|
+
(e) => {
|
|
101
|
+
e.preventDefault();
|
|
102
|
+
maskedInputRef.current?.click();
|
|
103
|
+
},
|
|
104
|
+
[]
|
|
105
|
+
);
|
|
102
106
|
return {
|
|
103
107
|
inputRef: setInputEl,
|
|
104
108
|
eventHandlers: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTimeInput.js","sources":["../../../../packages/vuu-ui-controls/src/time-input/useTimeInput.ts"],"sourcesContent":["import {\n type CommitHandler,\n DateStringISO,\n isValidTimeString,\n type TimeString,\n} from \"@vuu-ui/vuu-utils\";\nimport {\n ChangeEvent,\n ChangeEventHandler,\n ClipboardEventHandler,\n FocusEventHandler,\n KeyboardEventHandler,\n MouseEventHandler,\n RefCallback,\n useCallback,\n useMemo,\n useRef,\n} from \"react\";\nimport { Digit, MaskedInput } from \"./MaskedInput\";\n\nconst isDigit = (char: string): char is Digit =>\n char.length === 1 && /[0-9]/.test(char);\n\nexport interface TimeInputHookProps {\n date?: Date | DateStringISO;\n defaultValue?: TimeString;\n onChange?: ChangeEventHandler<HTMLInputElement>;\n onCommit: CommitHandler<HTMLInputElement, TimeString>;\n value?: TimeString;\n}\n\nexport const useTimeInput = ({\n defaultValue,\n onChange,\n onCommit,\n value,\n}: TimeInputHookProps) => {\n const mousedDownRef = useRef(false);\n const maskedInputRef = useRef<MaskedInput | undefined>(undefined);\n useMemo(() => {\n if (maskedInputRef.current === undefined) {\n maskedInputRef.current = new MaskedInput(defaultValue, null);\n maskedInputRef.current.on(\n \"change\",\n (e: ChangeEvent<HTMLInputElement>) => {\n onChange?.(e);\n },\n );\n }\n\n if (value && value !== maskedInputRef.current.value) {\n maskedInputRef.current.value = value;\n }\n }, [defaultValue, onChange, value]);\n\n const setInputEl = useCallback<RefCallback<HTMLInputElement>>((el) => {\n if (el && maskedInputRef.current) {\n maskedInputRef.current.input = el;\n }\n }, []);\n const back = useRef(false);\n\n const commitValue = useCallback<CommitHandler<HTMLInputElement, string>>(\n (evt, value) => {\n if (isValidTimeString(value)) {\n onCommit(evt, value, \"text-input\");\n } else if (value === \"hh:mm:ss\") {\n console.log(\"no value set\");\n } else {\n console.log(`value is not valid`);\n }\n },\n [onCommit],\n );\n\n const handleKeyDown = useCallback<KeyboardEventHandler<HTMLInputElement>>(\n (e) => {\n const { current: maskedInput } = maskedInputRef;\n if (maskedInput) {\n if (e.key === \"Backspace\") {\n maskedInput.backspace();\n back.current = true;\n } else if (isDigit(e.key)) {\n maskedInput.update(e.key);\n } else if (e.key === \"ArrowLeft\") {\n maskedInput.moveFocus(\"left\");\n } else if (e.key === \"ArrowRight\") {\n maskedInput.moveFocus(\"right\");\n } else if (e.key === \"ArrowUp\") {\n maskedInput.incrementValue();\n } else if (e.key === \"ArrowDown\") {\n maskedInput.decrementValue();\n } else if (e.key === \"v\" && e.metaKey) {\n // keyboard paste, do not prevent default\n return;\n } else if (e.key === \"Tab\") {\n return;\n } else if (e.key === \"Enter\") {\n commitValue(e, maskedInput.value);\n }\n }\n e.preventDefault();\n },\n [commitValue],\n );\n\n const handleDoubleClick = useCallback(() => {\n maskedInputRef.current?.doubleClick();\n }, []);\n\n const handlePaste = useCallback<ClipboardEventHandler<HTMLInputElement>>(\n (e) => {\n const value = e.clipboardData.getData(\"text\");\n if (isValidTimeString(value)) {\n maskedInputRef.current?.pasteValue(value);\n }\n },\n [],\n );\n\n const handleFocus = useCallback<FocusEventHandler<HTMLInputElement>>(() => {\n // If keboard has been used, how do we detect SHIFT + TAB\n if (mousedDownRef.current) {\n mousedDownRef.current = false;\n } else {\n maskedInputRef.current?.focus();\n }\n }, []);\n\n const handleMouseDown = useCallback<MouseEventHandler>(() => {\n mousedDownRef.current = true;\n }, []);\n\n const handleMouseUp = useCallback<MouseEventHandler<HTMLInputElement>>(() => {\n
|
|
1
|
+
{"version":3,"file":"useTimeInput.js","sources":["../../../../packages/vuu-ui-controls/src/time-input/useTimeInput.ts"],"sourcesContent":["import {\n type CommitHandler,\n DateStringISO,\n isValidTimeString,\n type TimeString,\n} from \"@vuu-ui/vuu-utils\";\nimport {\n ChangeEvent,\n ChangeEventHandler,\n ClipboardEventHandler,\n FocusEventHandler,\n KeyboardEventHandler,\n MouseEventHandler,\n RefCallback,\n useCallback,\n useMemo,\n useRef,\n} from \"react\";\nimport { Digit, MaskedInput } from \"./MaskedInput\";\n\nconst isDigit = (char: string): char is Digit =>\n char.length === 1 && /[0-9]/.test(char);\n\nexport interface TimeInputHookProps {\n date?: Date | DateStringISO;\n defaultValue?: TimeString;\n onChange?: ChangeEventHandler<HTMLInputElement>;\n onCommit: CommitHandler<HTMLInputElement, TimeString>;\n value?: TimeString;\n}\n\nexport const useTimeInput = ({\n defaultValue,\n onChange,\n onCommit,\n value,\n}: TimeInputHookProps) => {\n const mousedDownRef = useRef(false);\n const maskedInputRef = useRef<MaskedInput | undefined>(undefined);\n useMemo(() => {\n if (maskedInputRef.current === undefined) {\n maskedInputRef.current = new MaskedInput(defaultValue, null);\n maskedInputRef.current.on(\n \"change\",\n (e: ChangeEvent<HTMLInputElement>) => {\n onChange?.(e);\n },\n );\n }\n\n if (value && value !== maskedInputRef.current.value) {\n maskedInputRef.current.value = value;\n }\n }, [defaultValue, onChange, value]);\n\n const setInputEl = useCallback<RefCallback<HTMLInputElement>>((el) => {\n if (el && maskedInputRef.current) {\n maskedInputRef.current.input = el;\n }\n }, []);\n const back = useRef(false);\n\n const commitValue = useCallback<CommitHandler<HTMLInputElement, string>>(\n (evt, value) => {\n if (isValidTimeString(value)) {\n onCommit(evt, value, \"text-input\");\n } else if (value === \"hh:mm:ss\") {\n console.log(\"no value set\");\n } else {\n console.log(`value is not valid`);\n }\n },\n [onCommit],\n );\n\n const handleKeyDown = useCallback<KeyboardEventHandler<HTMLInputElement>>(\n (e) => {\n const { current: maskedInput } = maskedInputRef;\n if (maskedInput) {\n if (e.key === \"Backspace\") {\n maskedInput.backspace();\n back.current = true;\n } else if (isDigit(e.key)) {\n maskedInput.update(e.key);\n } else if (e.key === \"ArrowLeft\") {\n maskedInput.moveFocus(\"left\");\n } else if (e.key === \"ArrowRight\") {\n maskedInput.moveFocus(\"right\");\n } else if (e.key === \"ArrowUp\") {\n maskedInput.incrementValue();\n } else if (e.key === \"ArrowDown\") {\n maskedInput.decrementValue();\n } else if (e.key === \"v\" && e.metaKey) {\n // keyboard paste, do not prevent default\n return;\n } else if (e.key === \"Tab\") {\n return;\n } else if (e.key === \"Enter\") {\n commitValue(e, maskedInput.value);\n }\n }\n e.preventDefault();\n },\n [commitValue],\n );\n\n const handleDoubleClick = useCallback(() => {\n maskedInputRef.current?.doubleClick();\n }, []);\n\n const handlePaste = useCallback<ClipboardEventHandler<HTMLInputElement>>(\n (e) => {\n const value = e.clipboardData.getData(\"text\");\n if (isValidTimeString(value)) {\n maskedInputRef.current?.pasteValue(value);\n }\n },\n [],\n );\n\n const handleFocus = useCallback<FocusEventHandler<HTMLInputElement>>(() => {\n // If keboard has been used, how do we detect SHIFT + TAB\n if (mousedDownRef.current) {\n mousedDownRef.current = false;\n } else {\n maskedInputRef.current?.focus();\n }\n }, []);\n\n const handleMouseDown = useCallback<MouseEventHandler>(() => {\n mousedDownRef.current = true;\n }, []);\n\n const handleMouseUp = useCallback<MouseEventHandler<HTMLInputElement>>(\n (e) => {\n e.preventDefault();\n maskedInputRef.current?.click();\n },\n [],\n );\n\n return {\n inputRef: setInputEl,\n eventHandlers: {\n onBlur: maskedInputRef.current?.blur,\n onDoubleClick: handleDoubleClick,\n onFocus: handleFocus,\n onKeyDown: handleKeyDown,\n onMouseDown: handleMouseDown,\n onMouseUp: handleMouseUp,\n onPaste: handlePaste,\n },\n };\n};\n"],"names":["useRef","useMemo","MaskedInput","useCallback","value","isValidTimeString"],"mappings":"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"}
|
|
@@ -20,6 +20,7 @@ const VuuTypeaheadInput = ({
|
|
|
20
20
|
inputProps: inputPropsProp,
|
|
21
21
|
minCharacterCountToTriggerSuggestions,
|
|
22
22
|
onCommit,
|
|
23
|
+
selectOnTab,
|
|
23
24
|
table
|
|
24
25
|
}) => {
|
|
25
26
|
const targetWindow = window.useWindow();
|
|
@@ -60,6 +61,7 @@ const VuuTypeaheadInput = ({
|
|
|
60
61
|
onSelectionChange,
|
|
61
62
|
open,
|
|
62
63
|
ref,
|
|
64
|
+
selectOnTab,
|
|
63
65
|
value,
|
|
64
66
|
children: typeaheadValues.map((state) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
65
67
|
core.Option,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VuuTypeaheadInput.js","sources":["../../../../packages/vuu-ui-controls/src/vuu-typeahead-input/VuuTypeaheadInput.tsx"],"sourcesContent":["import { ComboBox, Option } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { NO_DATA_MATCH } from \"@vuu-ui/vuu-utils\";\nimport cx from \"clsx\";\nimport {\n useVuuTypeaheadInput,\n VuuTypeaheadInputHookProps,\n} from \"./useVuuTypeaheadInput\";\nimport vuuTypeaheadInputCss from \"./VuuTypeaheadInput.css\";\n\nconst classBase = \"vuuTypeaheadInput\";\nconst [noMatchingData] = NO_DATA_MATCH;\n\nexport interface VuuTypeaheadInputProps
|
|
1
|
+
{"version":3,"file":"VuuTypeaheadInput.js","sources":["../../../../packages/vuu-ui-controls/src/vuu-typeahead-input/VuuTypeaheadInput.tsx"],"sourcesContent":["import { ComboBox, ComboBoxProps, Option } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { NO_DATA_MATCH } from \"@vuu-ui/vuu-utils\";\nimport cx from \"clsx\";\nimport {\n useVuuTypeaheadInput,\n VuuTypeaheadInputHookProps,\n} from \"./useVuuTypeaheadInput\";\nimport vuuTypeaheadInputCss from \"./VuuTypeaheadInput.css\";\n\nconst classBase = \"vuuTypeaheadInput\";\nconst [noMatchingData] = NO_DATA_MATCH;\n\nexport interface VuuTypeaheadInputProps\n extends VuuTypeaheadInputHookProps,\n Pick<ComboBoxProps, \"selectOnTab\"> {\n className?: string;\n}\n\nexport const VuuTypeaheadInput = ({\n allowFreeInput,\n className,\n column,\n freeTextWarning,\n highlightFirstSuggestion,\n inputProps: inputPropsProp,\n minCharacterCountToTriggerSuggestions,\n onCommit,\n selectOnTab,\n table,\n}: VuuTypeaheadInputProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-typeahead-input\",\n css: vuuTypeaheadInputCss,\n window: targetWindow,\n });\n\n const {\n inputProps,\n noFreeText,\n onChange,\n onKeyDown,\n onOpenChange,\n onSelectionChange,\n open,\n ref,\n typeaheadValues,\n value,\n } = useVuuTypeaheadInput({\n allowFreeInput,\n column,\n freeTextWarning,\n highlightFirstSuggestion,\n inputProps: inputPropsProp,\n minCharacterCountToTriggerSuggestions,\n onCommit,\n table,\n });\n\n // need latest version of salt combobox\n // const defaultHighlightedIndex =\n // highlightFirstSuggestion === false ? -1 : undefined;\n\n return (\n <ComboBox\n className={cx(classBase, className)}\n // defaultHighlightedIndex={defaultHighlightedIndex}\n inputProps={inputProps}\n onChange={onChange}\n onKeyDown={onKeyDown}\n onOpenChange={onOpenChange}\n onSelectionChange={onSelectionChange}\n open={open}\n ref={ref}\n selectOnTab={selectOnTab}\n value={value}\n >\n {typeaheadValues.map((state) => (\n <Option\n className=\"vuuTypeaheadOption\"\n value={state}\n key={state}\n disabled={state === noMatchingData || state === noFreeText}\n />\n ))}\n </ComboBox>\n );\n};\n"],"names":["NO_DATA_MATCH","useWindow","useComponentCssInjection","vuuTypeaheadInputCss","useVuuTypeaheadInput","jsx","ComboBox","Option"],"mappings":";;;;;;;;;;;AAWA,MAAM,SAAY,GAAA,mBAAA;AAClB,MAAM,CAAC,cAAc,CAAI,GAAAA,sBAAA;AAQlB,MAAM,oBAAoB,CAAC;AAAA,EAChC,cAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,eAAA;AAAA,EACA,wBAAA;AAAA,EACA,UAAY,EAAA,cAAA;AAAA,EACZ,qCAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAA8B,KAAA;AAC5B,EAAA,MAAM,eAAeC,gBAAU,EAAA;AAC/B,EAAyBC,+BAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,qBAAA;AAAA,IACR,GAAK,EAAAC,mBAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GACT,CAAA;AAED,EAAM,MAAA;AAAA,IACJ,UAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA;AAAA,IACA,iBAAA;AAAA,IACA,IAAA;AAAA,IACA,GAAA;AAAA,IACA,eAAA;AAAA,IACA;AAAA,MACEC,yCAAqB,CAAA;AAAA,IACvB,cAAA;AAAA,IACA,MAAA;AAAA,IACA,eAAA;AAAA,IACA,wBAAA;AAAA,IACA,UAAY,EAAA,cAAA;AAAA,IACZ,qCAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,GACD,CAAA;AAMD,EACE,uBAAAC,cAAA;AAAA,IAACC,aAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAG,CAAA,SAAA,EAAW,SAAS,CAAA;AAAA,MAElC,UAAA;AAAA,MACA,QAAA;AAAA,MACA,SAAA;AAAA,MACA,YAAA;AAAA,MACA,iBAAA;AAAA,MACA,IAAA;AAAA,MACA,GAAA;AAAA,MACA,WAAA;AAAA,MACA,KAAA;AAAA,MAEC,QAAA,EAAA,eAAA,CAAgB,GAAI,CAAA,CAAC,KACpB,qBAAAD,cAAA;AAAA,QAACE,WAAA;AAAA,QAAA;AAAA,UACC,SAAU,EAAA,oBAAA;AAAA,UACV,KAAO,EAAA,KAAA;AAAA,UAEP,QAAA,EAAU,KAAU,KAAA,cAAA,IAAkB,KAAU,KAAA;AAAA,SAAA;AAAA,QAD3C;AAAA,OAGR;AAAA;AAAA,GACH;AAEJ;;;;"}
|
|
@@ -28,6 +28,14 @@ const useVuuTypeaheadInput = ({
|
|
|
28
28
|
const getSuggestions = vuuDataReact.useTypeaheadSuggestions();
|
|
29
29
|
const pendingListFocusRef = React.useRef(false);
|
|
30
30
|
const { current: value } = valueRef;
|
|
31
|
+
React.useMemo(() => {
|
|
32
|
+
console.log(
|
|
33
|
+
`[useVuuTypeaheadInput] inputProps value has changed ${inputPropsProp?.value} valueRef value ${valueRef.current}`
|
|
34
|
+
);
|
|
35
|
+
if (inputPropsProp?.value !== void 0 && inputPropsProp?.value !== valueRef.current) {
|
|
36
|
+
setValue(`${inputPropsProp.value}`);
|
|
37
|
+
}
|
|
38
|
+
}, [inputPropsProp?.value, setValue, valueRef]);
|
|
31
39
|
const commitTimeout = React.useRef(null);
|
|
32
40
|
const handleKeyDown = React.useCallback(
|
|
33
41
|
(evt) => {
|
|
@@ -53,7 +61,7 @@ const useVuuTypeaheadInput = ({
|
|
|
53
61
|
const input = el?.querySelector("input") ?? null;
|
|
54
62
|
inputRef.current = input;
|
|
55
63
|
}, []);
|
|
56
|
-
React.
|
|
64
|
+
const refreshSuggestions = React.useCallback(() => {
|
|
57
65
|
if (table) {
|
|
58
66
|
const vuuTable = vuuUtils.getVuuTable(table);
|
|
59
67
|
if (meetsMinTextLengthThreshold(
|
|
@@ -62,7 +70,6 @@ const useVuuTypeaheadInput = ({
|
|
|
62
70
|
)) {
|
|
63
71
|
const params = value ? [vuuTable, column, value] : [vuuTable, column];
|
|
64
72
|
getSuggestions(params).then((suggestions) => {
|
|
65
|
-
console.log({ suggestions });
|
|
66
73
|
if (suggestions === false) {
|
|
67
74
|
setTypeaheadValues([]);
|
|
68
75
|
} else if (suggestions.length === 0 && value) {
|
|
@@ -87,13 +94,16 @@ const useVuuTypeaheadInput = ({
|
|
|
87
94
|
}
|
|
88
95
|
}
|
|
89
96
|
}, [
|
|
90
|
-
|
|
97
|
+
NO_FREE_TEXT,
|
|
91
98
|
column,
|
|
92
99
|
getSuggestions,
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
100
|
+
minCharacterCountToTriggerSuggestions,
|
|
101
|
+
table,
|
|
102
|
+
value
|
|
96
103
|
]);
|
|
104
|
+
React.useEffect(() => {
|
|
105
|
+
refreshSuggestions();
|
|
106
|
+
}, [refreshSuggestions]);
|
|
97
107
|
const handleChange = React.useCallback(
|
|
98
108
|
(evt) => {
|
|
99
109
|
const { value: newValue } = evt.target;
|
|
@@ -130,9 +140,17 @@ const useVuuTypeaheadInput = ({
|
|
|
130
140
|
setOpen(newOpen);
|
|
131
141
|
}
|
|
132
142
|
};
|
|
143
|
+
const handleInputFocus = React.useCallback(
|
|
144
|
+
(e) => {
|
|
145
|
+
inputPropsProp?.onFocus?.(e);
|
|
146
|
+
refreshSuggestions();
|
|
147
|
+
},
|
|
148
|
+
[inputPropsProp, refreshSuggestions]
|
|
149
|
+
);
|
|
133
150
|
const inputProps = {
|
|
134
151
|
...inputPropsProp,
|
|
135
|
-
autoComplete: "off"
|
|
152
|
+
autoComplete: "off",
|
|
153
|
+
onFocus: handleInputFocus
|
|
136
154
|
};
|
|
137
155
|
const [noFreeText] = NO_FREE_TEXT;
|
|
138
156
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useVuuTypeaheadInput.js","sources":["../../../../packages/vuu-ui-controls/src/vuu-typeahead-input/useVuuTypeaheadInput.ts"],"sourcesContent":["import { PillInputProps } from \"@salt-ds/core/dist-types/pill-input\";\nimport { useTypeaheadSuggestions } from \"@vuu-ui/vuu-data-react\";\nimport { TableSchemaTable } from \"@vuu-ui/vuu-data-types\";\nimport type { TypeaheadParams } from \"@vuu-ui/vuu-protocol-types\";\nimport {\n dispatchKeyboardEvent,\n getVuuTable,\n useStateRef,\n NO_DATA_MATCH,\n type CommitHandler,\n} from \"@vuu-ui/vuu-utils\";\nimport {\n ComponentPropsWithoutRef,\n KeyboardEventHandler,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ChangeEventHandler,\n type RefCallback,\n type SyntheticEvent,\n} from \"react\";\n\nconst meetsMinTextLengthThreshold = (value: string, minLength: number) =>\n value.length >= minLength;\n\nexport interface VuuTypeaheadInputHookProps {\n /**\n * Allows a text string to be submitted that does not match any suggestion\n * Defaults to true\n */\n allowFreeInput?: boolean;\n column: string;\n /**\n * A warning to display to the user if allowFreeText is false and they attempt\n * to commit text which does not match any suggestions. A default message will\n * be shown if not provided\n */\n freeTextWarning?: string;\n /**\n * When suggestions are displayed, should first option be highlighted ?\n * Highlighted option will be selected if Enter pressed. If this option\n * is not applied and no suggestion is highlighted, Enter will commit\n * current text. This will be desirable if filter operator will be\n * 'contains', not if filter operator will be '='.\n */\n highlightFirstSuggestion?: boolean;\n inputProps?: PillInputProps[\"inputProps\"];\n /**\n * If zero, suggestions will be shown even without any text input.\n * Suggestions will be displayed on click, or, if focused via keynoard,\n * on ArrowDown.\n * If n, where n > 0, then n characters must be typed before suggestion\n * list will be fetched.\n */\n minCharacterCountToTriggerSuggestions?: 0 | 1 | 2 | 3;\n onCommit: CommitHandler<HTMLInputElement>;\n table: TableSchemaTable;\n}\n\nconst defaultFreeTextWarning =\n \"Please select a value from the list of suggestions. If no suggestions match your text, then the value is not valid. If you believe this should be a valid value, please reach out to the support team\";\n\nexport const useVuuTypeaheadInput = ({\n allowFreeInput = true,\n column,\n freeTextWarning,\n highlightFirstSuggestion = true,\n inputProps: inputPropsProp,\n minCharacterCountToTriggerSuggestions = 1,\n onCommit,\n table,\n}: VuuTypeaheadInputHookProps) => {\n const NO_FREE_TEXT = useMemo(\n () => [freeTextWarning ?? defaultFreeTextWarning],\n [freeTextWarning],\n );\n const [valueRef, setValue] = useStateRef(\"\");\n const [open, setOpen] = useState(false);\n const inputRef = useRef<HTMLInputElement | null>(null);\n const rootRef = useRef<HTMLDivElement | null>(null);\n const [typeaheadValues, setTypeaheadValues] = useState<string[]>([]);\n const getSuggestions = useTypeaheadSuggestions();\n const pendingListFocusRef = useRef(false);\n\n const { current: value } = valueRef;\n const commitTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const handleKeyDown = useCallback<KeyboardEventHandler<HTMLInputElement>>(\n (evt) => {\n const { current: value } = valueRef;\n if (evt.key === \"Enter\" && value !== \"\") {\n if (allowFreeInput) {\n commitTimeout.current = setTimeout(() => {\n onCommit?.(evt, value, \"text-input\");\n setOpen(false);\n commitTimeout.current = null;\n }, 200);\n } else {\n setTypeaheadValues(NO_FREE_TEXT);\n }\n } else if (evt.key === \"Enter\" && value === \"\") {\n console.log(\"ENTER no value\");\n }\n },\n [NO_FREE_TEXT, allowFreeInput, onCommit, valueRef],\n );\n\n const callbackRef = useCallback<RefCallback<HTMLDivElement>>((el) => {\n rootRef.current = el;\n const input = el?.querySelector(\"input\") ?? null;\n inputRef.current = input;\n }, []);\n\n useEffect(() => {\n if (table) {\n const vuuTable = getVuuTable(table);\n if (\n meetsMinTextLengthThreshold(\n value,\n minCharacterCountToTriggerSuggestions,\n )\n ) {\n const params: TypeaheadParams = value\n ? [vuuTable, column, value]\n : [vuuTable, column];\n getSuggestions(params)\n .then((suggestions) => {\n console.log({ suggestions });\n if (suggestions === false) {\n // TODO is this right\n setTypeaheadValues([]);\n } else if (suggestions.length === 0 && value) {\n setTypeaheadValues((values) =>\n // Do not update if we have already set suggestions to the no free text warning\n values === NO_FREE_TEXT ? NO_FREE_TEXT : NO_DATA_MATCH,\n );\n } else {\n setTypeaheadValues(suggestions);\n if (pendingListFocusRef.current && inputRef.current) {\n // This is a workaround for the fact that ComboBox does not automatically\n // highlight first list item when items have been populated dynamically.\n // This has been raised as a bug.\n //TODO this is failing to work correctly in new version of cypress\n dispatchKeyboardEvent(inputRef.current, \"keydown\", \"ArrowUp\");\n }\n }\n pendingListFocusRef.current = false;\n })\n .catch((err) => {\n console.error(\"Error getting suggestions\", err);\n });\n } else {\n setTypeaheadValues([]);\n }\n }\n }, [\n table,\n column,\n getSuggestions,\n value,\n NO_FREE_TEXT,\n minCharacterCountToTriggerSuggestions,\n ]);\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = useCallback(\n (evt) => {\n const { value: newValue } = evt.target;\n const { current: value } = valueRef;\n if (value === \"\" && newValue) {\n setOpen(true);\n const input = rootRef.current?.querySelector(\"input\");\n if (input && highlightFirstSuggestion) {\n pendingListFocusRef.current = true;\n }\n } else if (newValue === \"\" && value) {\n // treat clear value as a commit event\n onCommit(evt, \"\");\n }\n setValue(newValue);\n },\n [highlightFirstSuggestion, onCommit, setValue, valueRef],\n );\n\n const handleSelectionChange = (\n evt: SyntheticEvent,\n [newSelected]: string[],\n ) => {\n if (commitTimeout.current) {\n clearTimeout(commitTimeout.current);\n commitTimeout.current = null;\n }\n setValue(newSelected);\n onCommit(\n evt as SyntheticEvent<HTMLInputElement>,\n newSelected,\n \"typeahead-suggestion\",\n );\n };\n\n const handleOpenChange = (newOpen: boolean) => {\n if (newOpen && valueRef.current === \"\") {\n // ignore this, don't open dropdown unless user has typed at least one character\n setOpen(newOpen);\n } else {\n setOpen(newOpen);\n }\n };\n\n const inputProps: ComponentPropsWithoutRef<\"input\"> = {\n ...inputPropsProp,\n autoComplete: \"off\",\n };\n\n const [noFreeText] = NO_FREE_TEXT;\n return {\n inputProps,\n noFreeText,\n onChange: handleChange,\n onKeyDown: handleKeyDown,\n onOpenChange: handleOpenChange,\n onSelectionChange: handleSelectionChange,\n open,\n ref: callbackRef,\n typeaheadValues,\n value: valueRef.current,\n };\n};\n"],"names":["useMemo","useStateRef","useState","useRef","useTypeaheadSuggestions","useCallback","value","useEffect","getVuuTable","NO_DATA_MATCH","dispatchKeyboardEvent"],"mappings":";;;;;;AAwBA,MAAM,2BAA8B,GAAA,CAAC,KAAe,EAAA,SAAA,KAClD,MAAM,MAAU,IAAA,SAAA;AAoClB,MAAM,sBACJ,GAAA,uMAAA;AAEK,MAAM,uBAAuB,CAAC;AAAA,EACnC,cAAiB,GAAA,IAAA;AAAA,EACjB,MAAA;AAAA,EACA,eAAA;AAAA,EACA,wBAA2B,GAAA,IAAA;AAAA,EAC3B,UAAY,EAAA,cAAA;AAAA,EACZ,qCAAwC,GAAA,CAAA;AAAA,EACxC,QAAA;AAAA,EACA;AACF,CAAkC,KAAA;AAChC,EAAA,MAAM,YAAe,GAAAA,aAAA;AAAA,IACnB,MAAM,CAAC,eAAA,IAAmB,sBAAsB,CAAA;AAAA,IAChD,CAAC,eAAe;AAAA,GAClB;AACA,EAAA,MAAM,CAAC,QAAA,EAAU,QAAQ,CAAA,GAAIC,qBAAY,EAAE,CAAA;AAC3C,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIC,eAAS,KAAK,CAAA;AACtC,EAAM,MAAA,QAAA,GAAWC,aAAgC,IAAI,CAAA;AACrD,EAAM,MAAA,OAAA,GAAUA,aAA8B,IAAI,CAAA;AAClD,EAAA,MAAM,CAAC,eAAiB,EAAA,kBAAkB,CAAI,GAAAD,cAAA,CAAmB,EAAE,CAAA;AACnE,EAAA,MAAM,iBAAiBE,oCAAwB,EAAA;AAC/C,EAAM,MAAA,mBAAA,GAAsBD,aAAO,KAAK,CAAA;AAExC,EAAM,MAAA,EAAE,OAAS,EAAA,KAAA,EAAU,GAAA,QAAA;AAC3B,EAAM,MAAA,aAAA,GAAgBA,aAA6C,IAAI,CAAA;AAEvE,EAAA,MAAM,aAAgB,GAAAE,iBAAA;AAAA,IACpB,CAAC,GAAQ,KAAA;AACP,MAAM,MAAA,EAAE,OAASC,EAAAA,MAAAA,EAAU,GAAA,QAAA;AAC3B,MAAA,IAAI,GAAI,CAAA,GAAA,KAAQ,OAAWA,IAAAA,MAAAA,KAAU,EAAI,EAAA;AACvC,QAAA,IAAI,cAAgB,EAAA;AAClB,UAAc,aAAA,CAAA,OAAA,GAAU,WAAW,MAAM;AACvC,YAAW,QAAA,GAAA,GAAA,EAAKA,QAAO,YAAY,CAAA;AACnC,YAAA,OAAA,CAAQ,KAAK,CAAA;AACb,YAAA,aAAA,CAAc,OAAU,GAAA,IAAA;AAAA,aACvB,GAAG,CAAA;AAAA,SACD,MAAA;AACL,UAAA,kBAAA,CAAmB,YAAY,CAAA;AAAA;AACjC,OACS,MAAA,IAAA,GAAA,CAAI,GAAQ,KAAA,OAAA,IAAWA,WAAU,EAAI,EAAA;AAC9C,QAAA,OAAA,CAAQ,IAAI,gBAAgB,CAAA;AAAA;AAC9B,KACF;AAAA,IACA,CAAC,YAAA,EAAc,cAAgB,EAAA,QAAA,EAAU,QAAQ;AAAA,GACnD;AAEA,EAAM,MAAA,WAAA,GAAcD,iBAAyC,CAAA,CAAC,EAAO,KAAA;AACnE,IAAA,OAAA,CAAQ,OAAU,GAAA,EAAA;AAClB,IAAA,MAAM,KAAQ,GAAA,EAAA,EAAI,aAAc,CAAA,OAAO,CAAK,IAAA,IAAA;AAC5C,IAAA,QAAA,CAAS,OAAU,GAAA,KAAA;AAAA,GACrB,EAAG,EAAE,CAAA;AAEL,EAAAE,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,KAAO,EAAA;AACT,MAAM,MAAA,QAAA,GAAWC,qBAAY,KAAK,CAAA;AAClC,MACE,IAAA,2BAAA;AAAA,QACE,KAAA;AAAA,QACA;AAAA,OAEF,EAAA;AACA,QAAM,MAAA,MAAA,GAA0B,QAC5B,CAAC,QAAA,EAAU,QAAQ,KAAK,CAAA,GACxB,CAAC,QAAA,EAAU,MAAM,CAAA;AACrB,QAAA,cAAA,CAAe,MAAM,CAAA,CAClB,IAAK,CAAA,CAAC,WAAgB,KAAA;AACrB,UAAQ,OAAA,CAAA,GAAA,CAAI,EAAE,WAAA,EAAa,CAAA;AAC3B,UAAA,IAAI,gBAAgB,KAAO,EAAA;AAEzB,YAAA,kBAAA,CAAmB,EAAE,CAAA;AAAA,WACZ,MAAA,IAAA,WAAA,CAAY,MAAW,KAAA,CAAA,IAAK,KAAO,EAAA;AAC5C,YAAA,kBAAA;AAAA,cAAmB,CAAC,MAAA;AAAA;AAAA,gBAElB,MAAA,KAAW,eAAe,YAAe,GAAAC;AAAA;AAAA,aAC3C;AAAA,WACK,MAAA;AACL,YAAA,kBAAA,CAAmB,WAAW,CAAA;AAC9B,YAAI,IAAA,mBAAA,CAAoB,OAAW,IAAA,QAAA,CAAS,OAAS,EAAA;AAKnD,cAAsBC,8BAAA,CAAA,QAAA,CAAS,OAAS,EAAA,SAAA,EAAW,SAAS,CAAA;AAAA;AAC9D;AAEF,UAAA,mBAAA,CAAoB,OAAU,GAAA,KAAA;AAAA,SAC/B,CAAA,CACA,KAAM,CAAA,CAAC,GAAQ,KAAA;AACd,UAAQ,OAAA,CAAA,KAAA,CAAM,6BAA6B,GAAG,CAAA;AAAA,SAC/C,CAAA;AAAA,OACE,MAAA;AACL,QAAA,kBAAA,CAAmB,EAAE,CAAA;AAAA;AACvB;AACF,GACC,EAAA;AAAA,IACD,KAAA;AAAA,IACA,MAAA;AAAA,IACA,cAAA;AAAA,IACA,KAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,YAAqD,GAAAL,iBAAA;AAAA,IACzD,CAAC,GAAQ,KAAA;AACP,MAAA,MAAM,EAAE,KAAA,EAAO,QAAS,EAAA,GAAI,GAAI,CAAA,MAAA;AAChC,MAAM,MAAA,EAAE,OAASC,EAAAA,MAAAA,EAAU,GAAA,QAAA;AAC3B,MAAIA,IAAAA,MAAAA,KAAU,MAAM,QAAU,EAAA;AAC5B,QAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,QAAA,MAAM,KAAQ,GAAA,OAAA,CAAQ,OAAS,EAAA,aAAA,CAAc,OAAO,CAAA;AACpD,QAAA,IAAI,SAAS,wBAA0B,EAAA;AACrC,UAAA,mBAAA,CAAoB,OAAU,GAAA,IAAA;AAAA;AAChC,OACF,MAAA,IAAW,QAAa,KAAA,EAAA,IAAMA,MAAO,EAAA;AAEnC,QAAA,QAAA,CAAS,KAAK,EAAE,CAAA;AAAA;AAElB,MAAA,QAAA,CAAS,QAAQ,CAAA;AAAA,KACnB;AAAA,IACA,CAAC,wBAAA,EAA0B,QAAU,EAAA,QAAA,EAAU,QAAQ;AAAA,GACzD;AAEA,EAAA,MAAM,qBAAwB,GAAA,CAC5B,GACA,EAAA,CAAC,WAAW,CACT,KAAA;AACH,IAAA,IAAI,cAAc,OAAS,EAAA;AACzB,MAAA,YAAA,CAAa,cAAc,OAAO,CAAA;AAClC,MAAA,aAAA,CAAc,OAAU,GAAA,IAAA;AAAA;AAE1B,IAAA,QAAA,CAAS,WAAW,CAAA;AACpB,IAAA,QAAA;AAAA,MACE,GAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA,KACF;AAAA,GACF;AAEA,EAAM,MAAA,gBAAA,GAAmB,CAAC,OAAqB,KAAA;AAC7C,IAAI,IAAA,OAAA,IAAW,QAAS,CAAA,OAAA,KAAY,EAAI,EAAA;AAEtC,MAAA,OAAA,CAAQ,OAAO,CAAA;AAAA,KACV,MAAA;AACL,MAAA,OAAA,CAAQ,OAAO,CAAA;AAAA;AACjB,GACF;AAEA,EAAA,MAAM,UAAgD,GAAA;AAAA,IACpD,GAAG,cAAA;AAAA,IACH,YAAc,EAAA;AAAA,GAChB;AAEA,EAAM,MAAA,CAAC,UAAU,CAAI,GAAA,YAAA;AACrB,EAAO,OAAA;AAAA,IACL,UAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAU,EAAA,YAAA;AAAA,IACV,SAAW,EAAA,aAAA;AAAA,IACX,YAAc,EAAA,gBAAA;AAAA,IACd,iBAAmB,EAAA,qBAAA;AAAA,IACnB,IAAA;AAAA,IACA,GAAK,EAAA,WAAA;AAAA,IACL,eAAA;AAAA,IACA,OAAO,QAAS,CAAA;AAAA,GAClB;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"useVuuTypeaheadInput.js","sources":["../../../../packages/vuu-ui-controls/src/vuu-typeahead-input/useVuuTypeaheadInput.ts"],"sourcesContent":["import { PillInputProps } from \"@salt-ds/core/dist-types/pill-input\";\nimport { useTypeaheadSuggestions } from \"@vuu-ui/vuu-data-react\";\nimport { TableSchemaTable } from \"@vuu-ui/vuu-data-types\";\nimport type { TypeaheadParams } from \"@vuu-ui/vuu-protocol-types\";\nimport {\n dispatchKeyboardEvent,\n getVuuTable,\n useStateRef,\n NO_DATA_MATCH,\n type CommitHandler,\n} from \"@vuu-ui/vuu-utils\";\nimport {\n ComponentPropsWithoutRef,\n FocusEventHandler,\n KeyboardEventHandler,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ChangeEventHandler,\n type RefCallback,\n type SyntheticEvent,\n} from \"react\";\n\nconst meetsMinTextLengthThreshold = (value: string, minLength: number) =>\n value.length >= minLength;\n\nexport interface VuuTypeaheadInputHookProps {\n /**\n * Allows a text string to be submitted that does not match any suggestion\n * Defaults to true\n */\n allowFreeInput?: boolean;\n column: string;\n /**\n * A warning to display to the user if allowFreeText is false and they attempt\n * to commit text which does not match any suggestions. A default message will\n * be shown if not provided\n */\n freeTextWarning?: string;\n /**\n * When suggestions are displayed, should first option be highlighted ?\n * Highlighted option will be selected if Enter pressed. If this option\n * is not applied and no suggestion is highlighted, Enter will commit\n * current text. This will be desirable if filter operator will be\n * 'contains', not if filter operator will be '='.\n */\n highlightFirstSuggestion?: boolean;\n inputProps?: PillInputProps[\"inputProps\"];\n /**\n * If zero, suggestions will be shown even without any text input.\n * Suggestions will be displayed on click, or, if focused via keynoard,\n * on ArrowDown.\n * If n, where n > 0, then n characters must be typed before suggestion\n * list will be fetched.\n */\n minCharacterCountToTriggerSuggestions?: 0 | 1 | 2 | 3;\n onCommit: CommitHandler<HTMLInputElement>;\n table: TableSchemaTable;\n}\n\nconst defaultFreeTextWarning =\n \"Please select a value from the list of suggestions. If no suggestions match your text, then the value is not valid. If you believe this should be a valid value, please reach out to the support team\";\n\nexport const useVuuTypeaheadInput = ({\n allowFreeInput = true,\n column,\n freeTextWarning,\n highlightFirstSuggestion = true,\n inputProps: inputPropsProp,\n minCharacterCountToTriggerSuggestions = 1,\n onCommit,\n table,\n}: VuuTypeaheadInputHookProps) => {\n const NO_FREE_TEXT = useMemo(\n () => [freeTextWarning ?? defaultFreeTextWarning],\n [freeTextWarning],\n );\n const [valueRef, setValue] = useStateRef(\"\");\n const [open, setOpen] = useState(false);\n const inputRef = useRef<HTMLInputElement | null>(null);\n const rootRef = useRef<HTMLDivElement | null>(null);\n const [typeaheadValues, setTypeaheadValues] = useState<string[]>([]);\n const getSuggestions = useTypeaheadSuggestions();\n const pendingListFocusRef = useRef(false);\n\n const { current: value } = valueRef;\n\n useMemo(() => {\n console.log(\n `[useVuuTypeaheadInput] inputProps value has changed ${inputPropsProp?.value} valueRef value ${valueRef.current}`,\n );\n if (\n inputPropsProp?.value !== undefined &&\n inputPropsProp?.value !== valueRef.current\n ) {\n setValue(`${inputPropsProp.value}`);\n }\n }, [inputPropsProp?.value, setValue, valueRef]);\n\n const commitTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const handleKeyDown = useCallback<KeyboardEventHandler<HTMLInputElement>>(\n (evt) => {\n const { current: value } = valueRef;\n if (evt.key === \"Enter\" && value !== \"\") {\n if (allowFreeInput) {\n commitTimeout.current = setTimeout(() => {\n onCommit?.(evt, value, \"text-input\");\n setOpen(false);\n commitTimeout.current = null;\n }, 200);\n } else {\n setTypeaheadValues(NO_FREE_TEXT);\n }\n } else if (evt.key === \"Enter\" && value === \"\") {\n console.log(\"ENTER no value\");\n }\n },\n [NO_FREE_TEXT, allowFreeInput, onCommit, valueRef],\n );\n\n const callbackRef = useCallback<RefCallback<HTMLDivElement>>((el) => {\n rootRef.current = el;\n const input = el?.querySelector(\"input\") ?? null;\n inputRef.current = input;\n }, []);\n\n const refreshSuggestions = useCallback(() => {\n if (table) {\n const vuuTable = getVuuTable(table);\n if (\n meetsMinTextLengthThreshold(\n value,\n minCharacterCountToTriggerSuggestions,\n )\n ) {\n const params: TypeaheadParams = value\n ? [vuuTable, column, value]\n : [vuuTable, column];\n getSuggestions(params)\n .then((suggestions) => {\n if (suggestions === false) {\n // TODO is this right\n setTypeaheadValues([]);\n } else if (suggestions.length === 0 && value) {\n setTypeaheadValues((values) =>\n // Do not update if we have already set suggestions to the no free text warning\n values === NO_FREE_TEXT ? NO_FREE_TEXT : NO_DATA_MATCH,\n );\n } else {\n setTypeaheadValues(suggestions);\n if (pendingListFocusRef.current && inputRef.current) {\n // This is a workaround for the fact that ComboBox does not automatically\n // highlight first list item when items have been populated dynamically.\n // This has been raised as a bug.\n //TODO this is failing to work correctly in new version of cypress\n dispatchKeyboardEvent(inputRef.current, \"keydown\", \"ArrowUp\");\n }\n }\n pendingListFocusRef.current = false;\n })\n .catch((err) => {\n console.error(\"Error getting suggestions\", err);\n });\n } else {\n setTypeaheadValues([]);\n }\n }\n }, [\n NO_FREE_TEXT,\n column,\n getSuggestions,\n minCharacterCountToTriggerSuggestions,\n table,\n value,\n ]);\n\n useEffect(() => {\n // This will preload suggestions for controls with no char input minimum\n refreshSuggestions();\n }, [refreshSuggestions]);\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = useCallback(\n (evt) => {\n const { value: newValue } = evt.target;\n const { current: value } = valueRef;\n if (value === \"\" && newValue) {\n setOpen(true);\n const input = rootRef.current?.querySelector(\"input\");\n if (input && highlightFirstSuggestion) {\n pendingListFocusRef.current = true;\n }\n } else if (newValue === \"\" && value) {\n // treat clear value as a commit event\n onCommit(evt, \"\");\n }\n setValue(newValue);\n },\n [highlightFirstSuggestion, onCommit, setValue, valueRef],\n );\n\n const handleSelectionChange = (\n evt: SyntheticEvent,\n [newSelected]: string[],\n ) => {\n if (commitTimeout.current) {\n clearTimeout(commitTimeout.current);\n commitTimeout.current = null;\n }\n setValue(newSelected);\n onCommit(\n evt as SyntheticEvent<HTMLInputElement>,\n newSelected,\n \"typeahead-suggestion\",\n );\n };\n\n const handleOpenChange = (newOpen: boolean) => {\n if (newOpen && valueRef.current === \"\") {\n // ignore this, don't open dropdown unless user has typed at least one character\n setOpen(newOpen);\n } else {\n setOpen(newOpen);\n }\n };\n\n const handleInputFocus = useCallback<FocusEventHandler<HTMLInputElement>>(\n (e) => {\n inputPropsProp?.onFocus?.(e);\n refreshSuggestions();\n },\n [inputPropsProp, refreshSuggestions],\n );\n\n const inputProps: ComponentPropsWithoutRef<\"input\"> = {\n ...inputPropsProp,\n autoComplete: \"off\",\n onFocus: handleInputFocus,\n };\n\n const [noFreeText] = NO_FREE_TEXT;\n return {\n inputProps,\n noFreeText,\n onChange: handleChange,\n onKeyDown: handleKeyDown,\n onOpenChange: handleOpenChange,\n onSelectionChange: handleSelectionChange,\n open,\n ref: callbackRef,\n typeaheadValues,\n value: valueRef.current,\n };\n};\n"],"names":["useMemo","useStateRef","useState","useRef","useTypeaheadSuggestions","useCallback","value","getVuuTable","NO_DATA_MATCH","dispatchKeyboardEvent","useEffect"],"mappings":"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"}
|
|
@@ -29,24 +29,22 @@ const ContextPanelProvider = ({
|
|
|
29
29
|
}, []);
|
|
30
30
|
const hideContextPanel = hideContextPanelProp ?? inheritedHideContextPanel;
|
|
31
31
|
const showContextPanel = useCallback(
|
|
32
|
-
(
|
|
32
|
+
(elementOrComponentType, title, props) => {
|
|
33
33
|
if (showContextPanelProp) {
|
|
34
|
-
showContextPanelProp(
|
|
34
|
+
showContextPanelProp(elementOrComponentType, title, props);
|
|
35
35
|
} else if (inheritedShowContextPanel !== UndefinedShowContextPanel) {
|
|
36
|
-
inheritedShowContextPanel(
|
|
36
|
+
inheritedShowContextPanel(elementOrComponentType, title, props);
|
|
37
37
|
} else if (!isUnconfiguredProperty(showComponentInContextPanel)) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
} else {
|
|
43
|
-
const component = layoutFromJson(
|
|
38
|
+
const component = typeof elementOrComponentType === "string" ? { type: elementOrComponentType, props } : elementOrComponentType;
|
|
39
|
+
showComponentInContextPanel(component, title);
|
|
40
|
+
} else if (typeof elementOrComponentType === "string") {
|
|
41
|
+
const component = typeof elementOrComponentType === "string" ? layoutFromJson(
|
|
44
42
|
{
|
|
45
|
-
type:
|
|
43
|
+
type: elementOrComponentType,
|
|
46
44
|
props
|
|
47
45
|
},
|
|
48
46
|
""
|
|
49
|
-
);
|
|
47
|
+
) : elementOrComponentType;
|
|
50
48
|
setDialog(
|
|
51
49
|
/* @__PURE__ */ jsxs(Dialog, { open: true, onOpenChange: handleOpenChange, children: [
|
|
52
50
|
/* @__PURE__ */ jsx(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextPanelProvider.js","sources":["../../../../packages/vuu-ui-controls/src/context-panel-provider/ContextPanelProvider.tsx"],"sourcesContent":["import {\n createContext,\n ReactElement,\n ReactNode,\n useCallback,\n useContext,\n useState,\n} from \"react\";\nimport {\n isUnconfiguredProperty,\n layoutFromJson,\n useLayoutOperation,\n} from \"@vuu-ui/vuu-layout\";\nimport { LayoutJSON } from \"@vuu-ui/vuu-utils\";\nimport {\n Dialog,\n DialogCloseButton,\n DialogContent,\n DialogHeader,\n} from \"@salt-ds/core\";\n\nexport type ShowContextPanel = (\n
|
|
1
|
+
{"version":3,"file":"ContextPanelProvider.js","sources":["../../../../packages/vuu-ui-controls/src/context-panel-provider/ContextPanelProvider.tsx"],"sourcesContent":["import React, {\n createContext,\n ReactElement,\n ReactNode,\n useCallback,\n useContext,\n useState,\n} from \"react\";\nimport {\n isUnconfiguredProperty,\n layoutFromJson,\n useLayoutOperation,\n} from \"@vuu-ui/vuu-layout\";\nimport { LayoutJSON } from \"@vuu-ui/vuu-utils\";\nimport {\n Dialog,\n DialogCloseButton,\n DialogContent,\n DialogHeader,\n} from \"@salt-ds/core\";\n\n/**\n * If component is a string, the component will be read from the\n * comoponent registry. In that case, componentProps can be used\n * to pass props to the component.\n */\nexport type ShowContextPanel = (\n component: string | ReactElement,\n title: string,\n componentProps?: unknown,\n) => void;\n\nexport interface ContextPanelProps {\n hideContextPanel?: () => void;\n showContextPanel: ShowContextPanel;\n}\n\nconst UndefinedShowContextPanel = () => {\n console.warn(\n \"[ContextPanelContext] no implementation for showContextPanel, you need to add a ContextPanelProvider\",\n );\n};\n\nexport const ContextPanelContext = createContext<ContextPanelProps>({\n showContextPanel: UndefinedShowContextPanel,\n});\n\nexport const ContextPanelProvider = ({\n children,\n hideContextPanel: hideContextPanelProp,\n showContextPanel: showContextPanelProp,\n}: Partial<ContextPanelProps> & {\n children: ReactNode;\n}) => {\n const {\n hideContextPanel: inheritedHideContextPanel,\n showContextPanel: inheritedShowContextPanel,\n } = useContext(ContextPanelContext);\n const { showComponentInContextPanel } = useLayoutOperation();\n const [dialog, setDialog] = useState<ReactElement | null>(null);\n\n const handleOpenChange = useCallback((isOpen: boolean) => {\n if (!isOpen) {\n setDialog(null);\n }\n }, []);\n\n const hideContextPanel = hideContextPanelProp ?? inheritedHideContextPanel;\n\n const showContextPanel = useCallback<ShowContextPanel>(\n (elementOrComponentType, title, props) => {\n if (showContextPanelProp) {\n showContextPanelProp(elementOrComponentType, title, props);\n } else if (inheritedShowContextPanel !== UndefinedShowContextPanel) {\n inheritedShowContextPanel(elementOrComponentType, title, props);\n } else if (!isUnconfiguredProperty(showComponentInContextPanel)) {\n const component =\n typeof elementOrComponentType === \"string\"\n ? ({ type: elementOrComponentType, props } as LayoutJSON)\n : elementOrComponentType;\n showComponentInContextPanel(component, title);\n } else if (typeof elementOrComponentType === \"string\") {\n const component =\n typeof elementOrComponentType === \"string\"\n ? layoutFromJson(\n {\n type: elementOrComponentType,\n props,\n } as LayoutJSON,\n \"\",\n )\n : elementOrComponentType;\n\n setDialog(\n <Dialog open={true} onOpenChange={handleOpenChange}>\n <DialogCloseButton\n appearance=\"transparent\"\n data-embedded\n data-icon=\"close\"\n onClick={() => setDialog(null)}\n sentiment=\"neutral\"\n />\n <DialogHeader header={title} />\n <DialogContent>{component}</DialogContent>\n </Dialog>,\n );\n }\n },\n [\n handleOpenChange,\n inheritedShowContextPanel,\n showComponentInContextPanel,\n showContextPanelProp,\n ],\n );\n\n return (\n <ContextPanelContext.Provider\n value={{ hideContextPanel, showContextPanel }}\n >\n {children}\n {dialog}\n </ContextPanelContext.Provider>\n );\n};\n\nexport function useContextPanel() {\n const { showContextPanel } = useContext(ContextPanelContext);\n return showContextPanel;\n}\n\nexport function useHideContextPanel() {\n const { hideContextPanel } = useContext(ContextPanelContext);\n return hideContextPanel;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -94,9 +94,13 @@ const useTimeInput = ({
|
|
|
94
94
|
const handleMouseDown = useCallback(() => {
|
|
95
95
|
mousedDownRef.current = true;
|
|
96
96
|
}, []);
|
|
97
|
-
const handleMouseUp = useCallback(
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
const handleMouseUp = useCallback(
|
|
98
|
+
(e) => {
|
|
99
|
+
e.preventDefault();
|
|
100
|
+
maskedInputRef.current?.click();
|
|
101
|
+
},
|
|
102
|
+
[]
|
|
103
|
+
);
|
|
100
104
|
return {
|
|
101
105
|
inputRef: setInputEl,
|
|
102
106
|
eventHandlers: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTimeInput.js","sources":["../../../../packages/vuu-ui-controls/src/time-input/useTimeInput.ts"],"sourcesContent":["import {\n type CommitHandler,\n DateStringISO,\n isValidTimeString,\n type TimeString,\n} from \"@vuu-ui/vuu-utils\";\nimport {\n ChangeEvent,\n ChangeEventHandler,\n ClipboardEventHandler,\n FocusEventHandler,\n KeyboardEventHandler,\n MouseEventHandler,\n RefCallback,\n useCallback,\n useMemo,\n useRef,\n} from \"react\";\nimport { Digit, MaskedInput } from \"./MaskedInput\";\n\nconst isDigit = (char: string): char is Digit =>\n char.length === 1 && /[0-9]/.test(char);\n\nexport interface TimeInputHookProps {\n date?: Date | DateStringISO;\n defaultValue?: TimeString;\n onChange?: ChangeEventHandler<HTMLInputElement>;\n onCommit: CommitHandler<HTMLInputElement, TimeString>;\n value?: TimeString;\n}\n\nexport const useTimeInput = ({\n defaultValue,\n onChange,\n onCommit,\n value,\n}: TimeInputHookProps) => {\n const mousedDownRef = useRef(false);\n const maskedInputRef = useRef<MaskedInput | undefined>(undefined);\n useMemo(() => {\n if (maskedInputRef.current === undefined) {\n maskedInputRef.current = new MaskedInput(defaultValue, null);\n maskedInputRef.current.on(\n \"change\",\n (e: ChangeEvent<HTMLInputElement>) => {\n onChange?.(e);\n },\n );\n }\n\n if (value && value !== maskedInputRef.current.value) {\n maskedInputRef.current.value = value;\n }\n }, [defaultValue, onChange, value]);\n\n const setInputEl = useCallback<RefCallback<HTMLInputElement>>((el) => {\n if (el && maskedInputRef.current) {\n maskedInputRef.current.input = el;\n }\n }, []);\n const back = useRef(false);\n\n const commitValue = useCallback<CommitHandler<HTMLInputElement, string>>(\n (evt, value) => {\n if (isValidTimeString(value)) {\n onCommit(evt, value, \"text-input\");\n } else if (value === \"hh:mm:ss\") {\n console.log(\"no value set\");\n } else {\n console.log(`value is not valid`);\n }\n },\n [onCommit],\n );\n\n const handleKeyDown = useCallback<KeyboardEventHandler<HTMLInputElement>>(\n (e) => {\n const { current: maskedInput } = maskedInputRef;\n if (maskedInput) {\n if (e.key === \"Backspace\") {\n maskedInput.backspace();\n back.current = true;\n } else if (isDigit(e.key)) {\n maskedInput.update(e.key);\n } else if (e.key === \"ArrowLeft\") {\n maskedInput.moveFocus(\"left\");\n } else if (e.key === \"ArrowRight\") {\n maskedInput.moveFocus(\"right\");\n } else if (e.key === \"ArrowUp\") {\n maskedInput.incrementValue();\n } else if (e.key === \"ArrowDown\") {\n maskedInput.decrementValue();\n } else if (e.key === \"v\" && e.metaKey) {\n // keyboard paste, do not prevent default\n return;\n } else if (e.key === \"Tab\") {\n return;\n } else if (e.key === \"Enter\") {\n commitValue(e, maskedInput.value);\n }\n }\n e.preventDefault();\n },\n [commitValue],\n );\n\n const handleDoubleClick = useCallback(() => {\n maskedInputRef.current?.doubleClick();\n }, []);\n\n const handlePaste = useCallback<ClipboardEventHandler<HTMLInputElement>>(\n (e) => {\n const value = e.clipboardData.getData(\"text\");\n if (isValidTimeString(value)) {\n maskedInputRef.current?.pasteValue(value);\n }\n },\n [],\n );\n\n const handleFocus = useCallback<FocusEventHandler<HTMLInputElement>>(() => {\n // If keboard has been used, how do we detect SHIFT + TAB\n if (mousedDownRef.current) {\n mousedDownRef.current = false;\n } else {\n maskedInputRef.current?.focus();\n }\n }, []);\n\n const handleMouseDown = useCallback<MouseEventHandler>(() => {\n mousedDownRef.current = true;\n }, []);\n\n const handleMouseUp = useCallback<MouseEventHandler<HTMLInputElement>>(() => {\n
|
|
1
|
+
{"version":3,"file":"useTimeInput.js","sources":["../../../../packages/vuu-ui-controls/src/time-input/useTimeInput.ts"],"sourcesContent":["import {\n type CommitHandler,\n DateStringISO,\n isValidTimeString,\n type TimeString,\n} from \"@vuu-ui/vuu-utils\";\nimport {\n ChangeEvent,\n ChangeEventHandler,\n ClipboardEventHandler,\n FocusEventHandler,\n KeyboardEventHandler,\n MouseEventHandler,\n RefCallback,\n useCallback,\n useMemo,\n useRef,\n} from \"react\";\nimport { Digit, MaskedInput } from \"./MaskedInput\";\n\nconst isDigit = (char: string): char is Digit =>\n char.length === 1 && /[0-9]/.test(char);\n\nexport interface TimeInputHookProps {\n date?: Date | DateStringISO;\n defaultValue?: TimeString;\n onChange?: ChangeEventHandler<HTMLInputElement>;\n onCommit: CommitHandler<HTMLInputElement, TimeString>;\n value?: TimeString;\n}\n\nexport const useTimeInput = ({\n defaultValue,\n onChange,\n onCommit,\n value,\n}: TimeInputHookProps) => {\n const mousedDownRef = useRef(false);\n const maskedInputRef = useRef<MaskedInput | undefined>(undefined);\n useMemo(() => {\n if (maskedInputRef.current === undefined) {\n maskedInputRef.current = new MaskedInput(defaultValue, null);\n maskedInputRef.current.on(\n \"change\",\n (e: ChangeEvent<HTMLInputElement>) => {\n onChange?.(e);\n },\n );\n }\n\n if (value && value !== maskedInputRef.current.value) {\n maskedInputRef.current.value = value;\n }\n }, [defaultValue, onChange, value]);\n\n const setInputEl = useCallback<RefCallback<HTMLInputElement>>((el) => {\n if (el && maskedInputRef.current) {\n maskedInputRef.current.input = el;\n }\n }, []);\n const back = useRef(false);\n\n const commitValue = useCallback<CommitHandler<HTMLInputElement, string>>(\n (evt, value) => {\n if (isValidTimeString(value)) {\n onCommit(evt, value, \"text-input\");\n } else if (value === \"hh:mm:ss\") {\n console.log(\"no value set\");\n } else {\n console.log(`value is not valid`);\n }\n },\n [onCommit],\n );\n\n const handleKeyDown = useCallback<KeyboardEventHandler<HTMLInputElement>>(\n (e) => {\n const { current: maskedInput } = maskedInputRef;\n if (maskedInput) {\n if (e.key === \"Backspace\") {\n maskedInput.backspace();\n back.current = true;\n } else if (isDigit(e.key)) {\n maskedInput.update(e.key);\n } else if (e.key === \"ArrowLeft\") {\n maskedInput.moveFocus(\"left\");\n } else if (e.key === \"ArrowRight\") {\n maskedInput.moveFocus(\"right\");\n } else if (e.key === \"ArrowUp\") {\n maskedInput.incrementValue();\n } else if (e.key === \"ArrowDown\") {\n maskedInput.decrementValue();\n } else if (e.key === \"v\" && e.metaKey) {\n // keyboard paste, do not prevent default\n return;\n } else if (e.key === \"Tab\") {\n return;\n } else if (e.key === \"Enter\") {\n commitValue(e, maskedInput.value);\n }\n }\n e.preventDefault();\n },\n [commitValue],\n );\n\n const handleDoubleClick = useCallback(() => {\n maskedInputRef.current?.doubleClick();\n }, []);\n\n const handlePaste = useCallback<ClipboardEventHandler<HTMLInputElement>>(\n (e) => {\n const value = e.clipboardData.getData(\"text\");\n if (isValidTimeString(value)) {\n maskedInputRef.current?.pasteValue(value);\n }\n },\n [],\n );\n\n const handleFocus = useCallback<FocusEventHandler<HTMLInputElement>>(() => {\n // If keboard has been used, how do we detect SHIFT + TAB\n if (mousedDownRef.current) {\n mousedDownRef.current = false;\n } else {\n maskedInputRef.current?.focus();\n }\n }, []);\n\n const handleMouseDown = useCallback<MouseEventHandler>(() => {\n mousedDownRef.current = true;\n }, []);\n\n const handleMouseUp = useCallback<MouseEventHandler<HTMLInputElement>>(\n (e) => {\n e.preventDefault();\n maskedInputRef.current?.click();\n },\n [],\n );\n\n return {\n inputRef: setInputEl,\n eventHandlers: {\n onBlur: maskedInputRef.current?.blur,\n onDoubleClick: handleDoubleClick,\n onFocus: handleFocus,\n onKeyDown: handleKeyDown,\n onMouseDown: handleMouseDown,\n onMouseUp: handleMouseUp,\n onPaste: handlePaste,\n },\n };\n};\n"],"names":["value"],"mappings":";;;;AAoBA,MAAM,OAAA,GAAU,CAAC,IACf,KAAA,IAAA,CAAK,WAAW,CAAK,IAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AAUjC,MAAM,eAAe,CAAC;AAAA,EAC3B,YAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAA0B,KAAA;AACxB,EAAM,MAAA,aAAA,GAAgB,OAAO,KAAK,CAAA;AAClC,EAAM,MAAA,cAAA,GAAiB,OAAgC,KAAS,CAAA,CAAA;AAChE,EAAA,OAAA,CAAQ,MAAM;AACZ,IAAI,IAAA,cAAA,CAAe,YAAY,KAAW,CAAA,EAAA;AACxC,MAAA,cAAA,CAAe,OAAU,GAAA,IAAI,WAAY,CAAA,YAAA,EAAc,IAAI,CAAA;AAC3D,MAAA,cAAA,CAAe,OAAQ,CAAA,EAAA;AAAA,QACrB,QAAA;AAAA,QACA,CAAC,CAAqC,KAAA;AACpC,UAAA,QAAA,GAAW,CAAC,CAAA;AAAA;AACd,OACF;AAAA;AAGF,IAAA,IAAI,KAAS,IAAA,KAAA,KAAU,cAAe,CAAA,OAAA,CAAQ,KAAO,EAAA;AACnD,MAAA,cAAA,CAAe,QAAQ,KAAQ,GAAA,KAAA;AAAA;AACjC,GACC,EAAA,CAAC,YAAc,EAAA,QAAA,EAAU,KAAK,CAAC,CAAA;AAElC,EAAM,MAAA,UAAA,GAAa,WAA2C,CAAA,CAAC,EAAO,KAAA;AACpE,IAAI,IAAA,EAAA,IAAM,eAAe,OAAS,EAAA;AAChC,MAAA,cAAA,CAAe,QAAQ,KAAQ,GAAA,EAAA;AAAA;AACjC,GACF,EAAG,EAAE,CAAA;AACL,EAAM,MAAA,IAAA,GAAO,OAAO,KAAK,CAAA;AAEzB,EAAA,MAAM,WAAc,GAAA,WAAA;AAAA,IAClB,CAAC,KAAKA,MAAU,KAAA;AACd,MAAI,IAAA,iBAAA,CAAkBA,MAAK,CAAG,EAAA;AAC5B,QAAS,QAAA,CAAA,GAAA,EAAKA,QAAO,YAAY,CAAA;AAAA,OACnC,MAAA,IAAWA,WAAU,UAAY,EAAA;AAC/B,QAAA,OAAA,CAAQ,IAAI,cAAc,CAAA;AAAA,OACrB,MAAA;AACL,QAAA,OAAA,CAAQ,IAAI,CAAoB,kBAAA,CAAA,CAAA;AAAA;AAClC,KACF;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AAEA,EAAA,MAAM,aAAgB,GAAA,WAAA;AAAA,IACpB,CAAC,CAAM,KAAA;AACL,MAAM,MAAA,EAAE,OAAS,EAAA,WAAA,EAAgB,GAAA,cAAA;AACjC,MAAA,IAAI,WAAa,EAAA;AACf,QAAI,IAAA,CAAA,CAAE,QAAQ,WAAa,EAAA;AACzB,UAAA,WAAA,CAAY,SAAU,EAAA;AACtB,UAAA,IAAA,CAAK,OAAU,GAAA,IAAA;AAAA,SACN,MAAA,IAAA,OAAA,CAAQ,CAAE,CAAA,GAAG,CAAG,EAAA;AACzB,UAAY,WAAA,CAAA,MAAA,CAAO,EAAE,GAAG,CAAA;AAAA,SAC1B,MAAA,IAAW,CAAE,CAAA,GAAA,KAAQ,WAAa,EAAA;AAChC,UAAA,WAAA,CAAY,UAAU,MAAM,CAAA;AAAA,SAC9B,MAAA,IAAW,CAAE,CAAA,GAAA,KAAQ,YAAc,EAAA;AACjC,UAAA,WAAA,CAAY,UAAU,OAAO,CAAA;AAAA,SAC/B,MAAA,IAAW,CAAE,CAAA,GAAA,KAAQ,SAAW,EAAA;AAC9B,UAAA,WAAA,CAAY,cAAe,EAAA;AAAA,SAC7B,MAAA,IAAW,CAAE,CAAA,GAAA,KAAQ,WAAa,EAAA;AAChC,UAAA,WAAA,CAAY,cAAe,EAAA;AAAA,SAClB,MAAA,IAAA,CAAA,CAAE,GAAQ,KAAA,GAAA,IAAO,EAAE,OAAS,EAAA;AAErC,UAAA;AAAA,SACF,MAAA,IAAW,CAAE,CAAA,GAAA,KAAQ,KAAO,EAAA;AAC1B,UAAA;AAAA,SACF,MAAA,IAAW,CAAE,CAAA,GAAA,KAAQ,OAAS,EAAA;AAC5B,UAAY,WAAA,CAAA,CAAA,EAAG,YAAY,KAAK,CAAA;AAAA;AAClC;AAEF,MAAA,CAAA,CAAE,cAAe,EAAA;AAAA,KACnB;AAAA,IACA,CAAC,WAAW;AAAA,GACd;AAEA,EAAM,MAAA,iBAAA,GAAoB,YAAY,MAAM;AAC1C,IAAA,cAAA,CAAe,SAAS,WAAY,EAAA;AAAA,GACtC,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,WAAc,GAAA,WAAA;AAAA,IAClB,CAAC,CAAM,KAAA;AACL,MAAA,MAAMA,MAAQ,GAAA,CAAA,CAAE,aAAc,CAAA,OAAA,CAAQ,MAAM,CAAA;AAC5C,MAAI,IAAA,iBAAA,CAAkBA,MAAK,CAAG,EAAA;AAC5B,QAAe,cAAA,CAAA,OAAA,EAAS,WAAWA,MAAK,CAAA;AAAA;AAC1C,KACF;AAAA,IACA;AAAC,GACH;AAEA,EAAM,MAAA,WAAA,GAAc,YAAiD,MAAM;AAEzE,IAAA,IAAI,cAAc,OAAS,EAAA;AACzB,MAAA,aAAA,CAAc,OAAU,GAAA,KAAA;AAAA,KACnB,MAAA;AACL,MAAA,cAAA,CAAe,SAAS,KAAM,EAAA;AAAA;AAChC,GACF,EAAG,EAAE,CAAA;AAEL,EAAM,MAAA,eAAA,GAAkB,YAA+B,MAAM;AAC3D,IAAA,aAAA,CAAc,OAAU,GAAA,IAAA;AAAA,GAC1B,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,aAAgB,GAAA,WAAA;AAAA,IACpB,CAAC,CAAM,KAAA;AACL,MAAA,CAAA,CAAE,cAAe,EAAA;AACjB,MAAA,cAAA,CAAe,SAAS,KAAM,EAAA;AAAA,KAChC;AAAA,IACA;AAAC,GACH;AAEA,EAAO,OAAA;AAAA,IACL,QAAU,EAAA,UAAA;AAAA,IACV,aAAe,EAAA;AAAA,MACb,MAAA,EAAQ,eAAe,OAAS,EAAA,IAAA;AAAA,MAChC,aAAe,EAAA,iBAAA;AAAA,MACf,OAAS,EAAA,WAAA;AAAA,MACT,SAAW,EAAA,aAAA;AAAA,MACX,WAAa,EAAA,eAAA;AAAA,MACb,SAAW,EAAA,aAAA;AAAA,MACX,OAAS,EAAA;AAAA;AACX,GACF;AACF;;;;"}
|
|
@@ -18,6 +18,7 @@ const VuuTypeaheadInput = ({
|
|
|
18
18
|
inputProps: inputPropsProp,
|
|
19
19
|
minCharacterCountToTriggerSuggestions,
|
|
20
20
|
onCommit,
|
|
21
|
+
selectOnTab,
|
|
21
22
|
table
|
|
22
23
|
}) => {
|
|
23
24
|
const targetWindow = useWindow();
|
|
@@ -58,6 +59,7 @@ const VuuTypeaheadInput = ({
|
|
|
58
59
|
onSelectionChange,
|
|
59
60
|
open,
|
|
60
61
|
ref,
|
|
62
|
+
selectOnTab,
|
|
61
63
|
value,
|
|
62
64
|
children: typeaheadValues.map((state) => /* @__PURE__ */ jsx(
|
|
63
65
|
Option,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VuuTypeaheadInput.js","sources":["../../../../packages/vuu-ui-controls/src/vuu-typeahead-input/VuuTypeaheadInput.tsx"],"sourcesContent":["import { ComboBox, Option } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { NO_DATA_MATCH } from \"@vuu-ui/vuu-utils\";\nimport cx from \"clsx\";\nimport {\n useVuuTypeaheadInput,\n VuuTypeaheadInputHookProps,\n} from \"./useVuuTypeaheadInput\";\nimport vuuTypeaheadInputCss from \"./VuuTypeaheadInput.css\";\n\nconst classBase = \"vuuTypeaheadInput\";\nconst [noMatchingData] = NO_DATA_MATCH;\n\nexport interface VuuTypeaheadInputProps
|
|
1
|
+
{"version":3,"file":"VuuTypeaheadInput.js","sources":["../../../../packages/vuu-ui-controls/src/vuu-typeahead-input/VuuTypeaheadInput.tsx"],"sourcesContent":["import { ComboBox, ComboBoxProps, Option } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { NO_DATA_MATCH } from \"@vuu-ui/vuu-utils\";\nimport cx from \"clsx\";\nimport {\n useVuuTypeaheadInput,\n VuuTypeaheadInputHookProps,\n} from \"./useVuuTypeaheadInput\";\nimport vuuTypeaheadInputCss from \"./VuuTypeaheadInput.css\";\n\nconst classBase = \"vuuTypeaheadInput\";\nconst [noMatchingData] = NO_DATA_MATCH;\n\nexport interface VuuTypeaheadInputProps\n extends VuuTypeaheadInputHookProps,\n Pick<ComboBoxProps, \"selectOnTab\"> {\n className?: string;\n}\n\nexport const VuuTypeaheadInput = ({\n allowFreeInput,\n className,\n column,\n freeTextWarning,\n highlightFirstSuggestion,\n inputProps: inputPropsProp,\n minCharacterCountToTriggerSuggestions,\n onCommit,\n selectOnTab,\n table,\n}: VuuTypeaheadInputProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-typeahead-input\",\n css: vuuTypeaheadInputCss,\n window: targetWindow,\n });\n\n const {\n inputProps,\n noFreeText,\n onChange,\n onKeyDown,\n onOpenChange,\n onSelectionChange,\n open,\n ref,\n typeaheadValues,\n value,\n } = useVuuTypeaheadInput({\n allowFreeInput,\n column,\n freeTextWarning,\n highlightFirstSuggestion,\n inputProps: inputPropsProp,\n minCharacterCountToTriggerSuggestions,\n onCommit,\n table,\n });\n\n // need latest version of salt combobox\n // const defaultHighlightedIndex =\n // highlightFirstSuggestion === false ? -1 : undefined;\n\n return (\n <ComboBox\n className={cx(classBase, className)}\n // defaultHighlightedIndex={defaultHighlightedIndex}\n inputProps={inputProps}\n onChange={onChange}\n onKeyDown={onKeyDown}\n onOpenChange={onOpenChange}\n onSelectionChange={onSelectionChange}\n open={open}\n ref={ref}\n selectOnTab={selectOnTab}\n value={value}\n >\n {typeaheadValues.map((state) => (\n <Option\n className=\"vuuTypeaheadOption\"\n value={state}\n key={state}\n disabled={state === noMatchingData || state === noFreeText}\n />\n ))}\n </ComboBox>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAWA,MAAM,SAAY,GAAA,mBAAA;AAClB,MAAM,CAAC,cAAc,CAAI,GAAA,aAAA;AAQlB,MAAM,oBAAoB,CAAC;AAAA,EAChC,cAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,eAAA;AAAA,EACA,wBAAA;AAAA,EACA,UAAY,EAAA,cAAA;AAAA,EACZ,qCAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAA8B,KAAA;AAC5B,EAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,EAAyB,wBAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,qBAAA;AAAA,IACR,GAAK,EAAA,oBAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GACT,CAAA;AAED,EAAM,MAAA;AAAA,IACJ,UAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA;AAAA,IACA,iBAAA;AAAA,IACA,IAAA;AAAA,IACA,GAAA;AAAA,IACA,eAAA;AAAA,IACA;AAAA,MACE,oBAAqB,CAAA;AAAA,IACvB,cAAA;AAAA,IACA,MAAA;AAAA,IACA,eAAA;AAAA,IACA,wBAAA;AAAA,IACA,UAAY,EAAA,cAAA;AAAA,IACZ,qCAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,GACD,CAAA;AAMD,EACE,uBAAA,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAG,CAAA,SAAA,EAAW,SAAS,CAAA;AAAA,MAElC,UAAA;AAAA,MACA,QAAA;AAAA,MACA,SAAA;AAAA,MACA,YAAA;AAAA,MACA,iBAAA;AAAA,MACA,IAAA;AAAA,MACA,GAAA;AAAA,MACA,WAAA;AAAA,MACA,KAAA;AAAA,MAEC,QAAA,EAAA,eAAA,CAAgB,GAAI,CAAA,CAAC,KACpB,qBAAA,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,SAAU,EAAA,oBAAA;AAAA,UACV,KAAO,EAAA,KAAA;AAAA,UAEP,QAAA,EAAU,KAAU,KAAA,cAAA,IAAkB,KAAU,KAAA;AAAA,SAAA;AAAA,QAD3C;AAAA,OAGR;AAAA;AAAA,GACH;AAEJ;;;;"}
|
|
@@ -26,6 +26,14 @@ const useVuuTypeaheadInput = ({
|
|
|
26
26
|
const getSuggestions = useTypeaheadSuggestions();
|
|
27
27
|
const pendingListFocusRef = useRef(false);
|
|
28
28
|
const { current: value } = valueRef;
|
|
29
|
+
useMemo(() => {
|
|
30
|
+
console.log(
|
|
31
|
+
`[useVuuTypeaheadInput] inputProps value has changed ${inputPropsProp?.value} valueRef value ${valueRef.current}`
|
|
32
|
+
);
|
|
33
|
+
if (inputPropsProp?.value !== void 0 && inputPropsProp?.value !== valueRef.current) {
|
|
34
|
+
setValue(`${inputPropsProp.value}`);
|
|
35
|
+
}
|
|
36
|
+
}, [inputPropsProp?.value, setValue, valueRef]);
|
|
29
37
|
const commitTimeout = useRef(null);
|
|
30
38
|
const handleKeyDown = useCallback(
|
|
31
39
|
(evt) => {
|
|
@@ -51,7 +59,7 @@ const useVuuTypeaheadInput = ({
|
|
|
51
59
|
const input = el?.querySelector("input") ?? null;
|
|
52
60
|
inputRef.current = input;
|
|
53
61
|
}, []);
|
|
54
|
-
|
|
62
|
+
const refreshSuggestions = useCallback(() => {
|
|
55
63
|
if (table) {
|
|
56
64
|
const vuuTable = getVuuTable(table);
|
|
57
65
|
if (meetsMinTextLengthThreshold(
|
|
@@ -60,7 +68,6 @@ const useVuuTypeaheadInput = ({
|
|
|
60
68
|
)) {
|
|
61
69
|
const params = value ? [vuuTable, column, value] : [vuuTable, column];
|
|
62
70
|
getSuggestions(params).then((suggestions) => {
|
|
63
|
-
console.log({ suggestions });
|
|
64
71
|
if (suggestions === false) {
|
|
65
72
|
setTypeaheadValues([]);
|
|
66
73
|
} else if (suggestions.length === 0 && value) {
|
|
@@ -85,13 +92,16 @@ const useVuuTypeaheadInput = ({
|
|
|
85
92
|
}
|
|
86
93
|
}
|
|
87
94
|
}, [
|
|
88
|
-
|
|
95
|
+
NO_FREE_TEXT,
|
|
89
96
|
column,
|
|
90
97
|
getSuggestions,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
98
|
+
minCharacterCountToTriggerSuggestions,
|
|
99
|
+
table,
|
|
100
|
+
value
|
|
94
101
|
]);
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
refreshSuggestions();
|
|
104
|
+
}, [refreshSuggestions]);
|
|
95
105
|
const handleChange = useCallback(
|
|
96
106
|
(evt) => {
|
|
97
107
|
const { value: newValue } = evt.target;
|
|
@@ -128,9 +138,17 @@ const useVuuTypeaheadInput = ({
|
|
|
128
138
|
setOpen(newOpen);
|
|
129
139
|
}
|
|
130
140
|
};
|
|
141
|
+
const handleInputFocus = useCallback(
|
|
142
|
+
(e) => {
|
|
143
|
+
inputPropsProp?.onFocus?.(e);
|
|
144
|
+
refreshSuggestions();
|
|
145
|
+
},
|
|
146
|
+
[inputPropsProp, refreshSuggestions]
|
|
147
|
+
);
|
|
131
148
|
const inputProps = {
|
|
132
149
|
...inputPropsProp,
|
|
133
|
-
autoComplete: "off"
|
|
150
|
+
autoComplete: "off",
|
|
151
|
+
onFocus: handleInputFocus
|
|
134
152
|
};
|
|
135
153
|
const [noFreeText] = NO_FREE_TEXT;
|
|
136
154
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useVuuTypeaheadInput.js","sources":["../../../../packages/vuu-ui-controls/src/vuu-typeahead-input/useVuuTypeaheadInput.ts"],"sourcesContent":["import { PillInputProps } from \"@salt-ds/core/dist-types/pill-input\";\nimport { useTypeaheadSuggestions } from \"@vuu-ui/vuu-data-react\";\nimport { TableSchemaTable } from \"@vuu-ui/vuu-data-types\";\nimport type { TypeaheadParams } from \"@vuu-ui/vuu-protocol-types\";\nimport {\n dispatchKeyboardEvent,\n getVuuTable,\n useStateRef,\n NO_DATA_MATCH,\n type CommitHandler,\n} from \"@vuu-ui/vuu-utils\";\nimport {\n ComponentPropsWithoutRef,\n KeyboardEventHandler,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ChangeEventHandler,\n type RefCallback,\n type SyntheticEvent,\n} from \"react\";\n\nconst meetsMinTextLengthThreshold = (value: string, minLength: number) =>\n value.length >= minLength;\n\nexport interface VuuTypeaheadInputHookProps {\n /**\n * Allows a text string to be submitted that does not match any suggestion\n * Defaults to true\n */\n allowFreeInput?: boolean;\n column: string;\n /**\n * A warning to display to the user if allowFreeText is false and they attempt\n * to commit text which does not match any suggestions. A default message will\n * be shown if not provided\n */\n freeTextWarning?: string;\n /**\n * When suggestions are displayed, should first option be highlighted ?\n * Highlighted option will be selected if Enter pressed. If this option\n * is not applied and no suggestion is highlighted, Enter will commit\n * current text. This will be desirable if filter operator will be\n * 'contains', not if filter operator will be '='.\n */\n highlightFirstSuggestion?: boolean;\n inputProps?: PillInputProps[\"inputProps\"];\n /**\n * If zero, suggestions will be shown even without any text input.\n * Suggestions will be displayed on click, or, if focused via keynoard,\n * on ArrowDown.\n * If n, where n > 0, then n characters must be typed before suggestion\n * list will be fetched.\n */\n minCharacterCountToTriggerSuggestions?: 0 | 1 | 2 | 3;\n onCommit: CommitHandler<HTMLInputElement>;\n table: TableSchemaTable;\n}\n\nconst defaultFreeTextWarning =\n \"Please select a value from the list of suggestions. If no suggestions match your text, then the value is not valid. If you believe this should be a valid value, please reach out to the support team\";\n\nexport const useVuuTypeaheadInput = ({\n allowFreeInput = true,\n column,\n freeTextWarning,\n highlightFirstSuggestion = true,\n inputProps: inputPropsProp,\n minCharacterCountToTriggerSuggestions = 1,\n onCommit,\n table,\n}: VuuTypeaheadInputHookProps) => {\n const NO_FREE_TEXT = useMemo(\n () => [freeTextWarning ?? defaultFreeTextWarning],\n [freeTextWarning],\n );\n const [valueRef, setValue] = useStateRef(\"\");\n const [open, setOpen] = useState(false);\n const inputRef = useRef<HTMLInputElement | null>(null);\n const rootRef = useRef<HTMLDivElement | null>(null);\n const [typeaheadValues, setTypeaheadValues] = useState<string[]>([]);\n const getSuggestions = useTypeaheadSuggestions();\n const pendingListFocusRef = useRef(false);\n\n const { current: value } = valueRef;\n const commitTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const handleKeyDown = useCallback<KeyboardEventHandler<HTMLInputElement>>(\n (evt) => {\n const { current: value } = valueRef;\n if (evt.key === \"Enter\" && value !== \"\") {\n if (allowFreeInput) {\n commitTimeout.current = setTimeout(() => {\n onCommit?.(evt, value, \"text-input\");\n setOpen(false);\n commitTimeout.current = null;\n }, 200);\n } else {\n setTypeaheadValues(NO_FREE_TEXT);\n }\n } else if (evt.key === \"Enter\" && value === \"\") {\n console.log(\"ENTER no value\");\n }\n },\n [NO_FREE_TEXT, allowFreeInput, onCommit, valueRef],\n );\n\n const callbackRef = useCallback<RefCallback<HTMLDivElement>>((el) => {\n rootRef.current = el;\n const input = el?.querySelector(\"input\") ?? null;\n inputRef.current = input;\n }, []);\n\n useEffect(() => {\n if (table) {\n const vuuTable = getVuuTable(table);\n if (\n meetsMinTextLengthThreshold(\n value,\n minCharacterCountToTriggerSuggestions,\n )\n ) {\n const params: TypeaheadParams = value\n ? [vuuTable, column, value]\n : [vuuTable, column];\n getSuggestions(params)\n .then((suggestions) => {\n console.log({ suggestions });\n if (suggestions === false) {\n // TODO is this right\n setTypeaheadValues([]);\n } else if (suggestions.length === 0 && value) {\n setTypeaheadValues((values) =>\n // Do not update if we have already set suggestions to the no free text warning\n values === NO_FREE_TEXT ? NO_FREE_TEXT : NO_DATA_MATCH,\n );\n } else {\n setTypeaheadValues(suggestions);\n if (pendingListFocusRef.current && inputRef.current) {\n // This is a workaround for the fact that ComboBox does not automatically\n // highlight first list item when items have been populated dynamically.\n // This has been raised as a bug.\n //TODO this is failing to work correctly in new version of cypress\n dispatchKeyboardEvent(inputRef.current, \"keydown\", \"ArrowUp\");\n }\n }\n pendingListFocusRef.current = false;\n })\n .catch((err) => {\n console.error(\"Error getting suggestions\", err);\n });\n } else {\n setTypeaheadValues([]);\n }\n }\n }, [\n table,\n column,\n getSuggestions,\n value,\n NO_FREE_TEXT,\n minCharacterCountToTriggerSuggestions,\n ]);\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = useCallback(\n (evt) => {\n const { value: newValue } = evt.target;\n const { current: value } = valueRef;\n if (value === \"\" && newValue) {\n setOpen(true);\n const input = rootRef.current?.querySelector(\"input\");\n if (input && highlightFirstSuggestion) {\n pendingListFocusRef.current = true;\n }\n } else if (newValue === \"\" && value) {\n // treat clear value as a commit event\n onCommit(evt, \"\");\n }\n setValue(newValue);\n },\n [highlightFirstSuggestion, onCommit, setValue, valueRef],\n );\n\n const handleSelectionChange = (\n evt: SyntheticEvent,\n [newSelected]: string[],\n ) => {\n if (commitTimeout.current) {\n clearTimeout(commitTimeout.current);\n commitTimeout.current = null;\n }\n setValue(newSelected);\n onCommit(\n evt as SyntheticEvent<HTMLInputElement>,\n newSelected,\n \"typeahead-suggestion\",\n );\n };\n\n const handleOpenChange = (newOpen: boolean) => {\n if (newOpen && valueRef.current === \"\") {\n // ignore this, don't open dropdown unless user has typed at least one character\n setOpen(newOpen);\n } else {\n setOpen(newOpen);\n }\n };\n\n const inputProps: ComponentPropsWithoutRef<\"input\"> = {\n ...inputPropsProp,\n autoComplete: \"off\",\n };\n\n const [noFreeText] = NO_FREE_TEXT;\n return {\n inputProps,\n noFreeText,\n onChange: handleChange,\n onKeyDown: handleKeyDown,\n onOpenChange: handleOpenChange,\n onSelectionChange: handleSelectionChange,\n open,\n ref: callbackRef,\n typeaheadValues,\n value: valueRef.current,\n };\n};\n"],"names":["value"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useVuuTypeaheadInput.js","sources":["../../../../packages/vuu-ui-controls/src/vuu-typeahead-input/useVuuTypeaheadInput.ts"],"sourcesContent":["import { PillInputProps } from \"@salt-ds/core/dist-types/pill-input\";\nimport { useTypeaheadSuggestions } from \"@vuu-ui/vuu-data-react\";\nimport { TableSchemaTable } from \"@vuu-ui/vuu-data-types\";\nimport type { TypeaheadParams } from \"@vuu-ui/vuu-protocol-types\";\nimport {\n dispatchKeyboardEvent,\n getVuuTable,\n useStateRef,\n NO_DATA_MATCH,\n type CommitHandler,\n} from \"@vuu-ui/vuu-utils\";\nimport {\n ComponentPropsWithoutRef,\n FocusEventHandler,\n KeyboardEventHandler,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ChangeEventHandler,\n type RefCallback,\n type SyntheticEvent,\n} from \"react\";\n\nconst meetsMinTextLengthThreshold = (value: string, minLength: number) =>\n value.length >= minLength;\n\nexport interface VuuTypeaheadInputHookProps {\n /**\n * Allows a text string to be submitted that does not match any suggestion\n * Defaults to true\n */\n allowFreeInput?: boolean;\n column: string;\n /**\n * A warning to display to the user if allowFreeText is false and they attempt\n * to commit text which does not match any suggestions. A default message will\n * be shown if not provided\n */\n freeTextWarning?: string;\n /**\n * When suggestions are displayed, should first option be highlighted ?\n * Highlighted option will be selected if Enter pressed. If this option\n * is not applied and no suggestion is highlighted, Enter will commit\n * current text. This will be desirable if filter operator will be\n * 'contains', not if filter operator will be '='.\n */\n highlightFirstSuggestion?: boolean;\n inputProps?: PillInputProps[\"inputProps\"];\n /**\n * If zero, suggestions will be shown even without any text input.\n * Suggestions will be displayed on click, or, if focused via keynoard,\n * on ArrowDown.\n * If n, where n > 0, then n characters must be typed before suggestion\n * list will be fetched.\n */\n minCharacterCountToTriggerSuggestions?: 0 | 1 | 2 | 3;\n onCommit: CommitHandler<HTMLInputElement>;\n table: TableSchemaTable;\n}\n\nconst defaultFreeTextWarning =\n \"Please select a value from the list of suggestions. If no suggestions match your text, then the value is not valid. If you believe this should be a valid value, please reach out to the support team\";\n\nexport const useVuuTypeaheadInput = ({\n allowFreeInput = true,\n column,\n freeTextWarning,\n highlightFirstSuggestion = true,\n inputProps: inputPropsProp,\n minCharacterCountToTriggerSuggestions = 1,\n onCommit,\n table,\n}: VuuTypeaheadInputHookProps) => {\n const NO_FREE_TEXT = useMemo(\n () => [freeTextWarning ?? defaultFreeTextWarning],\n [freeTextWarning],\n );\n const [valueRef, setValue] = useStateRef(\"\");\n const [open, setOpen] = useState(false);\n const inputRef = useRef<HTMLInputElement | null>(null);\n const rootRef = useRef<HTMLDivElement | null>(null);\n const [typeaheadValues, setTypeaheadValues] = useState<string[]>([]);\n const getSuggestions = useTypeaheadSuggestions();\n const pendingListFocusRef = useRef(false);\n\n const { current: value } = valueRef;\n\n useMemo(() => {\n console.log(\n `[useVuuTypeaheadInput] inputProps value has changed ${inputPropsProp?.value} valueRef value ${valueRef.current}`,\n );\n if (\n inputPropsProp?.value !== undefined &&\n inputPropsProp?.value !== valueRef.current\n ) {\n setValue(`${inputPropsProp.value}`);\n }\n }, [inputPropsProp?.value, setValue, valueRef]);\n\n const commitTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const handleKeyDown = useCallback<KeyboardEventHandler<HTMLInputElement>>(\n (evt) => {\n const { current: value } = valueRef;\n if (evt.key === \"Enter\" && value !== \"\") {\n if (allowFreeInput) {\n commitTimeout.current = setTimeout(() => {\n onCommit?.(evt, value, \"text-input\");\n setOpen(false);\n commitTimeout.current = null;\n }, 200);\n } else {\n setTypeaheadValues(NO_FREE_TEXT);\n }\n } else if (evt.key === \"Enter\" && value === \"\") {\n console.log(\"ENTER no value\");\n }\n },\n [NO_FREE_TEXT, allowFreeInput, onCommit, valueRef],\n );\n\n const callbackRef = useCallback<RefCallback<HTMLDivElement>>((el) => {\n rootRef.current = el;\n const input = el?.querySelector(\"input\") ?? null;\n inputRef.current = input;\n }, []);\n\n const refreshSuggestions = useCallback(() => {\n if (table) {\n const vuuTable = getVuuTable(table);\n if (\n meetsMinTextLengthThreshold(\n value,\n minCharacterCountToTriggerSuggestions,\n )\n ) {\n const params: TypeaheadParams = value\n ? [vuuTable, column, value]\n : [vuuTable, column];\n getSuggestions(params)\n .then((suggestions) => {\n if (suggestions === false) {\n // TODO is this right\n setTypeaheadValues([]);\n } else if (suggestions.length === 0 && value) {\n setTypeaheadValues((values) =>\n // Do not update if we have already set suggestions to the no free text warning\n values === NO_FREE_TEXT ? NO_FREE_TEXT : NO_DATA_MATCH,\n );\n } else {\n setTypeaheadValues(suggestions);\n if (pendingListFocusRef.current && inputRef.current) {\n // This is a workaround for the fact that ComboBox does not automatically\n // highlight first list item when items have been populated dynamically.\n // This has been raised as a bug.\n //TODO this is failing to work correctly in new version of cypress\n dispatchKeyboardEvent(inputRef.current, \"keydown\", \"ArrowUp\");\n }\n }\n pendingListFocusRef.current = false;\n })\n .catch((err) => {\n console.error(\"Error getting suggestions\", err);\n });\n } else {\n setTypeaheadValues([]);\n }\n }\n }, [\n NO_FREE_TEXT,\n column,\n getSuggestions,\n minCharacterCountToTriggerSuggestions,\n table,\n value,\n ]);\n\n useEffect(() => {\n // This will preload suggestions for controls with no char input minimum\n refreshSuggestions();\n }, [refreshSuggestions]);\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = useCallback(\n (evt) => {\n const { value: newValue } = evt.target;\n const { current: value } = valueRef;\n if (value === \"\" && newValue) {\n setOpen(true);\n const input = rootRef.current?.querySelector(\"input\");\n if (input && highlightFirstSuggestion) {\n pendingListFocusRef.current = true;\n }\n } else if (newValue === \"\" && value) {\n // treat clear value as a commit event\n onCommit(evt, \"\");\n }\n setValue(newValue);\n },\n [highlightFirstSuggestion, onCommit, setValue, valueRef],\n );\n\n const handleSelectionChange = (\n evt: SyntheticEvent,\n [newSelected]: string[],\n ) => {\n if (commitTimeout.current) {\n clearTimeout(commitTimeout.current);\n commitTimeout.current = null;\n }\n setValue(newSelected);\n onCommit(\n evt as SyntheticEvent<HTMLInputElement>,\n newSelected,\n \"typeahead-suggestion\",\n );\n };\n\n const handleOpenChange = (newOpen: boolean) => {\n if (newOpen && valueRef.current === \"\") {\n // ignore this, don't open dropdown unless user has typed at least one character\n setOpen(newOpen);\n } else {\n setOpen(newOpen);\n }\n };\n\n const handleInputFocus = useCallback<FocusEventHandler<HTMLInputElement>>(\n (e) => {\n inputPropsProp?.onFocus?.(e);\n refreshSuggestions();\n },\n [inputPropsProp, refreshSuggestions],\n );\n\n const inputProps: ComponentPropsWithoutRef<\"input\"> = {\n ...inputPropsProp,\n autoComplete: \"off\",\n onFocus: handleInputFocus,\n };\n\n const [noFreeText] = NO_FREE_TEXT;\n return {\n inputProps,\n noFreeText,\n onChange: handleChange,\n onKeyDown: handleKeyDown,\n onOpenChange: handleOpenChange,\n onSelectionChange: handleSelectionChange,\n open,\n ref: callbackRef,\n typeaheadValues,\n value: valueRef.current,\n };\n};\n"],"names":["value"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.13.
|
|
2
|
+
"version": "0.13.45-alpha.01",
|
|
3
3
|
"description": "VUU UI Controls",
|
|
4
4
|
"author": "heswell",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"devDependencies": {
|
|
7
|
-
"@vuu-ui/vuu-data-types": "0.13.
|
|
8
|
-
"@vuu-ui/vuu-protocol-types": "0.13.
|
|
9
|
-
"@vuu-ui/vuu-table-types": "0.13.
|
|
7
|
+
"@vuu-ui/vuu-data-types": "0.13.45-alpha.01",
|
|
8
|
+
"@vuu-ui/vuu-protocol-types": "0.13.45-alpha.01",
|
|
9
|
+
"@vuu-ui/vuu-table-types": "0.13.45-alpha.01"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@vuu-ui/vuu-context-menu": "0.13.
|
|
13
|
-
"@vuu-ui/vuu-data-react": "0.13.
|
|
14
|
-
"@vuu-ui/vuu-layout": "0.13.
|
|
15
|
-
"@vuu-ui/vuu-popups": "0.13.
|
|
16
|
-
"@vuu-ui/vuu-table": "0.13.
|
|
17
|
-
"@vuu-ui/vuu-utils": "0.13.
|
|
12
|
+
"@vuu-ui/vuu-context-menu": "0.13.45-alpha.01",
|
|
13
|
+
"@vuu-ui/vuu-data-react": "0.13.45-alpha.01",
|
|
14
|
+
"@vuu-ui/vuu-layout": "0.13.45-alpha.01",
|
|
15
|
+
"@vuu-ui/vuu-popups": "0.13.45-alpha.01",
|
|
16
|
+
"@vuu-ui/vuu-table": "0.13.45-alpha.01",
|
|
17
|
+
"@vuu-ui/vuu-utils": "0.13.45-alpha.01",
|
|
18
18
|
"@salt-ds/core": "1.48.0",
|
|
19
19
|
"@salt-ds/icons": "1.14.0",
|
|
20
20
|
"@salt-ds/styles": "0.2.1",
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
|
-
|
|
1
|
+
import React, { ReactElement, ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* If component is a string, the component will be read from the
|
|
4
|
+
* comoponent registry. In that case, componentProps can be used
|
|
5
|
+
* to pass props to the component.
|
|
6
|
+
*/
|
|
7
|
+
export type ShowContextPanel = (component: string | ReactElement, title: string, componentProps?: unknown) => void;
|
|
3
8
|
export interface ContextPanelProps {
|
|
4
9
|
hideContextPanel?: () => void;
|
|
5
10
|
showContextPanel: ShowContextPanel;
|
|
6
11
|
}
|
|
7
|
-
export declare const ContextPanelContext:
|
|
12
|
+
export declare const ContextPanelContext: React.Context<ContextPanelProps>;
|
|
8
13
|
export declare const ContextPanelProvider: ({ children, hideContextPanel: hideContextPanelProp, showContextPanel: showContextPanelProp, }: Partial<ContextPanelProps> & {
|
|
9
14
|
children: ReactNode;
|
|
10
15
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { ComboBoxProps } from "@salt-ds/core";
|
|
1
2
|
import { VuuTypeaheadInputHookProps } from "./useVuuTypeaheadInput";
|
|
2
|
-
export interface VuuTypeaheadInputProps extends VuuTypeaheadInputHookProps {
|
|
3
|
+
export interface VuuTypeaheadInputProps extends VuuTypeaheadInputHookProps, Pick<ComboBoxProps, "selectOnTab"> {
|
|
3
4
|
className?: string;
|
|
4
5
|
}
|
|
5
|
-
export declare const VuuTypeaheadInput: ({ allowFreeInput, className, column, freeTextWarning, highlightFirstSuggestion, inputProps: inputPropsProp, minCharacterCountToTriggerSuggestions, onCommit, table, }: VuuTypeaheadInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export declare const VuuTypeaheadInput: ({ allowFreeInput, className, column, freeTextWarning, highlightFirstSuggestion, inputProps: inputPropsProp, minCharacterCountToTriggerSuggestions, onCommit, selectOnTab, table, }: VuuTypeaheadInputProps) => import("react/jsx-runtime").JSX.Element;
|