@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.
@@ -31,24 +31,22 @@ const ContextPanelProvider = ({
31
31
  }, []);
32
32
  const hideContextPanel = hideContextPanelProp ?? inheritedHideContextPanel;
33
33
  const showContextPanel = React.useCallback(
34
- (componentType, title, props) => {
34
+ (elementOrComponentType, title, props) => {
35
35
  if (showContextPanelProp) {
36
- showContextPanelProp(componentType, title, props);
36
+ showContextPanelProp(elementOrComponentType, title, props);
37
37
  } else if (inheritedShowContextPanel !== UndefinedShowContextPanel) {
38
- inheritedShowContextPanel(componentType, title, props);
38
+ inheritedShowContextPanel(elementOrComponentType, title, props);
39
39
  } else if (!vuuLayout.isUnconfiguredProperty(showComponentInContextPanel)) {
40
- showComponentInContextPanel(
41
- { type: componentType, props },
42
- title
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: componentType,
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 componentType: string,\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 (componentType, title, props) => {\n if (showContextPanelProp) {\n showContextPanelProp(componentType, title, props);\n } else if (inheritedShowContextPanel !== UndefinedShowContextPanel) {\n inheritedShowContextPanel(componentType, title, props);\n } else if (!isUnconfiguredProperty(showComponentInContextPanel)) {\n showComponentInContextPanel(\n { type: componentType, props } as LayoutJSON,\n title,\n );\n } else {\n const component = layoutFromJson(\n {\n type: componentType,\n props,\n } as LayoutJSON,\n \"\",\n );\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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"}
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
- maskedInputRef.current?.click();
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 maskedInputRef.current?.click();\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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"}
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 extends VuuTypeaheadInputHookProps {\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 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 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;AAMlB,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;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,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;;;;"}
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.useEffect(() => {
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
- table,
97
+ NO_FREE_TEXT,
91
98
  column,
92
99
  getSuggestions,
93
- value,
94
- NO_FREE_TEXT,
95
- minCharacterCountToTriggerSuggestions
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":"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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":["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
- (componentType, title, props) => {
32
+ (elementOrComponentType, title, props) => {
33
33
  if (showContextPanelProp) {
34
- showContextPanelProp(componentType, title, props);
34
+ showContextPanelProp(elementOrComponentType, title, props);
35
35
  } else if (inheritedShowContextPanel !== UndefinedShowContextPanel) {
36
- inheritedShowContextPanel(componentType, title, props);
36
+ inheritedShowContextPanel(elementOrComponentType, title, props);
37
37
  } else if (!isUnconfiguredProperty(showComponentInContextPanel)) {
38
- showComponentInContextPanel(
39
- { type: componentType, props },
40
- title
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: componentType,
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 componentType: string,\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 (componentType, title, props) => {\n if (showContextPanelProp) {\n showContextPanelProp(componentType, title, props);\n } else if (inheritedShowContextPanel !== UndefinedShowContextPanel) {\n inheritedShowContextPanel(componentType, title, props);\n } else if (!isUnconfiguredProperty(showComponentInContextPanel)) {\n showComponentInContextPanel(\n { type: componentType, props } as LayoutJSON,\n title,\n );\n } else {\n const component = layoutFromJson(\n {\n type: componentType,\n props,\n } as LayoutJSON,\n \"\",\n );\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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"}
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
- maskedInputRef.current?.click();
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 maskedInputRef.current?.click();\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":"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"}
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":"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"}
@@ -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 extends VuuTypeaheadInputHookProps {\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 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 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;AAMlB,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;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,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;;;;"}
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
- useEffect(() => {
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
- table,
95
+ NO_FREE_TEXT,
89
96
  column,
90
97
  getSuggestions,
91
- value,
92
- NO_FREE_TEXT,
93
- minCharacterCountToTriggerSuggestions
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.44",
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.44",
8
- "@vuu-ui/vuu-protocol-types": "0.13.44",
9
- "@vuu-ui/vuu-table-types": "0.13.44"
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.44",
13
- "@vuu-ui/vuu-data-react": "0.13.44",
14
- "@vuu-ui/vuu-layout": "0.13.44",
15
- "@vuu-ui/vuu-popups": "0.13.44",
16
- "@vuu-ui/vuu-table": "0.13.44",
17
- "@vuu-ui/vuu-utils": "0.13.44",
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
- export type ShowContextPanel = (componentType: string, title: string, componentProps: unknown) => void;
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: import("react").Context<ContextPanelProps>;
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;