@vuu-ui/vuu-ui-controls 0.13.106 → 0.13.108
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/editable/useEditableText.js +99 -56
- package/cjs/editable/useEditableText.js.map +1 -1
- package/cjs/icon-button/IconButton.css.js +1 -1
- package/cjs/instrument-picker/TablePicker.js +11 -2
- package/cjs/instrument-picker/TablePicker.js.map +1 -1
- package/cjs/split-button/SplitButton.css.js +1 -1
- package/cjs/split-button/SplitButton.js +9 -7
- package/cjs/split-button/SplitButton.js.map +1 -1
- package/cjs/toolbar/Toolbar.css.js +1 -1
- package/cjs/vuu-typeahead-input/VuuTypeaheadInput.js.map +1 -1
- package/cjs/vuu-typeahead-input/useVuuTypeaheadInput.js +9 -1
- package/cjs/vuu-typeahead-input/useVuuTypeaheadInput.js.map +1 -1
- package/esm/editable/useEditableText.js +100 -57
- package/esm/editable/useEditableText.js.map +1 -1
- package/esm/icon-button/IconButton.css.js +1 -1
- package/esm/instrument-picker/TablePicker.js +11 -2
- package/esm/instrument-picker/TablePicker.js.map +1 -1
- package/esm/split-button/SplitButton.css.js +1 -1
- package/esm/split-button/SplitButton.js +9 -7
- package/esm/split-button/SplitButton.js.map +1 -1
- package/esm/toolbar/Toolbar.css.js +1 -1
- package/esm/vuu-typeahead-input/VuuTypeaheadInput.js.map +1 -1
- package/esm/vuu-typeahead-input/useVuuTypeaheadInput.js +9 -1
- package/esm/vuu-typeahead-input/useVuuTypeaheadInput.js.map +1 -1
- package/package.json +12 -12
- package/types/editable/useEditableText.d.ts +4 -3
- package/types/split-button/SplitButton.d.ts +1 -1
|
@@ -15,85 +15,123 @@ const useEditableText = ({
|
|
|
15
15
|
});
|
|
16
16
|
const initialValueRef = React.useRef(value?.toString() ?? "");
|
|
17
17
|
const isDirtyRef = React.useRef(false);
|
|
18
|
+
const isEditingRef = React.useRef(false);
|
|
18
19
|
React.useMemo(() => {
|
|
19
20
|
if (initialValueRef.current !== value?.toString()) {
|
|
20
21
|
initialValueRef.current = stringValueOf(value);
|
|
21
22
|
setEditState({ message: "", value: stringValueOf(value) });
|
|
22
23
|
}
|
|
23
24
|
}, [value]);
|
|
24
|
-
const commit = React.useCallback(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
const commit = React.useCallback(async () => {
|
|
26
|
+
const { value: value2 } = editState;
|
|
27
|
+
const result = clientSideEditValidationCheck?.(value2, "*");
|
|
28
|
+
if (result?.ok === false) {
|
|
29
|
+
setEditState((state) => ({
|
|
30
|
+
...state,
|
|
31
|
+
message: result?.messages?.join(",")
|
|
32
|
+
}));
|
|
33
|
+
return false;
|
|
34
|
+
} else {
|
|
35
|
+
setEditState((state) => ({ ...state, message: void 0 }));
|
|
36
|
+
const typedValue = vuuUtils.getTypedValue(value2, type, true);
|
|
37
|
+
const response = await onEdit?.(
|
|
38
|
+
{ editType: "commit", value: typedValue, isValid: true },
|
|
39
|
+
"commit"
|
|
40
|
+
);
|
|
41
|
+
if (vuuUtils.isRpcSuccess(response)) {
|
|
42
|
+
isDirtyRef.current = false;
|
|
43
|
+
initialValueRef.current = value2;
|
|
44
|
+
return true;
|
|
45
|
+
} else if (vuuUtils.isRpcError(response)) {
|
|
46
|
+
setEditState((state) => ({
|
|
47
|
+
...state,
|
|
48
|
+
message: response.errorMessage
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}, [clientSideEditValidationCheck, editState, onEdit, type]);
|
|
54
|
+
const handleKeyDown = React.useCallback(
|
|
55
|
+
async (evt) => {
|
|
56
|
+
const { key, target } = evt;
|
|
57
|
+
const input = target;
|
|
58
|
+
if (key === "Enter") {
|
|
59
|
+
if (isEditingRef.current) {
|
|
60
|
+
if (isDirtyRef.current) {
|
|
61
|
+
const commitSuccessful = await commit();
|
|
62
|
+
if (commitSuccessful) {
|
|
63
|
+
isEditingRef.current = false;
|
|
64
|
+
vuuUtils.dispatchCustomEvent(input, "vuu-exit-edit-mode");
|
|
65
|
+
vuuUtils.dispatchCustomEvent(input, "vuu-commit");
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
isEditingRef.current = false;
|
|
69
|
+
vuuUtils.dispatchCustomEvent(input, "vuu-exit-edit-mode");
|
|
70
|
+
}
|
|
34
71
|
} else {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
72
|
+
isEditingRef.current = true;
|
|
73
|
+
vuuUtils.dispatchCustomEvent(input, "vuu-enter-edit-mode");
|
|
74
|
+
input.select();
|
|
75
|
+
}
|
|
76
|
+
} else if (key === "ArrowRight" || key === "ArrowLeft" || key === "ArrowUp" || key === "ArrowDown") {
|
|
77
|
+
if (isEditingRef.current) {
|
|
78
|
+
evt.stopPropagation();
|
|
79
|
+
}
|
|
80
|
+
} else if (evt.key === "Escape") {
|
|
81
|
+
if (isEditingRef.current) {
|
|
82
|
+
if (isDirtyRef.current) {
|
|
83
|
+
const { value: previousValue } = editState;
|
|
42
84
|
isDirtyRef.current = false;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
85
|
+
setEditState({
|
|
86
|
+
value: initialValueRef.current,
|
|
87
|
+
message: void 0
|
|
88
|
+
});
|
|
89
|
+
onEdit?.(
|
|
90
|
+
{
|
|
91
|
+
editType: "cancel",
|
|
92
|
+
isValid: true,
|
|
93
|
+
previousValue,
|
|
94
|
+
value: initialValueRef.current
|
|
95
|
+
},
|
|
96
|
+
"cancel"
|
|
97
|
+
);
|
|
47
98
|
}
|
|
99
|
+
isEditingRef.current = false;
|
|
100
|
+
vuuUtils.dispatchCustomEvent(input, "vuu-exit-edit-mode");
|
|
48
101
|
}
|
|
49
|
-
} else {
|
|
50
|
-
vuuUtils.dispatchCustomEvent(target, "vuu-commit");
|
|
51
102
|
}
|
|
52
103
|
},
|
|
53
|
-
[
|
|
104
|
+
[commit, editState, onEdit]
|
|
54
105
|
);
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const { value: previousValue } = editState;
|
|
64
|
-
isDirtyRef.current = false;
|
|
65
|
-
setEditState({ value: initialValueRef.current, message: void 0 });
|
|
66
|
-
onEdit?.(
|
|
67
|
-
{
|
|
68
|
-
editType: "cancel",
|
|
69
|
-
isValid: true,
|
|
70
|
-
previousValue,
|
|
71
|
-
value: initialValueRef.current
|
|
72
|
-
},
|
|
73
|
-
"cancel"
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
106
|
+
const beginEditHandler = React.useCallback((evt) => {
|
|
107
|
+
isEditingRef.current = true;
|
|
108
|
+
vuuUtils.dispatchCustomEvent(evt.target, "vuu-enter-edit-mode");
|
|
109
|
+
}, []);
|
|
110
|
+
const handleFocus = React.useCallback(
|
|
111
|
+
(e) => {
|
|
112
|
+
console.log(`[useEditableText] handleFocus`);
|
|
113
|
+
e.target.addEventListener("vuu-begin-edit", beginEditHandler, true);
|
|
77
114
|
},
|
|
78
|
-
[
|
|
115
|
+
[beginEditHandler]
|
|
79
116
|
);
|
|
80
117
|
const handleBlur = React.useCallback(
|
|
81
|
-
(evt) => {
|
|
82
|
-
|
|
83
|
-
|
|
118
|
+
async (evt) => {
|
|
119
|
+
evt.target.removeEventListener("vuu-begin-edit", beginEditHandler, true);
|
|
120
|
+
if (isEditingRef.current) {
|
|
121
|
+
if (isDirtyRef.current) {
|
|
122
|
+
const commitSuccessful = await commit();
|
|
123
|
+
console.log({ commitSuccessful });
|
|
124
|
+
}
|
|
125
|
+
isEditingRef.current = false;
|
|
126
|
+
vuuUtils.dispatchCustomEvent(evt.target, "vuu-exit-edit-mode");
|
|
84
127
|
}
|
|
85
128
|
},
|
|
86
|
-
[commit]
|
|
129
|
+
[beginEditHandler, commit]
|
|
87
130
|
);
|
|
88
131
|
const handleChange = React.useCallback(
|
|
89
132
|
(evt) => {
|
|
90
133
|
const { value: value2 } = evt.target;
|
|
91
134
|
const typedValue = vuuUtils.getTypedValue(value2, type, true);
|
|
92
|
-
console.log(
|
|
93
|
-
`[useEditableText] handleChange '${value2}' typedValue ${typedValue}
|
|
94
|
-
initial value ${initialValueRef.current}
|
|
95
|
-
`
|
|
96
|
-
);
|
|
97
135
|
isDirtyRef.current = value2 !== initialValueRef.current;
|
|
98
136
|
const result = clientSideEditValidationCheck?.(value2, "change");
|
|
99
137
|
setEditState({ value: value2 });
|
|
@@ -108,6 +146,10 @@ const useEditableText = ({
|
|
|
108
146
|
if (result?.ok === false) {
|
|
109
147
|
setEditState({ value: value2, message: result.messages?.join(",") });
|
|
110
148
|
}
|
|
149
|
+
if (!isEditingRef.current) {
|
|
150
|
+
isEditingRef.current = true;
|
|
151
|
+
vuuUtils.dispatchCustomEvent(evt.target, "vuu-enter-edit-mode");
|
|
152
|
+
}
|
|
111
153
|
},
|
|
112
154
|
[clientSideEditValidationCheck, onEdit, type]
|
|
113
155
|
);
|
|
@@ -115,6 +157,7 @@ const useEditableText = ({
|
|
|
115
157
|
//TODO why are we detecting commit here, why not use VuuInput ?
|
|
116
158
|
inputProps: {
|
|
117
159
|
onBlur: handleBlur,
|
|
160
|
+
onFocus: handleFocus,
|
|
118
161
|
onKeyDown: handleKeyDown
|
|
119
162
|
},
|
|
120
163
|
onChange: handleChange,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEditableText.js","sources":["../../../../packages/vuu-ui-controls/src/editable/useEditableText.ts"],"sourcesContent":["import type { DataValueValidationChecker } from \"@vuu-ui/vuu-data-types\";\nimport { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport type { DataItemEditHandler } from \"@vuu-ui/vuu-table-types\";\nimport { dispatchCustomEvent, getTypedValue } from \"@vuu-ui/vuu-utils\";\nimport {\n FocusEventHandler,\n FormEventHandler,\n KeyboardEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport interface EditableTextHookProps<\n T extends VuuRowDataItemType = VuuRowDataItemType,\n> {\n clientSideEditValidationCheck?: DataValueValidationChecker;\n value?: T;\n onEdit?: DataItemEditHandler;\n type?: \"string\" | \"number\" | \"boolean\";\n}\n\ntype EditState = {\n message?: string;\n value: string;\n};\n\nconst stringValueOf = (value?: VuuRowDataItemType) => value?.toString() ?? \"\";\n\nexport const useEditableText = <T extends string | number | boolean = string>({\n clientSideEditValidationCheck,\n value,\n onEdit,\n type = \"string\",\n}: EditableTextHookProps<T>) => {\n const [editState, setEditState] = useState<EditState>({\n value: stringValueOf(value),\n });\n const initialValueRef = useRef<string>(value?.toString() ?? \"\");\n const isDirtyRef = useRef(false);\n\n useMemo(() => {\n if (initialValueRef.current !== value?.toString()) {\n initialValueRef.current = stringValueOf(value);\n setEditState({ message: \"\", value: stringValueOf(value) });\n }\n }, [value]);\n\n const commit = useCallback(\n async (target: HTMLElement) => {\n const { value } = editState;\n if (isDirtyRef.current) {\n const result = clientSideEditValidationCheck?.(value, \"*\");\n if (result?.ok === false) {\n setEditState((state) => ({\n ...state,\n message: result?.messages?.join(\",\"),\n }));\n } else {\n setEditState((state) => ({ ...state, message: undefined }));\n const typedValue = getTypedValue(value, type, true);\n const response = await onEdit?.(\n { editType: \"commit\", value: typedValue, isValid: true },\n \"commit\",\n );\n if (response === true) {\n isDirtyRef.current = false;\n initialValueRef.current = value;\n dispatchCustomEvent(target, \"vuu-commit\");\n } else if (typeof response === \"string\") {\n setEditState((state) => ({ ...state, message: response }));\n }\n }\n } else {\n // why, if not dirty ?\n dispatchCustomEvent(target, \"vuu-commit\");\n }\n },\n [clientSideEditValidationCheck, editState, onEdit, type],\n );\n\n const handleKeyDown = useCallback(\n (evt: KeyboardEvent<HTMLElement>) => {\n if (evt.key === \"Enter\") {\n commit(evt.target as HTMLElement);\n } else if (\n evt.key === \"ArrowRight\" ||\n evt.key === \"ArrowLeft\" ||\n evt.key === \"ArrowUp\" ||\n evt.key === \"ArrowDown\"\n ) {\n evt.stopPropagation();\n } else if (evt.key === \"Escape\") {\n if (isDirtyRef.current) {\n const { value: previousValue } = editState;\n isDirtyRef.current = false;\n setEditState({ value: initialValueRef.current, message: undefined });\n // this assumes the original value was valid, is that safe ?\n onEdit?.(\n {\n editType: \"cancel\",\n isValid: true,\n previousValue,\n value: initialValueRef.current,\n },\n \"cancel\",\n );\n }\n }\n },\n [commit, editState, onEdit],\n );\n\n const handleBlur = useCallback<FocusEventHandler<HTMLElement>>(\n (evt) => {\n if (isDirtyRef.current) {\n commit(evt.target as HTMLElement);\n }\n },\n [commit],\n );\n\n const handleChange = useCallback<FormEventHandler>(\n (evt) => {\n const { value } = evt.target as HTMLInputElement;\n const typedValue = getTypedValue(value, type, true);\n console.log(\n `[useEditableText] handleChange '${value}' typedValue ${typedValue}\n initial value ${initialValueRef.current}\n `,\n );\n isDirtyRef.current = value !== initialValueRef.current;\n const result = clientSideEditValidationCheck?.(value, \"change\");\n setEditState({ value });\n\n onEdit?.(\n {\n editType: \"change\",\n isValid: result?.ok !== false,\n value: typedValue,\n },\n \"change\",\n );\n if (result?.ok === false) {\n setEditState({ value, message: result.messages?.join(\",\") });\n }\n },\n [clientSideEditValidationCheck, onEdit, type],\n );\n\n return {\n //TODO why are we detecting commit here, why not use VuuInput ?\n inputProps: {\n onBlur: handleBlur,\n onKeyDown: handleKeyDown,\n },\n onChange: handleChange,\n value: editState.value,\n warningMessage: editState.message,\n };\n};\n"],"names":["useState","useRef","useMemo","useCallback","value","getTypedValue","dispatchCustomEvent"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useEditableText.js","sources":["../../../../packages/vuu-ui-controls/src/editable/useEditableText.ts"],"sourcesContent":["import type { DataValueValidationChecker } from \"@vuu-ui/vuu-data-types\";\nimport { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport type { TableCellEditHandler } from \"@vuu-ui/vuu-table-types\";\nimport {\n dispatchCustomEvent,\n getTypedValue,\n isRpcError,\n isRpcSuccess,\n} from \"@vuu-ui/vuu-utils\";\nimport {\n FocusEventHandler,\n FormEventHandler,\n KeyboardEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport interface EditableTextHookProps<\n T extends VuuRowDataItemType = VuuRowDataItemType,\n> {\n clientSideEditValidationCheck?: DataValueValidationChecker;\n value?: T;\n onEdit?: TableCellEditHandler;\n type?: \"string\" | \"number\" | \"boolean\";\n}\n\ntype EditState = {\n message?: string;\n value: string;\n};\n\nconst stringValueOf = (value?: VuuRowDataItemType) => value?.toString() ?? \"\";\n\nexport const useEditableText = <T extends string | number | boolean = string>({\n clientSideEditValidationCheck,\n value,\n onEdit,\n type = \"string\",\n}: EditableTextHookProps<T>) => {\n const [editState, setEditState] = useState<EditState>({\n value: stringValueOf(value),\n });\n const initialValueRef = useRef<string>(value?.toString() ?? \"\");\n const isDirtyRef = useRef(false);\n const isEditingRef = useRef(false);\n\n useMemo(() => {\n if (initialValueRef.current !== value?.toString()) {\n initialValueRef.current = stringValueOf(value);\n setEditState({ message: \"\", value: stringValueOf(value) });\n }\n }, [value]);\n\n const commit = useCallback(async () => {\n const { value } = editState;\n const result = clientSideEditValidationCheck?.(value, \"*\");\n if (result?.ok === false) {\n setEditState((state) => ({\n ...state,\n message: result?.messages?.join(\",\"),\n }));\n return false;\n } else {\n setEditState((state) => ({ ...state, message: undefined }));\n const typedValue = getTypedValue(value, type, true);\n const response = await onEdit?.(\n { editType: \"commit\", value: typedValue, isValid: true },\n \"commit\",\n );\n if (isRpcSuccess(response)) {\n isDirtyRef.current = false;\n initialValueRef.current = value;\n return true;\n } else if (isRpcError(response)) {\n setEditState((state) => ({\n ...state,\n message: response.errorMessage,\n }));\n }\n }\n return false;\n }, [clientSideEditValidationCheck, editState, onEdit, type]);\n\n const handleKeyDown = useCallback(\n async (evt: KeyboardEvent<HTMLElement>) => {\n const { key, target } = evt;\n // console.log(`[useEditableText] handleKeyDown`);\n const input = target as HTMLInputElement;\n if (key === \"Enter\") {\n // console.log(\n // `[useEditableText] ENTER isEditing ? ${isEditingRef.current}, isDirty ${isDirtyRef.current}`,\n // );\n if (isEditingRef.current) {\n if (isDirtyRef.current) {\n // console.log(\" ...await commit\");\n const commitSuccessful = await commit();\n if (commitSuccessful) {\n isEditingRef.current = false;\n dispatchCustomEvent(input, \"vuu-exit-edit-mode\");\n dispatchCustomEvent(input, \"vuu-commit\");\n }\n } else {\n isEditingRef.current = false;\n dispatchCustomEvent(input, \"vuu-exit-edit-mode\");\n }\n } else {\n isEditingRef.current = true;\n dispatchCustomEvent(input, \"vuu-enter-edit-mode\");\n input.select();\n }\n } else if (\n key === \"ArrowRight\" ||\n key === \"ArrowLeft\" ||\n key === \"ArrowUp\" ||\n key === \"ArrowDown\"\n ) {\n if (isEditingRef.current) {\n // console.log(\n // `[useEditableText] handleKeydown, arrowkey whilst editing, stop propagation`,\n // );\n evt.stopPropagation();\n } else {\n // console.log(\n // `[useEditableText] handleKeydown, arrowkey, not editing so let it bubble`,\n // );\n // evt.preventDefault();\n }\n } else if (evt.key === \"Escape\") {\n if (isEditingRef.current) {\n // console.log(\n // `[useEditableText] ESC whilst editing, dirty ? ${isDirtyRef.current}`,\n // );\n if (isDirtyRef.current) {\n const { value: previousValue } = editState;\n isDirtyRef.current = false;\n setEditState({\n value: initialValueRef.current,\n message: undefined,\n });\n // this assumes the original value was valid, is that safe ?\n onEdit?.(\n {\n editType: \"cancel\",\n isValid: true,\n previousValue,\n value: initialValueRef.current,\n },\n \"cancel\",\n );\n }\n isEditingRef.current = false;\n dispatchCustomEvent(input, \"vuu-exit-edit-mode\");\n }\n } /* else if (isEditingRef.current === false && isCharacterKey(key)) {\n isEditingRef.current = true;\n dispatchCustomEvent(evt.target as HTMLElement, \"vuu-enter-edit-mode\");\n }*/\n },\n [commit, editState, onEdit],\n );\n\n const beginEditHandler = useCallback((evt: Event) => {\n // console.log(\"begin edit handler\");\n isEditingRef.current = true;\n dispatchCustomEvent(evt.target as HTMLElement, \"vuu-enter-edit-mode\");\n }, []);\n\n const handleFocus = useCallback<FocusEventHandler<HTMLElement>>(\n (e) => {\n console.log(`[useEditableText] handleFocus`);\n e.target.addEventListener(\"vuu-begin-edit\", beginEditHandler, true);\n },\n [beginEditHandler],\n );\n\n const handleBlur = useCallback<FocusEventHandler<HTMLElement>>(\n async (evt) => {\n evt.target.removeEventListener(\"vuu-begin-edit\", beginEditHandler, true);\n if (isEditingRef.current) {\n if (isDirtyRef.current) {\n const commitSuccessful = await commit();\n console.log({ commitSuccessful });\n }\n isEditingRef.current = false;\n dispatchCustomEvent(evt.target, \"vuu-exit-edit-mode\");\n }\n },\n [beginEditHandler, commit],\n );\n\n const handleChange = useCallback<FormEventHandler>(\n (evt) => {\n const { value } = evt.target as HTMLInputElement;\n const typedValue = getTypedValue(value, type, true);\n // console.log(\n // `[useEditableText] handleChange '${value}' typedValue ${typedValue}\n // initial value ${initialValueRef.current}\n // `,\n // );\n isDirtyRef.current = value !== initialValueRef.current;\n const result = clientSideEditValidationCheck?.(value, \"change\");\n setEditState({ value });\n\n onEdit?.(\n {\n editType: \"change\",\n isValid: result?.ok !== false,\n value: typedValue,\n },\n \"change\",\n );\n if (result?.ok === false) {\n setEditState({ value, message: result.messages?.join(\",\") });\n }\n\n if (!isEditingRef.current) {\n isEditingRef.current = true;\n dispatchCustomEvent(evt.target as HTMLElement, \"vuu-enter-edit-mode\");\n }\n },\n [clientSideEditValidationCheck, onEdit, type],\n );\n\n return {\n //TODO why are we detecting commit here, why not use VuuInput ?\n inputProps: {\n onBlur: handleBlur,\n onFocus: handleFocus,\n onKeyDown: handleKeyDown,\n },\n onChange: handleChange,\n value: editState.value,\n warningMessage: editState.message,\n };\n};\n"],"names":["useState","useRef","useMemo","useCallback","value","getTypedValue","isRpcSuccess","isRpcError","dispatchCustomEvent"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var iconButtonCss = ".vuuIconButton {\n --saltButton-padding: 0;\n --saltButton-minWidth: var(--salt-size-base);\n}\n";
|
|
3
|
+
var iconButtonCss = ".vuuIconButton.saltButton {\n --saltButton-padding: 0;\n --saltButton-minWidth: var(--salt-size-base);\n width: calc(var(--salt-size-base) + var(--salt-size-fixed-400));\n}\n";
|
|
4
4
|
|
|
5
5
|
module.exports = iconButtonCss;
|
|
6
6
|
//# sourceMappingURL=IconButton.css.js.map
|
|
@@ -75,17 +75,26 @@ const TablePicker = ({
|
|
|
75
75
|
IconButton.IconButton,
|
|
76
76
|
{
|
|
77
77
|
...getReferenceProps(),
|
|
78
|
+
appearance: "transparent",
|
|
78
79
|
"data-embedded": true,
|
|
79
80
|
ref: reference,
|
|
80
81
|
icon: "chevron-down",
|
|
81
82
|
onKeyDown,
|
|
82
|
-
|
|
83
|
+
sentiment: "neutral"
|
|
83
84
|
}
|
|
84
85
|
),
|
|
85
86
|
[getReferenceProps, onKeyDown, reference]
|
|
86
87
|
);
|
|
87
88
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ...htmlAttributes, className: classBase, ref: containerRef, children: [
|
|
88
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
89
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
90
|
+
core.Input,
|
|
91
|
+
{
|
|
92
|
+
...inputProps,
|
|
93
|
+
bordered: true,
|
|
94
|
+
endAdornment,
|
|
95
|
+
value
|
|
96
|
+
}
|
|
97
|
+
),
|
|
89
98
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
90
99
|
FloatingTable,
|
|
91
100
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TablePicker.js","sources":["../../../../packages/vuu-ui-controls/src/instrument-picker/TablePicker.tsx"],"sourcesContent":["import type { DataSourceRowObject, TableSchema } from \"@vuu-ui/vuu-data-types\";\nimport { Table, type TableProps } from \"@vuu-ui/vuu-table\";\nimport {\n Input,\n useFloatingComponent,\n useIdMemo,\n type FloatingComponentProps,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport cx from \"clsx\";\nimport { forwardRef, useMemo, type HTMLAttributes } from \"react\";\nimport { IconButton } from \"../icon-button\";\nimport tablePickerCss from \"./TablePicker.css\";\nimport { useTablePicker } from \"./useTablePicker\";\n\nconst classBase = \"vuuTablePicker\";\n\ninterface FloatingTableProps extends FloatingComponentProps {\n collapsed?: boolean;\n}\n\nexport interface TablePickerProps\n extends Omit<HTMLAttributes<HTMLElement>, \"onSelect\">,\n Pick<TableProps, \"onSelect\"> {\n TableProps?: Pick<TableProps, \"config\">;\n rowToString?: (row: DataSourceRowObject) => string;\n schema: TableSchema;\n searchColumns?: string[];\n}\n\nconst FloatingTable = forwardRef<HTMLDivElement, FloatingTableProps>(\n function FloatingTable(\n { children, className, collapsed, open, ...props },\n forwardedRef,\n ) {\n const { Component: FloatingComponent } = useFloatingComponent();\n return (\n <FloatingComponent\n className={cx(\n `${classBase}-floating-table`,\n {\n [`${classBase}-collapsed`]: collapsed,\n },\n className,\n )}\n role=\"listbox\"\n open={open}\n {...props}\n ref={forwardedRef}\n >\n {children}\n </FloatingComponent>\n );\n },\n);\n\nexport const TablePicker = ({\n TableProps,\n onSelect,\n rowToString,\n schema,\n searchColumns,\n ...htmlAttributes\n}: TablePickerProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-table-picker\",\n css: tablePickerCss,\n window: targetWindow,\n });\n\n const tableId = useIdMemo();\n\n const {\n containerRef,\n dataSource,\n highlightedIndex,\n floatingUIProps: { x, y, strategy, floating, reference },\n inputProps,\n interactionPropGetters: { getFloatingProps, getReferenceProps },\n onKeyDown,\n open,\n tableConfig,\n tableHandlers,\n tableRef,\n value,\n width,\n } = useTablePicker({\n TableProps,\n rowToString,\n onSelect,\n schema,\n searchColumns,\n });\n\n const endAdornment = useMemo(\n () => (\n <IconButton\n {...getReferenceProps()}\n data-embedded\n ref={reference}\n icon=\"chevron-down\"\n onKeyDown={onKeyDown}\n
|
|
1
|
+
{"version":3,"file":"TablePicker.js","sources":["../../../../packages/vuu-ui-controls/src/instrument-picker/TablePicker.tsx"],"sourcesContent":["import type { DataSourceRowObject, TableSchema } from \"@vuu-ui/vuu-data-types\";\nimport { Table, type TableProps } from \"@vuu-ui/vuu-table\";\nimport {\n Input,\n useFloatingComponent,\n useIdMemo,\n type FloatingComponentProps,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport cx from \"clsx\";\nimport { forwardRef, useMemo, type HTMLAttributes } from \"react\";\nimport { IconButton } from \"../icon-button\";\nimport tablePickerCss from \"./TablePicker.css\";\nimport { useTablePicker } from \"./useTablePicker\";\n\nconst classBase = \"vuuTablePicker\";\n\ninterface FloatingTableProps extends FloatingComponentProps {\n collapsed?: boolean;\n}\n\nexport interface TablePickerProps\n extends Omit<HTMLAttributes<HTMLElement>, \"onSelect\">,\n Pick<TableProps, \"onSelect\"> {\n TableProps?: Pick<TableProps, \"config\">;\n rowToString?: (row: DataSourceRowObject) => string;\n schema: TableSchema;\n searchColumns?: string[];\n}\n\nconst FloatingTable = forwardRef<HTMLDivElement, FloatingTableProps>(\n function FloatingTable(\n { children, className, collapsed, open, ...props },\n forwardedRef,\n ) {\n const { Component: FloatingComponent } = useFloatingComponent();\n return (\n <FloatingComponent\n className={cx(\n `${classBase}-floating-table`,\n {\n [`${classBase}-collapsed`]: collapsed,\n },\n className,\n )}\n role=\"listbox\"\n open={open}\n {...props}\n ref={forwardedRef}\n >\n {children}\n </FloatingComponent>\n );\n },\n);\n\nexport const TablePicker = ({\n TableProps,\n onSelect,\n rowToString,\n schema,\n searchColumns,\n ...htmlAttributes\n}: TablePickerProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-table-picker\",\n css: tablePickerCss,\n window: targetWindow,\n });\n\n const tableId = useIdMemo();\n\n const {\n containerRef,\n dataSource,\n highlightedIndex,\n floatingUIProps: { x, y, strategy, floating, reference },\n inputProps,\n interactionPropGetters: { getFloatingProps, getReferenceProps },\n onKeyDown,\n open,\n tableConfig,\n tableHandlers,\n tableRef,\n value,\n width,\n } = useTablePicker({\n TableProps,\n rowToString,\n onSelect,\n schema,\n searchColumns,\n });\n\n const endAdornment = useMemo(\n () => (\n <IconButton\n {...getReferenceProps()}\n appearance=\"transparent\"\n data-embedded\n ref={reference}\n icon=\"chevron-down\"\n onKeyDown={onKeyDown}\n sentiment=\"neutral\"\n />\n ),\n [getReferenceProps, onKeyDown, reference],\n );\n\n return (\n <div {...htmlAttributes} className={classBase} ref={containerRef}>\n <Input\n {...inputProps}\n bordered\n endAdornment={endAdornment}\n value={value}\n />\n <FloatingTable\n {...getFloatingProps()}\n collapsed={!open}\n id={tableId}\n open={open}\n left={x + 3}\n position={strategy}\n ref={floating}\n top={y + 3}\n >\n <Table\n {...tableHandlers}\n config={tableConfig}\n dataSource={dataSource}\n highlightedIndex={highlightedIndex}\n maxViewportRowLimit={10}\n navigationStyle=\"row\"\n ref={tableRef}\n selectionModel=\"single\"\n showColumnHeaders={false}\n width={width - 3}\n />\n </FloatingTable>\n </div>\n );\n};\n"],"names":["forwardRef","FloatingTable","useFloatingComponent","jsx","useWindow","useComponentCssInjection","tablePickerCss","useIdMemo","useTablePicker","useMemo","IconButton","Input","Table"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var splitButtonCss = ".vuuSplitButton {\n --saltButton-background: var(--split-background);\n --saltButton-background-hover: var(--split-background);\n --vuuPopupMenu-background: var(--split-background);\n --vuuPopupMenu-iconSize: 20px;\n\n /** less verbose local refs */\n --background: var(--vuuSplitButton-background);\n --foreground: var(--vuuSplitButton-foreground);\n --background-hover: var(--vuuSplitButton-background-hover);\n --foreground-hover: var(--vuuSplitButton-foreground-hover);\n\n --border-radius: var(--vuuSplitButton-borderRadius,
|
|
3
|
+
var splitButtonCss = ".vuuSplitButton {\n --saltButton-background: var(--split-background);\n --saltButton-background-hover: var(--split-background);\n --vuuPopupMenu-background: var(--split-background);\n --vuuPopupMenu-iconSize: 20px;\n\n /** less verbose local refs */\n --background: var(--vuuSplitButton-background);\n --foreground: var(--vuuSplitButton-foreground);\n --background-hover: var(--vuuSplitButton-background-hover);\n --foreground-hover: var(--vuuSplitButton-foreground-hover);\n\n --border-radius: var(--vuuSplitButton-borderRadius, var(--salt-palette-corner-weaker));\n --main-border-radius: var(--border-radius) 0 0 var(--border-radius);\n --trigger-border-radius: 0 var(--border-radius) var(--border-radius) 0;\n --trigger-border-style: solid solid solid none;\n\n align-items: center;\n border: none;\n border-radius: var(--border-radius);\n display: flex;\n\n .vuuSplitButton-main {\n border-radius: var(--main-border-radius);\n }\n .vuuSplitButton-trigger {\n border-radius: var(--trigger-border-radius);\n }\n}\n\n.vuuSplitButton.vuuFocusVisible {\n .saltButton {\n outline-style: none;\n }\n &.vuuSplitButton-primary {\n --split-background: var(\n --background-hover,\n var(--salt-actionable-bold-background-hover)\n );\n }\n &.vuuSplitButton-secondary {\n --split-background: var(\n --background-hover,\n var(--salt-actionable-subtle-background-hover)\n );\n }\n &.vuuSplitButton-cta {\n --split-background: var(\n --background-hover,\n var(--salt-actionable-accented-bold-background-hover)\n );\n .vuuSplitButton-trigger {\n --vuu-icon-color: var(--salt-actionable-bold-foreground-hover);\n }\n }\n}\n\n/** TODO move into theme */\n.vuuFocusVisible {\n outline-style: var(--salt-focused-outlineStyle);\n outline-width: var(--salt-focused-outlineWidth);\n outline-color: var(--salt-focused-outlineColor);\n outline-offset: var(--salt-focused-outlineOffset);\n}\n\n.vuuSplitButton-primary {\n --split-background: var(\n --background,\n var(--salt-actionable-bold-background)\n );\n --split-background-active: var(--salt-actionable-bold-background-active);\n --split-color-active: var(--salt-actionable-bold-foreground-active);\n}\n\n.vuuSplitButton-primary:hover:not(.vuuSplitButton-disabled) {\n --vuuButton-borderColor: var(--split-background);\n --saltButton-borderColor: var(--split-background);\n --split-background: var(\n --background-hover,\n var(--salt-actionable-bold-background-hover)\n );\n .saltButton {\n --saltButton-text-color: var(--salt-actionable-bold-foreground-hover);\n }\n}\n\n.vuuSplitButton-secondary {\n --saltButton-borderColor: var(--split-background);\n --split-background: var(\n --background,\n var(--salt-actionable-subtle-background)\n );\n --split-background-active: var(--salt-actionable-subtle-background-active);\n --split-color-active: var(--salt-actionable-subtle-foreground-active);\n}\n\n.vuuSplitButton-secondary:hover:not(.vuuSplitButton-disabled) {\n --vuuButton-borderColor: var(--split-background);\n --split-background: var(--salt-actionable-subtle-background-hover);\n .saltButton {\n --saltButton-text-color: var(--salt-actionable-subtle-foreground-hover);\n }\n}\n\n.vuuSplitButton-cta {\n --split-background: var(--background, var(--salt-actionable-accented-bold-background));\n --split-background-active: var(--salt-actionable-accented-bold-background-active);\n --split-color-active: var(--salt-actionable-bold-foreground-active);\n}\n.vuuSplitButton-cta:hover:not(.vuuSplitButton-disabled) {\n --vuuButton-borderColor: var(--split-background);\n --split-background: var(--salt-actionable-accented-bold-background-hover);\n --split-color: var(--salt-actionable-bold-foreground-hover);\n .saltButton {\n --saltButton-text-color: var(--salt-actionable-bold-foreground-hover);\n --vuu-icon-color: var(--salt-actionable-bold-foreground-hover);\n }\n}\n\n.vuuSplitButton:has(\n .vuuSplitButton-main:active,\n .vuuSplitButton-main.saltButton-active\n ) {\n --split-background: var(--split-background-active);\n .vuuSplitButton-trigger {\n --vuu-icon-color: var(--split-color-active);\n }\n}\n";
|
|
4
4
|
|
|
5
5
|
module.exports = splitButtonCss;
|
|
6
6
|
//# sourceMappingURL=SplitButton.css.js.map
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
-
var vuuPopups = require('@vuu-ui/vuu-popups');
|
|
5
4
|
var core = require('@salt-ds/core');
|
|
6
|
-
var React = require('react');
|
|
7
|
-
var useSplitButton = require('./useSplitButton.js');
|
|
8
|
-
var cx = require('clsx');
|
|
9
5
|
var styles = require('@salt-ds/styles');
|
|
10
6
|
var window = require('@salt-ds/window');
|
|
11
|
-
var SplitButton$1 = require('./SplitButton.css.js');
|
|
12
7
|
var vuuContextMenu = require('@vuu-ui/vuu-context-menu');
|
|
8
|
+
var vuuPopups = require('@vuu-ui/vuu-popups');
|
|
9
|
+
var cx = require('clsx');
|
|
10
|
+
var React = require('react');
|
|
11
|
+
var useSplitButton = require('./useSplitButton.js');
|
|
12
|
+
var SplitButton$1 = require('./SplitButton.css.js');
|
|
13
13
|
|
|
14
14
|
const classBase = "vuuSplitButton";
|
|
15
15
|
const SplitButton = React.forwardRef(
|
|
@@ -54,10 +54,11 @@ const SplitButton = React.forwardRef(
|
|
|
54
54
|
core.Button,
|
|
55
55
|
{
|
|
56
56
|
...ButtonProps2,
|
|
57
|
+
appearance: "solid",
|
|
57
58
|
className: `${classBase}-main`,
|
|
58
59
|
disabled,
|
|
59
60
|
ref: buttonRef,
|
|
60
|
-
|
|
61
|
+
sentiment: "neutral",
|
|
61
62
|
children
|
|
62
63
|
}
|
|
63
64
|
),
|
|
@@ -65,11 +66,12 @@ const SplitButton = React.forwardRef(
|
|
|
65
66
|
vuuPopups.PopupMenu,
|
|
66
67
|
{
|
|
67
68
|
...PopupMenuProps2,
|
|
69
|
+
appearance: "solid",
|
|
68
70
|
className: `${classBase}-trigger`,
|
|
69
71
|
disabled,
|
|
70
72
|
icon: PopupMenuProps2?.icon ?? "chevron-down",
|
|
71
73
|
tabIndex: segmented ? 0 : -1,
|
|
72
|
-
|
|
74
|
+
sentiment: "neutral"
|
|
73
75
|
}
|
|
74
76
|
)
|
|
75
77
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SplitButton.js","sources":["../../../../packages/vuu-ui-controls/src/split-button/SplitButton.tsx"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"SplitButton.js","sources":["../../../../packages/vuu-ui-controls/src/split-button/SplitButton.tsx"],"sourcesContent":["import { Button, ButtonProps, useForkRef } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { ContextMenuProvider } from \"@vuu-ui/vuu-context-menu\";\nimport { PopupMenu, PopupMenuProps } from \"@vuu-ui/vuu-popups\";\nimport cx from \"clsx\";\nimport { forwardRef, HTMLAttributes } from \"react\";\nimport { useSplitButton } from \"./useSplitButton\";\n\nimport splitButtonCss from \"./SplitButton.css\";\n\nexport interface SplitButtonProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"onClick\">,\n Pick<ButtonProps, \"onClick\"> {\n ButtonProps?: Partial<Omit<ButtonProps, \"onClick\" | \"variant\">>;\n PopupMenuProps?: Partial<PopupMenuProps>;\n disabled?: boolean;\n segmented?: boolean;\n variant?: ButtonProps[\"variant\"];\n}\n\nconst classBase = \"vuuSplitButton\";\n\nexport const SplitButton = forwardRef<HTMLDivElement, SplitButtonProps>(\n function SplitButton(\n {\n ButtonProps: ButtonPropsProp,\n PopupMenuProps: PopupMenuPropsProp,\n children,\n className,\n disabled = false,\n onClick,\n segmented = false,\n variant = \"primary\",\n ...htmlAttributes\n },\n forwardedRef,\n ) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-split-button\",\n css: splitButtonCss,\n window: targetWindow,\n });\n\n const { ButtonProps, buttonRef, rootRef, PopupMenuProps, ...rootProps } =\n useSplitButton({\n ButtonProps: ButtonPropsProp,\n PopupMenuProps: PopupMenuPropsProp,\n classBase,\n onClick,\n segmented,\n });\n\n return (\n <ContextMenuProvider>\n <div\n {...htmlAttributes}\n {...rootProps}\n className={cx(classBase, `${classBase}-${variant}`, className, {\n [`${classBase}-disabled`]: disabled,\n [`${classBase}-segmented`]: segmented,\n })}\n ref={useForkRef(forwardedRef, rootRef)}\n data-showcase-center\n tabIndex={-1}\n >\n <Button\n {...ButtonProps}\n appearance=\"solid\"\n className={`${classBase}-main`}\n disabled={disabled}\n ref={buttonRef}\n sentiment=\"neutral\"\n >\n {children}\n </Button>\n <PopupMenu\n {...PopupMenuProps}\n appearance=\"solid\"\n className={`${classBase}-trigger`}\n disabled={disabled}\n icon={PopupMenuProps?.icon ?? \"chevron-down\"}\n tabIndex={segmented ? 0 : -1}\n sentiment=\"neutral\"\n />\n </div>\n </ContextMenuProvider>\n );\n },\n);\n"],"names":["forwardRef","SplitButton","useWindow","useComponentCssInjection","splitButtonCss","ButtonProps","PopupMenuProps","useSplitButton","ContextMenuProvider","jsxs","useForkRef","jsx","Button","PopupMenu"],"mappings":";;;;;;;;;;;;;AAqBA,MAAM,SAAY,GAAA,gBAAA;AAEX,MAAM,WAAc,GAAAA,gBAAA;AAAA,EACzB,SAASC,YACP,CAAA;AAAA,IACE,WAAa,EAAA,eAAA;AAAA,IACb,cAAgB,EAAA,kBAAA;AAAA,IAChB,QAAA;AAAA,IACA,SAAA;AAAA,IACA,QAAW,GAAA,KAAA;AAAA,IACX,OAAA;AAAA,IACA,SAAY,GAAA,KAAA;AAAA,IACZ,OAAU,GAAA,SAAA;AAAA,IACV,GAAG;AAAA,KAEL,YACA,EAAA;AACA,IAAA,MAAM,eAAeC,gBAAU,EAAA;AAC/B,IAAyBC,+BAAA,CAAA;AAAA,MACvB,MAAQ,EAAA,kBAAA;AAAA,MACR,GAAK,EAAAC,aAAA;AAAA,MACL,MAAQ,EAAA;AAAA,KACT,CAAA;AAED,IAAM,MAAA,EAAE,WAAAC,EAAAA,YAAAA,EAAa,SAAW,EAAA,OAAA,EAAS,gBAAAC,eAAgB,EAAA,GAAG,SAAU,EAAA,GACpEC,6BAAe,CAAA;AAAA,MACb,WAAa,EAAA,eAAA;AAAA,MACb,cAAgB,EAAA,kBAAA;AAAA,MAChB,SAAA;AAAA,MACA,OAAA;AAAA,MACA;AAAA,KACD,CAAA;AAEH,IAAA,sCACGC,kCACC,EAAA,EAAA,QAAA,kBAAAC,eAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACE,GAAG,cAAA;AAAA,QACH,GAAG,SAAA;AAAA,QACJ,SAAA,EAAW,GAAG,SAAW,EAAA,CAAA,EAAG,SAAS,CAAI,CAAA,EAAA,OAAO,IAAI,SAAW,EAAA;AAAA,UAC7D,CAAC,CAAA,EAAG,SAAS,CAAA,SAAA,CAAW,GAAG,QAAA;AAAA,UAC3B,CAAC,CAAA,EAAG,SAAS,CAAA,UAAA,CAAY,GAAG;AAAA,SAC7B,CAAA;AAAA,QACD,GAAA,EAAKC,eAAW,CAAA,YAAA,EAAc,OAAO,CAAA;AAAA,QACrC,sBAAoB,EAAA,IAAA;AAAA,QACpB,QAAU,EAAA,CAAA,CAAA;AAAA,QAEV,QAAA,EAAA;AAAA,0BAAAC,cAAA;AAAA,YAACC,WAAA;AAAA,YAAA;AAAA,cACE,GAAGP,YAAAA;AAAA,cACJ,UAAW,EAAA,OAAA;AAAA,cACX,SAAA,EAAW,GAAG,SAAS,CAAA,KAAA,CAAA;AAAA,cACvB,QAAA;AAAA,cACA,GAAK,EAAA,SAAA;AAAA,cACL,SAAU,EAAA,SAAA;AAAA,cAET;AAAA;AAAA,WACH;AAAA,0BACAM,cAAA;AAAA,YAACE,mBAAA;AAAA,YAAA;AAAA,cACE,GAAGP,eAAAA;AAAA,cACJ,UAAW,EAAA,OAAA;AAAA,cACX,SAAA,EAAW,GAAG,SAAS,CAAA,QAAA,CAAA;AAAA,cACvB,QAAA;AAAA,cACA,IAAA,EAAMA,iBAAgB,IAAQ,IAAA,cAAA;AAAA,cAC9B,QAAA,EAAU,YAAY,CAAI,GAAA,CAAA,CAAA;AAAA,cAC1B,SAAU,EAAA;AAAA;AAAA;AACZ;AAAA;AAAA,KAEJ,EAAA,CAAA;AAAA;AAGN;;;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var toolbarCss = ".vuuToolbar {\n --toolbar-height: var(--vuuToolbar-height, 36px);\n --toolbar-item-height: var(--vuuToolbarItem-height, 100%);\n --vuuOverflowContainer-background: var(--vuuToolbar-background);\n --vuuOverflowContainer-borderColor: var(--vuuToolbar-borderColor);\n --vuuOverflowContainer-borderStyle: var(--vuuToolbar-borderStyle);\n --vuuOverflowContainer-borderWidth: var(--vuuToolbar-borderWidth);\n height: var(--toolbar-height);\n}\n\n.vuuToolbar-alignCenter {\n --vuuOverflowContainer-justifyContent: center;\n}\n\n.vuuToolbar-alignEnd {\n --vuuOverflowContainer-justifyContent: flex-end;\n}\n\n/* .vuuToolbarItem {\n height: var(--toolbar-item-height);\n} */\n\n.vuuToolbar-withSeparators .vuuOverflowContainer-item:not(:first-child):before {\n content: '';\n position: absolute;\n left: calc(-1 * var(--overflow-item-gap));\n top: calc((var(--toolbar-height) - var(--toolbar-item-height)) /2)
|
|
3
|
+
var toolbarCss = ".vuuToolbar {\n --toolbar-height: var(--vuuToolbar-height, 36px);\n --toolbar-item-height: var(--vuuToolbarItem-height, 100%);\n --vuuOverflowContainer-background: var(--vuuToolbar-background);\n --vuuOverflowContainer-borderColor: var(--vuuToolbar-borderColor);\n --vuuOverflowContainer-borderStyle: var(--vuuToolbar-borderStyle);\n --vuuOverflowContainer-borderWidth: var(--vuuToolbar-borderWidth);\n height: var(--toolbar-height);\n}\n\n.vuuToolbar-alignCenter {\n --vuuOverflowContainer-justifyContent: center;\n}\n\n.vuuToolbar-alignEnd {\n --vuuOverflowContainer-justifyContent: flex-end;\n}\n\n/* .vuuToolbarItem {\n height: var(--toolbar-item-height);\n} */\n\n.vuuToolbar-withSeparators .vuuOverflowContainer-item:not(:first-child):before {\n content: '';\n position: absolute;\n left: calc(-1 * var(--overflow-item-gap));\n /* top: calc((var(--toolbar-height) - var(--toolbar-item-height)) /2); */\n top: 0px;\n width: 1px;\n height: var(--toolbar-item-height);\n background-color: var(--salt-separable-primary-borderColor);\n}\n\n\n.vuuToolbarItem.vuuFocusVisible {\n outline-color: var(--vuuToolbarItem-outlineColor, var(--salt-focused-outlineColor));\n outline-style: dashed;\n outline-width: 1px;\n outline-offset: 0px;\n }\n\n\n .vuuToolbarItem:focus,\n .vuuToolbarItem:focus-visible {\n\n outline-color: var(--vuuToolbarItem-outlineColor, var(--vuu-color-purple-10));\n outline-style: dashed;\n outline-width: 1px;\n outline-offset: 0px;\n\n}\n\n\n ";
|
|
4
4
|
|
|
5
5
|
module.exports = toolbarCss;
|
|
6
6
|
//# sourceMappingURL=Toolbar.css.js.map
|
|
@@ -1 +1 @@
|
|
|
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
|
|
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\";\n\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 return (\n <ComboBox\n className={cx(classBase, className)}\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":";;;;;;;;;;;AAYA,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;AAED,EACE,uBAAAC,cAAA;AAAA,IAACC,aAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAG,CAAA,SAAA,EAAW,SAAS,CAAA;AAAA,MAClC,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;;;;"}
|
|
@@ -79,7 +79,15 @@ const useVuuTypeaheadInput = ({
|
|
|
79
79
|
} else {
|
|
80
80
|
setTypeaheadValues(suggestions);
|
|
81
81
|
if (pendingListFocusRef.current && inputRef.current) {
|
|
82
|
-
|
|
82
|
+
requestAnimationFrame(() => {
|
|
83
|
+
if (inputRef.current) {
|
|
84
|
+
vuuUtils.dispatchKeyboardEvent(
|
|
85
|
+
inputRef.current,
|
|
86
|
+
"keydown",
|
|
87
|
+
"ArrowDown"
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
83
91
|
}
|
|
84
92
|
}
|
|
85
93
|
pendingListFocusRef.current = false;
|
|
@@ -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 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 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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"}
|
|
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 getVuuTable,\n useStateRef,\n NO_DATA_MATCH,\n type CommitHandler,\n dispatchKeyboardEvent,\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 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 requestAnimationFrame(() => {\n if (inputRef.current) {\n // highlight the first option. Doesn't work as expected on Safari\n dispatchKeyboardEvent(\n inputRef.current,\n \"keydown\",\n \"ArrowDown\",\n );\n }\n });\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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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getTypedValue, dispatchCustomEvent } from '@vuu-ui/vuu-utils';
|
|
1
|
+
import { getTypedValue, isRpcSuccess, isRpcError, dispatchCustomEvent } from '@vuu-ui/vuu-utils';
|
|
2
2
|
import { useState, useRef, useMemo, useCallback } from 'react';
|
|
3
3
|
|
|
4
4
|
const stringValueOf = (value) => value?.toString() ?? "";
|
|
@@ -13,85 +13,123 @@ const useEditableText = ({
|
|
|
13
13
|
});
|
|
14
14
|
const initialValueRef = useRef(value?.toString() ?? "");
|
|
15
15
|
const isDirtyRef = useRef(false);
|
|
16
|
+
const isEditingRef = useRef(false);
|
|
16
17
|
useMemo(() => {
|
|
17
18
|
if (initialValueRef.current !== value?.toString()) {
|
|
18
19
|
initialValueRef.current = stringValueOf(value);
|
|
19
20
|
setEditState({ message: "", value: stringValueOf(value) });
|
|
20
21
|
}
|
|
21
22
|
}, [value]);
|
|
22
|
-
const commit = useCallback(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
const commit = useCallback(async () => {
|
|
24
|
+
const { value: value2 } = editState;
|
|
25
|
+
const result = clientSideEditValidationCheck?.(value2, "*");
|
|
26
|
+
if (result?.ok === false) {
|
|
27
|
+
setEditState((state) => ({
|
|
28
|
+
...state,
|
|
29
|
+
message: result?.messages?.join(",")
|
|
30
|
+
}));
|
|
31
|
+
return false;
|
|
32
|
+
} else {
|
|
33
|
+
setEditState((state) => ({ ...state, message: void 0 }));
|
|
34
|
+
const typedValue = getTypedValue(value2, type, true);
|
|
35
|
+
const response = await onEdit?.(
|
|
36
|
+
{ editType: "commit", value: typedValue, isValid: true },
|
|
37
|
+
"commit"
|
|
38
|
+
);
|
|
39
|
+
if (isRpcSuccess(response)) {
|
|
40
|
+
isDirtyRef.current = false;
|
|
41
|
+
initialValueRef.current = value2;
|
|
42
|
+
return true;
|
|
43
|
+
} else if (isRpcError(response)) {
|
|
44
|
+
setEditState((state) => ({
|
|
45
|
+
...state,
|
|
46
|
+
message: response.errorMessage
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}, [clientSideEditValidationCheck, editState, onEdit, type]);
|
|
52
|
+
const handleKeyDown = useCallback(
|
|
53
|
+
async (evt) => {
|
|
54
|
+
const { key, target } = evt;
|
|
55
|
+
const input = target;
|
|
56
|
+
if (key === "Enter") {
|
|
57
|
+
if (isEditingRef.current) {
|
|
58
|
+
if (isDirtyRef.current) {
|
|
59
|
+
const commitSuccessful = await commit();
|
|
60
|
+
if (commitSuccessful) {
|
|
61
|
+
isEditingRef.current = false;
|
|
62
|
+
dispatchCustomEvent(input, "vuu-exit-edit-mode");
|
|
63
|
+
dispatchCustomEvent(input, "vuu-commit");
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
isEditingRef.current = false;
|
|
67
|
+
dispatchCustomEvent(input, "vuu-exit-edit-mode");
|
|
68
|
+
}
|
|
32
69
|
} else {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
70
|
+
isEditingRef.current = true;
|
|
71
|
+
dispatchCustomEvent(input, "vuu-enter-edit-mode");
|
|
72
|
+
input.select();
|
|
73
|
+
}
|
|
74
|
+
} else if (key === "ArrowRight" || key === "ArrowLeft" || key === "ArrowUp" || key === "ArrowDown") {
|
|
75
|
+
if (isEditingRef.current) {
|
|
76
|
+
evt.stopPropagation();
|
|
77
|
+
}
|
|
78
|
+
} else if (evt.key === "Escape") {
|
|
79
|
+
if (isEditingRef.current) {
|
|
80
|
+
if (isDirtyRef.current) {
|
|
81
|
+
const { value: previousValue } = editState;
|
|
40
82
|
isDirtyRef.current = false;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
83
|
+
setEditState({
|
|
84
|
+
value: initialValueRef.current,
|
|
85
|
+
message: void 0
|
|
86
|
+
});
|
|
87
|
+
onEdit?.(
|
|
88
|
+
{
|
|
89
|
+
editType: "cancel",
|
|
90
|
+
isValid: true,
|
|
91
|
+
previousValue,
|
|
92
|
+
value: initialValueRef.current
|
|
93
|
+
},
|
|
94
|
+
"cancel"
|
|
95
|
+
);
|
|
45
96
|
}
|
|
97
|
+
isEditingRef.current = false;
|
|
98
|
+
dispatchCustomEvent(input, "vuu-exit-edit-mode");
|
|
46
99
|
}
|
|
47
|
-
} else {
|
|
48
|
-
dispatchCustomEvent(target, "vuu-commit");
|
|
49
100
|
}
|
|
50
101
|
},
|
|
51
|
-
[
|
|
102
|
+
[commit, editState, onEdit]
|
|
52
103
|
);
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const { value: previousValue } = editState;
|
|
62
|
-
isDirtyRef.current = false;
|
|
63
|
-
setEditState({ value: initialValueRef.current, message: void 0 });
|
|
64
|
-
onEdit?.(
|
|
65
|
-
{
|
|
66
|
-
editType: "cancel",
|
|
67
|
-
isValid: true,
|
|
68
|
-
previousValue,
|
|
69
|
-
value: initialValueRef.current
|
|
70
|
-
},
|
|
71
|
-
"cancel"
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
104
|
+
const beginEditHandler = useCallback((evt) => {
|
|
105
|
+
isEditingRef.current = true;
|
|
106
|
+
dispatchCustomEvent(evt.target, "vuu-enter-edit-mode");
|
|
107
|
+
}, []);
|
|
108
|
+
const handleFocus = useCallback(
|
|
109
|
+
(e) => {
|
|
110
|
+
console.log(`[useEditableText] handleFocus`);
|
|
111
|
+
e.target.addEventListener("vuu-begin-edit", beginEditHandler, true);
|
|
75
112
|
},
|
|
76
|
-
[
|
|
113
|
+
[beginEditHandler]
|
|
77
114
|
);
|
|
78
115
|
const handleBlur = useCallback(
|
|
79
|
-
(evt) => {
|
|
80
|
-
|
|
81
|
-
|
|
116
|
+
async (evt) => {
|
|
117
|
+
evt.target.removeEventListener("vuu-begin-edit", beginEditHandler, true);
|
|
118
|
+
if (isEditingRef.current) {
|
|
119
|
+
if (isDirtyRef.current) {
|
|
120
|
+
const commitSuccessful = await commit();
|
|
121
|
+
console.log({ commitSuccessful });
|
|
122
|
+
}
|
|
123
|
+
isEditingRef.current = false;
|
|
124
|
+
dispatchCustomEvent(evt.target, "vuu-exit-edit-mode");
|
|
82
125
|
}
|
|
83
126
|
},
|
|
84
|
-
[commit]
|
|
127
|
+
[beginEditHandler, commit]
|
|
85
128
|
);
|
|
86
129
|
const handleChange = useCallback(
|
|
87
130
|
(evt) => {
|
|
88
131
|
const { value: value2 } = evt.target;
|
|
89
132
|
const typedValue = getTypedValue(value2, type, true);
|
|
90
|
-
console.log(
|
|
91
|
-
`[useEditableText] handleChange '${value2}' typedValue ${typedValue}
|
|
92
|
-
initial value ${initialValueRef.current}
|
|
93
|
-
`
|
|
94
|
-
);
|
|
95
133
|
isDirtyRef.current = value2 !== initialValueRef.current;
|
|
96
134
|
const result = clientSideEditValidationCheck?.(value2, "change");
|
|
97
135
|
setEditState({ value: value2 });
|
|
@@ -106,6 +144,10 @@ const useEditableText = ({
|
|
|
106
144
|
if (result?.ok === false) {
|
|
107
145
|
setEditState({ value: value2, message: result.messages?.join(",") });
|
|
108
146
|
}
|
|
147
|
+
if (!isEditingRef.current) {
|
|
148
|
+
isEditingRef.current = true;
|
|
149
|
+
dispatchCustomEvent(evt.target, "vuu-enter-edit-mode");
|
|
150
|
+
}
|
|
109
151
|
},
|
|
110
152
|
[clientSideEditValidationCheck, onEdit, type]
|
|
111
153
|
);
|
|
@@ -113,6 +155,7 @@ const useEditableText = ({
|
|
|
113
155
|
//TODO why are we detecting commit here, why not use VuuInput ?
|
|
114
156
|
inputProps: {
|
|
115
157
|
onBlur: handleBlur,
|
|
158
|
+
onFocus: handleFocus,
|
|
116
159
|
onKeyDown: handleKeyDown
|
|
117
160
|
},
|
|
118
161
|
onChange: handleChange,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEditableText.js","sources":["../../../../packages/vuu-ui-controls/src/editable/useEditableText.ts"],"sourcesContent":["import type { DataValueValidationChecker } from \"@vuu-ui/vuu-data-types\";\nimport { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport type { DataItemEditHandler } from \"@vuu-ui/vuu-table-types\";\nimport { dispatchCustomEvent, getTypedValue } from \"@vuu-ui/vuu-utils\";\nimport {\n FocusEventHandler,\n FormEventHandler,\n KeyboardEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport interface EditableTextHookProps<\n T extends VuuRowDataItemType = VuuRowDataItemType,\n> {\n clientSideEditValidationCheck?: DataValueValidationChecker;\n value?: T;\n onEdit?: DataItemEditHandler;\n type?: \"string\" | \"number\" | \"boolean\";\n}\n\ntype EditState = {\n message?: string;\n value: string;\n};\n\nconst stringValueOf = (value?: VuuRowDataItemType) => value?.toString() ?? \"\";\n\nexport const useEditableText = <T extends string | number | boolean = string>({\n clientSideEditValidationCheck,\n value,\n onEdit,\n type = \"string\",\n}: EditableTextHookProps<T>) => {\n const [editState, setEditState] = useState<EditState>({\n value: stringValueOf(value),\n });\n const initialValueRef = useRef<string>(value?.toString() ?? \"\");\n const isDirtyRef = useRef(false);\n\n useMemo(() => {\n if (initialValueRef.current !== value?.toString()) {\n initialValueRef.current = stringValueOf(value);\n setEditState({ message: \"\", value: stringValueOf(value) });\n }\n }, [value]);\n\n const commit = useCallback(\n async (target: HTMLElement) => {\n const { value } = editState;\n if (isDirtyRef.current) {\n const result = clientSideEditValidationCheck?.(value, \"*\");\n if (result?.ok === false) {\n setEditState((state) => ({\n ...state,\n message: result?.messages?.join(\",\"),\n }));\n } else {\n setEditState((state) => ({ ...state, message: undefined }));\n const typedValue = getTypedValue(value, type, true);\n const response = await onEdit?.(\n { editType: \"commit\", value: typedValue, isValid: true },\n \"commit\",\n );\n if (response === true) {\n isDirtyRef.current = false;\n initialValueRef.current = value;\n dispatchCustomEvent(target, \"vuu-commit\");\n } else if (typeof response === \"string\") {\n setEditState((state) => ({ ...state, message: response }));\n }\n }\n } else {\n // why, if not dirty ?\n dispatchCustomEvent(target, \"vuu-commit\");\n }\n },\n [clientSideEditValidationCheck, editState, onEdit, type],\n );\n\n const handleKeyDown = useCallback(\n (evt: KeyboardEvent<HTMLElement>) => {\n if (evt.key === \"Enter\") {\n commit(evt.target as HTMLElement);\n } else if (\n evt.key === \"ArrowRight\" ||\n evt.key === \"ArrowLeft\" ||\n evt.key === \"ArrowUp\" ||\n evt.key === \"ArrowDown\"\n ) {\n evt.stopPropagation();\n } else if (evt.key === \"Escape\") {\n if (isDirtyRef.current) {\n const { value: previousValue } = editState;\n isDirtyRef.current = false;\n setEditState({ value: initialValueRef.current, message: undefined });\n // this assumes the original value was valid, is that safe ?\n onEdit?.(\n {\n editType: \"cancel\",\n isValid: true,\n previousValue,\n value: initialValueRef.current,\n },\n \"cancel\",\n );\n }\n }\n },\n [commit, editState, onEdit],\n );\n\n const handleBlur = useCallback<FocusEventHandler<HTMLElement>>(\n (evt) => {\n if (isDirtyRef.current) {\n commit(evt.target as HTMLElement);\n }\n },\n [commit],\n );\n\n const handleChange = useCallback<FormEventHandler>(\n (evt) => {\n const { value } = evt.target as HTMLInputElement;\n const typedValue = getTypedValue(value, type, true);\n console.log(\n `[useEditableText] handleChange '${value}' typedValue ${typedValue}\n initial value ${initialValueRef.current}\n `,\n );\n isDirtyRef.current = value !== initialValueRef.current;\n const result = clientSideEditValidationCheck?.(value, \"change\");\n setEditState({ value });\n\n onEdit?.(\n {\n editType: \"change\",\n isValid: result?.ok !== false,\n value: typedValue,\n },\n \"change\",\n );\n if (result?.ok === false) {\n setEditState({ value, message: result.messages?.join(\",\") });\n }\n },\n [clientSideEditValidationCheck, onEdit, type],\n );\n\n return {\n //TODO why are we detecting commit here, why not use VuuInput ?\n inputProps: {\n onBlur: handleBlur,\n onKeyDown: handleKeyDown,\n },\n onChange: handleChange,\n value: editState.value,\n warningMessage: editState.message,\n };\n};\n"],"names":["value"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useEditableText.js","sources":["../../../../packages/vuu-ui-controls/src/editable/useEditableText.ts"],"sourcesContent":["import type { DataValueValidationChecker } from \"@vuu-ui/vuu-data-types\";\nimport { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport type { TableCellEditHandler } from \"@vuu-ui/vuu-table-types\";\nimport {\n dispatchCustomEvent,\n getTypedValue,\n isRpcError,\n isRpcSuccess,\n} from \"@vuu-ui/vuu-utils\";\nimport {\n FocusEventHandler,\n FormEventHandler,\n KeyboardEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport interface EditableTextHookProps<\n T extends VuuRowDataItemType = VuuRowDataItemType,\n> {\n clientSideEditValidationCheck?: DataValueValidationChecker;\n value?: T;\n onEdit?: TableCellEditHandler;\n type?: \"string\" | \"number\" | \"boolean\";\n}\n\ntype EditState = {\n message?: string;\n value: string;\n};\n\nconst stringValueOf = (value?: VuuRowDataItemType) => value?.toString() ?? \"\";\n\nexport const useEditableText = <T extends string | number | boolean = string>({\n clientSideEditValidationCheck,\n value,\n onEdit,\n type = \"string\",\n}: EditableTextHookProps<T>) => {\n const [editState, setEditState] = useState<EditState>({\n value: stringValueOf(value),\n });\n const initialValueRef = useRef<string>(value?.toString() ?? \"\");\n const isDirtyRef = useRef(false);\n const isEditingRef = useRef(false);\n\n useMemo(() => {\n if (initialValueRef.current !== value?.toString()) {\n initialValueRef.current = stringValueOf(value);\n setEditState({ message: \"\", value: stringValueOf(value) });\n }\n }, [value]);\n\n const commit = useCallback(async () => {\n const { value } = editState;\n const result = clientSideEditValidationCheck?.(value, \"*\");\n if (result?.ok === false) {\n setEditState((state) => ({\n ...state,\n message: result?.messages?.join(\",\"),\n }));\n return false;\n } else {\n setEditState((state) => ({ ...state, message: undefined }));\n const typedValue = getTypedValue(value, type, true);\n const response = await onEdit?.(\n { editType: \"commit\", value: typedValue, isValid: true },\n \"commit\",\n );\n if (isRpcSuccess(response)) {\n isDirtyRef.current = false;\n initialValueRef.current = value;\n return true;\n } else if (isRpcError(response)) {\n setEditState((state) => ({\n ...state,\n message: response.errorMessage,\n }));\n }\n }\n return false;\n }, [clientSideEditValidationCheck, editState, onEdit, type]);\n\n const handleKeyDown = useCallback(\n async (evt: KeyboardEvent<HTMLElement>) => {\n const { key, target } = evt;\n // console.log(`[useEditableText] handleKeyDown`);\n const input = target as HTMLInputElement;\n if (key === \"Enter\") {\n // console.log(\n // `[useEditableText] ENTER isEditing ? ${isEditingRef.current}, isDirty ${isDirtyRef.current}`,\n // );\n if (isEditingRef.current) {\n if (isDirtyRef.current) {\n // console.log(\" ...await commit\");\n const commitSuccessful = await commit();\n if (commitSuccessful) {\n isEditingRef.current = false;\n dispatchCustomEvent(input, \"vuu-exit-edit-mode\");\n dispatchCustomEvent(input, \"vuu-commit\");\n }\n } else {\n isEditingRef.current = false;\n dispatchCustomEvent(input, \"vuu-exit-edit-mode\");\n }\n } else {\n isEditingRef.current = true;\n dispatchCustomEvent(input, \"vuu-enter-edit-mode\");\n input.select();\n }\n } else if (\n key === \"ArrowRight\" ||\n key === \"ArrowLeft\" ||\n key === \"ArrowUp\" ||\n key === \"ArrowDown\"\n ) {\n if (isEditingRef.current) {\n // console.log(\n // `[useEditableText] handleKeydown, arrowkey whilst editing, stop propagation`,\n // );\n evt.stopPropagation();\n } else {\n // console.log(\n // `[useEditableText] handleKeydown, arrowkey, not editing so let it bubble`,\n // );\n // evt.preventDefault();\n }\n } else if (evt.key === \"Escape\") {\n if (isEditingRef.current) {\n // console.log(\n // `[useEditableText] ESC whilst editing, dirty ? ${isDirtyRef.current}`,\n // );\n if (isDirtyRef.current) {\n const { value: previousValue } = editState;\n isDirtyRef.current = false;\n setEditState({\n value: initialValueRef.current,\n message: undefined,\n });\n // this assumes the original value was valid, is that safe ?\n onEdit?.(\n {\n editType: \"cancel\",\n isValid: true,\n previousValue,\n value: initialValueRef.current,\n },\n \"cancel\",\n );\n }\n isEditingRef.current = false;\n dispatchCustomEvent(input, \"vuu-exit-edit-mode\");\n }\n } /* else if (isEditingRef.current === false && isCharacterKey(key)) {\n isEditingRef.current = true;\n dispatchCustomEvent(evt.target as HTMLElement, \"vuu-enter-edit-mode\");\n }*/\n },\n [commit, editState, onEdit],\n );\n\n const beginEditHandler = useCallback((evt: Event) => {\n // console.log(\"begin edit handler\");\n isEditingRef.current = true;\n dispatchCustomEvent(evt.target as HTMLElement, \"vuu-enter-edit-mode\");\n }, []);\n\n const handleFocus = useCallback<FocusEventHandler<HTMLElement>>(\n (e) => {\n console.log(`[useEditableText] handleFocus`);\n e.target.addEventListener(\"vuu-begin-edit\", beginEditHandler, true);\n },\n [beginEditHandler],\n );\n\n const handleBlur = useCallback<FocusEventHandler<HTMLElement>>(\n async (evt) => {\n evt.target.removeEventListener(\"vuu-begin-edit\", beginEditHandler, true);\n if (isEditingRef.current) {\n if (isDirtyRef.current) {\n const commitSuccessful = await commit();\n console.log({ commitSuccessful });\n }\n isEditingRef.current = false;\n dispatchCustomEvent(evt.target, \"vuu-exit-edit-mode\");\n }\n },\n [beginEditHandler, commit],\n );\n\n const handleChange = useCallback<FormEventHandler>(\n (evt) => {\n const { value } = evt.target as HTMLInputElement;\n const typedValue = getTypedValue(value, type, true);\n // console.log(\n // `[useEditableText] handleChange '${value}' typedValue ${typedValue}\n // initial value ${initialValueRef.current}\n // `,\n // );\n isDirtyRef.current = value !== initialValueRef.current;\n const result = clientSideEditValidationCheck?.(value, \"change\");\n setEditState({ value });\n\n onEdit?.(\n {\n editType: \"change\",\n isValid: result?.ok !== false,\n value: typedValue,\n },\n \"change\",\n );\n if (result?.ok === false) {\n setEditState({ value, message: result.messages?.join(\",\") });\n }\n\n if (!isEditingRef.current) {\n isEditingRef.current = true;\n dispatchCustomEvent(evt.target as HTMLElement, \"vuu-enter-edit-mode\");\n }\n },\n [clientSideEditValidationCheck, onEdit, type],\n );\n\n return {\n //TODO why are we detecting commit here, why not use VuuInput ?\n inputProps: {\n onBlur: handleBlur,\n onFocus: handleFocus,\n onKeyDown: handleKeyDown,\n },\n onChange: handleChange,\n value: editState.value,\n warningMessage: editState.message,\n };\n};\n"],"names":["value"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var iconButtonCss = ".vuuIconButton {\n --saltButton-padding: 0;\n --saltButton-minWidth: var(--salt-size-base);\n}\n";
|
|
1
|
+
var iconButtonCss = ".vuuIconButton.saltButton {\n --saltButton-padding: 0;\n --saltButton-minWidth: var(--salt-size-base);\n width: calc(var(--salt-size-base) + var(--salt-size-fixed-400));\n}\n";
|
|
2
2
|
|
|
3
3
|
export { iconButtonCss as default };
|
|
4
4
|
//# sourceMappingURL=IconButton.css.js.map
|
|
@@ -73,17 +73,26 @@ const TablePicker = ({
|
|
|
73
73
|
IconButton,
|
|
74
74
|
{
|
|
75
75
|
...getReferenceProps(),
|
|
76
|
+
appearance: "transparent",
|
|
76
77
|
"data-embedded": true,
|
|
77
78
|
ref: reference,
|
|
78
79
|
icon: "chevron-down",
|
|
79
80
|
onKeyDown,
|
|
80
|
-
|
|
81
|
+
sentiment: "neutral"
|
|
81
82
|
}
|
|
82
83
|
),
|
|
83
84
|
[getReferenceProps, onKeyDown, reference]
|
|
84
85
|
);
|
|
85
86
|
return /* @__PURE__ */ jsxs("div", { ...htmlAttributes, className: classBase, ref: containerRef, children: [
|
|
86
|
-
/* @__PURE__ */ jsx(
|
|
87
|
+
/* @__PURE__ */ jsx(
|
|
88
|
+
Input,
|
|
89
|
+
{
|
|
90
|
+
...inputProps,
|
|
91
|
+
bordered: true,
|
|
92
|
+
endAdornment,
|
|
93
|
+
value
|
|
94
|
+
}
|
|
95
|
+
),
|
|
87
96
|
/* @__PURE__ */ jsx(
|
|
88
97
|
FloatingTable,
|
|
89
98
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TablePicker.js","sources":["../../../../packages/vuu-ui-controls/src/instrument-picker/TablePicker.tsx"],"sourcesContent":["import type { DataSourceRowObject, TableSchema } from \"@vuu-ui/vuu-data-types\";\nimport { Table, type TableProps } from \"@vuu-ui/vuu-table\";\nimport {\n Input,\n useFloatingComponent,\n useIdMemo,\n type FloatingComponentProps,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport cx from \"clsx\";\nimport { forwardRef, useMemo, type HTMLAttributes } from \"react\";\nimport { IconButton } from \"../icon-button\";\nimport tablePickerCss from \"./TablePicker.css\";\nimport { useTablePicker } from \"./useTablePicker\";\n\nconst classBase = \"vuuTablePicker\";\n\ninterface FloatingTableProps extends FloatingComponentProps {\n collapsed?: boolean;\n}\n\nexport interface TablePickerProps\n extends Omit<HTMLAttributes<HTMLElement>, \"onSelect\">,\n Pick<TableProps, \"onSelect\"> {\n TableProps?: Pick<TableProps, \"config\">;\n rowToString?: (row: DataSourceRowObject) => string;\n schema: TableSchema;\n searchColumns?: string[];\n}\n\nconst FloatingTable = forwardRef<HTMLDivElement, FloatingTableProps>(\n function FloatingTable(\n { children, className, collapsed, open, ...props },\n forwardedRef,\n ) {\n const { Component: FloatingComponent } = useFloatingComponent();\n return (\n <FloatingComponent\n className={cx(\n `${classBase}-floating-table`,\n {\n [`${classBase}-collapsed`]: collapsed,\n },\n className,\n )}\n role=\"listbox\"\n open={open}\n {...props}\n ref={forwardedRef}\n >\n {children}\n </FloatingComponent>\n );\n },\n);\n\nexport const TablePicker = ({\n TableProps,\n onSelect,\n rowToString,\n schema,\n searchColumns,\n ...htmlAttributes\n}: TablePickerProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-table-picker\",\n css: tablePickerCss,\n window: targetWindow,\n });\n\n const tableId = useIdMemo();\n\n const {\n containerRef,\n dataSource,\n highlightedIndex,\n floatingUIProps: { x, y, strategy, floating, reference },\n inputProps,\n interactionPropGetters: { getFloatingProps, getReferenceProps },\n onKeyDown,\n open,\n tableConfig,\n tableHandlers,\n tableRef,\n value,\n width,\n } = useTablePicker({\n TableProps,\n rowToString,\n onSelect,\n schema,\n searchColumns,\n });\n\n const endAdornment = useMemo(\n () => (\n <IconButton\n {...getReferenceProps()}\n data-embedded\n ref={reference}\n icon=\"chevron-down\"\n onKeyDown={onKeyDown}\n
|
|
1
|
+
{"version":3,"file":"TablePicker.js","sources":["../../../../packages/vuu-ui-controls/src/instrument-picker/TablePicker.tsx"],"sourcesContent":["import type { DataSourceRowObject, TableSchema } from \"@vuu-ui/vuu-data-types\";\nimport { Table, type TableProps } from \"@vuu-ui/vuu-table\";\nimport {\n Input,\n useFloatingComponent,\n useIdMemo,\n type FloatingComponentProps,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport cx from \"clsx\";\nimport { forwardRef, useMemo, type HTMLAttributes } from \"react\";\nimport { IconButton } from \"../icon-button\";\nimport tablePickerCss from \"./TablePicker.css\";\nimport { useTablePicker } from \"./useTablePicker\";\n\nconst classBase = \"vuuTablePicker\";\n\ninterface FloatingTableProps extends FloatingComponentProps {\n collapsed?: boolean;\n}\n\nexport interface TablePickerProps\n extends Omit<HTMLAttributes<HTMLElement>, \"onSelect\">,\n Pick<TableProps, \"onSelect\"> {\n TableProps?: Pick<TableProps, \"config\">;\n rowToString?: (row: DataSourceRowObject) => string;\n schema: TableSchema;\n searchColumns?: string[];\n}\n\nconst FloatingTable = forwardRef<HTMLDivElement, FloatingTableProps>(\n function FloatingTable(\n { children, className, collapsed, open, ...props },\n forwardedRef,\n ) {\n const { Component: FloatingComponent } = useFloatingComponent();\n return (\n <FloatingComponent\n className={cx(\n `${classBase}-floating-table`,\n {\n [`${classBase}-collapsed`]: collapsed,\n },\n className,\n )}\n role=\"listbox\"\n open={open}\n {...props}\n ref={forwardedRef}\n >\n {children}\n </FloatingComponent>\n );\n },\n);\n\nexport const TablePicker = ({\n TableProps,\n onSelect,\n rowToString,\n schema,\n searchColumns,\n ...htmlAttributes\n}: TablePickerProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-table-picker\",\n css: tablePickerCss,\n window: targetWindow,\n });\n\n const tableId = useIdMemo();\n\n const {\n containerRef,\n dataSource,\n highlightedIndex,\n floatingUIProps: { x, y, strategy, floating, reference },\n inputProps,\n interactionPropGetters: { getFloatingProps, getReferenceProps },\n onKeyDown,\n open,\n tableConfig,\n tableHandlers,\n tableRef,\n value,\n width,\n } = useTablePicker({\n TableProps,\n rowToString,\n onSelect,\n schema,\n searchColumns,\n });\n\n const endAdornment = useMemo(\n () => (\n <IconButton\n {...getReferenceProps()}\n appearance=\"transparent\"\n data-embedded\n ref={reference}\n icon=\"chevron-down\"\n onKeyDown={onKeyDown}\n sentiment=\"neutral\"\n />\n ),\n [getReferenceProps, onKeyDown, reference],\n );\n\n return (\n <div {...htmlAttributes} className={classBase} ref={containerRef}>\n <Input\n {...inputProps}\n bordered\n endAdornment={endAdornment}\n value={value}\n />\n <FloatingTable\n {...getFloatingProps()}\n collapsed={!open}\n id={tableId}\n open={open}\n left={x + 3}\n position={strategy}\n ref={floating}\n top={y + 3}\n >\n <Table\n {...tableHandlers}\n config={tableConfig}\n dataSource={dataSource}\n highlightedIndex={highlightedIndex}\n maxViewportRowLimit={10}\n navigationStyle=\"row\"\n ref={tableRef}\n selectionModel=\"single\"\n showColumnHeaders={false}\n width={width - 3}\n />\n </FloatingTable>\n </div>\n );\n};\n"],"names":["FloatingTable"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var splitButtonCss = ".vuuSplitButton {\n --saltButton-background: var(--split-background);\n --saltButton-background-hover: var(--split-background);\n --vuuPopupMenu-background: var(--split-background);\n --vuuPopupMenu-iconSize: 20px;\n\n /** less verbose local refs */\n --background: var(--vuuSplitButton-background);\n --foreground: var(--vuuSplitButton-foreground);\n --background-hover: var(--vuuSplitButton-background-hover);\n --foreground-hover: var(--vuuSplitButton-foreground-hover);\n\n --border-radius: var(--vuuSplitButton-borderRadius,
|
|
1
|
+
var splitButtonCss = ".vuuSplitButton {\n --saltButton-background: var(--split-background);\n --saltButton-background-hover: var(--split-background);\n --vuuPopupMenu-background: var(--split-background);\n --vuuPopupMenu-iconSize: 20px;\n\n /** less verbose local refs */\n --background: var(--vuuSplitButton-background);\n --foreground: var(--vuuSplitButton-foreground);\n --background-hover: var(--vuuSplitButton-background-hover);\n --foreground-hover: var(--vuuSplitButton-foreground-hover);\n\n --border-radius: var(--vuuSplitButton-borderRadius, var(--salt-palette-corner-weaker));\n --main-border-radius: var(--border-radius) 0 0 var(--border-radius);\n --trigger-border-radius: 0 var(--border-radius) var(--border-radius) 0;\n --trigger-border-style: solid solid solid none;\n\n align-items: center;\n border: none;\n border-radius: var(--border-radius);\n display: flex;\n\n .vuuSplitButton-main {\n border-radius: var(--main-border-radius);\n }\n .vuuSplitButton-trigger {\n border-radius: var(--trigger-border-radius);\n }\n}\n\n.vuuSplitButton.vuuFocusVisible {\n .saltButton {\n outline-style: none;\n }\n &.vuuSplitButton-primary {\n --split-background: var(\n --background-hover,\n var(--salt-actionable-bold-background-hover)\n );\n }\n &.vuuSplitButton-secondary {\n --split-background: var(\n --background-hover,\n var(--salt-actionable-subtle-background-hover)\n );\n }\n &.vuuSplitButton-cta {\n --split-background: var(\n --background-hover,\n var(--salt-actionable-accented-bold-background-hover)\n );\n .vuuSplitButton-trigger {\n --vuu-icon-color: var(--salt-actionable-bold-foreground-hover);\n }\n }\n}\n\n/** TODO move into theme */\n.vuuFocusVisible {\n outline-style: var(--salt-focused-outlineStyle);\n outline-width: var(--salt-focused-outlineWidth);\n outline-color: var(--salt-focused-outlineColor);\n outline-offset: var(--salt-focused-outlineOffset);\n}\n\n.vuuSplitButton-primary {\n --split-background: var(\n --background,\n var(--salt-actionable-bold-background)\n );\n --split-background-active: var(--salt-actionable-bold-background-active);\n --split-color-active: var(--salt-actionable-bold-foreground-active);\n}\n\n.vuuSplitButton-primary:hover:not(.vuuSplitButton-disabled) {\n --vuuButton-borderColor: var(--split-background);\n --saltButton-borderColor: var(--split-background);\n --split-background: var(\n --background-hover,\n var(--salt-actionable-bold-background-hover)\n );\n .saltButton {\n --saltButton-text-color: var(--salt-actionable-bold-foreground-hover);\n }\n}\n\n.vuuSplitButton-secondary {\n --saltButton-borderColor: var(--split-background);\n --split-background: var(\n --background,\n var(--salt-actionable-subtle-background)\n );\n --split-background-active: var(--salt-actionable-subtle-background-active);\n --split-color-active: var(--salt-actionable-subtle-foreground-active);\n}\n\n.vuuSplitButton-secondary:hover:not(.vuuSplitButton-disabled) {\n --vuuButton-borderColor: var(--split-background);\n --split-background: var(--salt-actionable-subtle-background-hover);\n .saltButton {\n --saltButton-text-color: var(--salt-actionable-subtle-foreground-hover);\n }\n}\n\n.vuuSplitButton-cta {\n --split-background: var(--background, var(--salt-actionable-accented-bold-background));\n --split-background-active: var(--salt-actionable-accented-bold-background-active);\n --split-color-active: var(--salt-actionable-bold-foreground-active);\n}\n.vuuSplitButton-cta:hover:not(.vuuSplitButton-disabled) {\n --vuuButton-borderColor: var(--split-background);\n --split-background: var(--salt-actionable-accented-bold-background-hover);\n --split-color: var(--salt-actionable-bold-foreground-hover);\n .saltButton {\n --saltButton-text-color: var(--salt-actionable-bold-foreground-hover);\n --vuu-icon-color: var(--salt-actionable-bold-foreground-hover);\n }\n}\n\n.vuuSplitButton:has(\n .vuuSplitButton-main:active,\n .vuuSplitButton-main.saltButton-active\n ) {\n --split-background: var(--split-background-active);\n .vuuSplitButton-trigger {\n --vuu-icon-color: var(--split-color-active);\n }\n}\n";
|
|
2
2
|
|
|
3
3
|
export { splitButtonCss as default };
|
|
4
4
|
//# sourceMappingURL=SplitButton.css.js.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { PopupMenu } from '@vuu-ui/vuu-popups';
|
|
3
2
|
import { useForkRef, Button } from '@salt-ds/core';
|
|
4
|
-
import { forwardRef } from 'react';
|
|
5
|
-
import { useSplitButton } from './useSplitButton.js';
|
|
6
|
-
import cx from 'clsx';
|
|
7
3
|
import { useComponentCssInjection } from '@salt-ds/styles';
|
|
8
4
|
import { useWindow } from '@salt-ds/window';
|
|
9
|
-
import splitButtonCss from './SplitButton.css.js';
|
|
10
5
|
import { ContextMenuProvider } from '@vuu-ui/vuu-context-menu';
|
|
6
|
+
import { PopupMenu } from '@vuu-ui/vuu-popups';
|
|
7
|
+
import cx from 'clsx';
|
|
8
|
+
import { forwardRef } from 'react';
|
|
9
|
+
import { useSplitButton } from './useSplitButton.js';
|
|
10
|
+
import splitButtonCss from './SplitButton.css.js';
|
|
11
11
|
|
|
12
12
|
const classBase = "vuuSplitButton";
|
|
13
13
|
const SplitButton = forwardRef(
|
|
@@ -52,10 +52,11 @@ const SplitButton = forwardRef(
|
|
|
52
52
|
Button,
|
|
53
53
|
{
|
|
54
54
|
...ButtonProps2,
|
|
55
|
+
appearance: "solid",
|
|
55
56
|
className: `${classBase}-main`,
|
|
56
57
|
disabled,
|
|
57
58
|
ref: buttonRef,
|
|
58
|
-
|
|
59
|
+
sentiment: "neutral",
|
|
59
60
|
children
|
|
60
61
|
}
|
|
61
62
|
),
|
|
@@ -63,11 +64,12 @@ const SplitButton = forwardRef(
|
|
|
63
64
|
PopupMenu,
|
|
64
65
|
{
|
|
65
66
|
...PopupMenuProps2,
|
|
67
|
+
appearance: "solid",
|
|
66
68
|
className: `${classBase}-trigger`,
|
|
67
69
|
disabled,
|
|
68
70
|
icon: PopupMenuProps2?.icon ?? "chevron-down",
|
|
69
71
|
tabIndex: segmented ? 0 : -1,
|
|
70
|
-
|
|
72
|
+
sentiment: "neutral"
|
|
71
73
|
}
|
|
72
74
|
)
|
|
73
75
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SplitButton.js","sources":["../../../../packages/vuu-ui-controls/src/split-button/SplitButton.tsx"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"SplitButton.js","sources":["../../../../packages/vuu-ui-controls/src/split-button/SplitButton.tsx"],"sourcesContent":["import { Button, ButtonProps, useForkRef } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { ContextMenuProvider } from \"@vuu-ui/vuu-context-menu\";\nimport { PopupMenu, PopupMenuProps } from \"@vuu-ui/vuu-popups\";\nimport cx from \"clsx\";\nimport { forwardRef, HTMLAttributes } from \"react\";\nimport { useSplitButton } from \"./useSplitButton\";\n\nimport splitButtonCss from \"./SplitButton.css\";\n\nexport interface SplitButtonProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"onClick\">,\n Pick<ButtonProps, \"onClick\"> {\n ButtonProps?: Partial<Omit<ButtonProps, \"onClick\" | \"variant\">>;\n PopupMenuProps?: Partial<PopupMenuProps>;\n disabled?: boolean;\n segmented?: boolean;\n variant?: ButtonProps[\"variant\"];\n}\n\nconst classBase = \"vuuSplitButton\";\n\nexport const SplitButton = forwardRef<HTMLDivElement, SplitButtonProps>(\n function SplitButton(\n {\n ButtonProps: ButtonPropsProp,\n PopupMenuProps: PopupMenuPropsProp,\n children,\n className,\n disabled = false,\n onClick,\n segmented = false,\n variant = \"primary\",\n ...htmlAttributes\n },\n forwardedRef,\n ) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-split-button\",\n css: splitButtonCss,\n window: targetWindow,\n });\n\n const { ButtonProps, buttonRef, rootRef, PopupMenuProps, ...rootProps } =\n useSplitButton({\n ButtonProps: ButtonPropsProp,\n PopupMenuProps: PopupMenuPropsProp,\n classBase,\n onClick,\n segmented,\n });\n\n return (\n <ContextMenuProvider>\n <div\n {...htmlAttributes}\n {...rootProps}\n className={cx(classBase, `${classBase}-${variant}`, className, {\n [`${classBase}-disabled`]: disabled,\n [`${classBase}-segmented`]: segmented,\n })}\n ref={useForkRef(forwardedRef, rootRef)}\n data-showcase-center\n tabIndex={-1}\n >\n <Button\n {...ButtonProps}\n appearance=\"solid\"\n className={`${classBase}-main`}\n disabled={disabled}\n ref={buttonRef}\n sentiment=\"neutral\"\n >\n {children}\n </Button>\n <PopupMenu\n {...PopupMenuProps}\n appearance=\"solid\"\n className={`${classBase}-trigger`}\n disabled={disabled}\n icon={PopupMenuProps?.icon ?? \"chevron-down\"}\n tabIndex={segmented ? 0 : -1}\n sentiment=\"neutral\"\n />\n </div>\n </ContextMenuProvider>\n );\n },\n);\n"],"names":["SplitButton","ButtonProps","PopupMenuProps"],"mappings":";;;;;;;;;;;AAqBA,MAAM,SAAY,GAAA,gBAAA;AAEX,MAAM,WAAc,GAAA,UAAA;AAAA,EACzB,SAASA,YACP,CAAA;AAAA,IACE,WAAa,EAAA,eAAA;AAAA,IACb,cAAgB,EAAA,kBAAA;AAAA,IAChB,QAAA;AAAA,IACA,SAAA;AAAA,IACA,QAAW,GAAA,KAAA;AAAA,IACX,OAAA;AAAA,IACA,SAAY,GAAA,KAAA;AAAA,IACZ,OAAU,GAAA,SAAA;AAAA,IACV,GAAG;AAAA,KAEL,YACA,EAAA;AACA,IAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,IAAyB,wBAAA,CAAA;AAAA,MACvB,MAAQ,EAAA,kBAAA;AAAA,MACR,GAAK,EAAA,cAAA;AAAA,MACL,MAAQ,EAAA;AAAA,KACT,CAAA;AAED,IAAM,MAAA,EAAE,WAAAC,EAAAA,YAAAA,EAAa,SAAW,EAAA,OAAA,EAAS,gBAAAC,eAAgB,EAAA,GAAG,SAAU,EAAA,GACpE,cAAe,CAAA;AAAA,MACb,WAAa,EAAA,eAAA;AAAA,MACb,cAAgB,EAAA,kBAAA;AAAA,MAChB,SAAA;AAAA,MACA,OAAA;AAAA,MACA;AAAA,KACD,CAAA;AAEH,IAAA,2BACG,mBACC,EAAA,EAAA,QAAA,kBAAA,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACE,GAAG,cAAA;AAAA,QACH,GAAG,SAAA;AAAA,QACJ,SAAA,EAAW,GAAG,SAAW,EAAA,CAAA,EAAG,SAAS,CAAI,CAAA,EAAA,OAAO,IAAI,SAAW,EAAA;AAAA,UAC7D,CAAC,CAAA,EAAG,SAAS,CAAA,SAAA,CAAW,GAAG,QAAA;AAAA,UAC3B,CAAC,CAAA,EAAG,SAAS,CAAA,UAAA,CAAY,GAAG;AAAA,SAC7B,CAAA;AAAA,QACD,GAAA,EAAK,UAAW,CAAA,YAAA,EAAc,OAAO,CAAA;AAAA,QACrC,sBAAoB,EAAA,IAAA;AAAA,QACpB,QAAU,EAAA,CAAA,CAAA;AAAA,QAEV,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACE,GAAGD,YAAAA;AAAA,cACJ,UAAW,EAAA,OAAA;AAAA,cACX,SAAA,EAAW,GAAG,SAAS,CAAA,KAAA,CAAA;AAAA,cACvB,QAAA;AAAA,cACA,GAAK,EAAA,SAAA;AAAA,cACL,SAAU,EAAA,SAAA;AAAA,cAET;AAAA;AAAA,WACH;AAAA,0BACA,GAAA;AAAA,YAAC,SAAA;AAAA,YAAA;AAAA,cACE,GAAGC,eAAAA;AAAA,cACJ,UAAW,EAAA,OAAA;AAAA,cACX,SAAA,EAAW,GAAG,SAAS,CAAA,QAAA,CAAA;AAAA,cACvB,QAAA;AAAA,cACA,IAAA,EAAMA,iBAAgB,IAAQ,IAAA,cAAA;AAAA,cAC9B,QAAA,EAAU,YAAY,CAAI,GAAA,CAAA,CAAA;AAAA,cAC1B,SAAU,EAAA;AAAA;AAAA;AACZ;AAAA;AAAA,KAEJ,EAAA,CAAA;AAAA;AAGN;;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var toolbarCss = ".vuuToolbar {\n --toolbar-height: var(--vuuToolbar-height, 36px);\n --toolbar-item-height: var(--vuuToolbarItem-height, 100%);\n --vuuOverflowContainer-background: var(--vuuToolbar-background);\n --vuuOverflowContainer-borderColor: var(--vuuToolbar-borderColor);\n --vuuOverflowContainer-borderStyle: var(--vuuToolbar-borderStyle);\n --vuuOverflowContainer-borderWidth: var(--vuuToolbar-borderWidth);\n height: var(--toolbar-height);\n}\n\n.vuuToolbar-alignCenter {\n --vuuOverflowContainer-justifyContent: center;\n}\n\n.vuuToolbar-alignEnd {\n --vuuOverflowContainer-justifyContent: flex-end;\n}\n\n/* .vuuToolbarItem {\n height: var(--toolbar-item-height);\n} */\n\n.vuuToolbar-withSeparators .vuuOverflowContainer-item:not(:first-child):before {\n content: '';\n position: absolute;\n left: calc(-1 * var(--overflow-item-gap));\n top: calc((var(--toolbar-height) - var(--toolbar-item-height)) /2)
|
|
1
|
+
var toolbarCss = ".vuuToolbar {\n --toolbar-height: var(--vuuToolbar-height, 36px);\n --toolbar-item-height: var(--vuuToolbarItem-height, 100%);\n --vuuOverflowContainer-background: var(--vuuToolbar-background);\n --vuuOverflowContainer-borderColor: var(--vuuToolbar-borderColor);\n --vuuOverflowContainer-borderStyle: var(--vuuToolbar-borderStyle);\n --vuuOverflowContainer-borderWidth: var(--vuuToolbar-borderWidth);\n height: var(--toolbar-height);\n}\n\n.vuuToolbar-alignCenter {\n --vuuOverflowContainer-justifyContent: center;\n}\n\n.vuuToolbar-alignEnd {\n --vuuOverflowContainer-justifyContent: flex-end;\n}\n\n/* .vuuToolbarItem {\n height: var(--toolbar-item-height);\n} */\n\n.vuuToolbar-withSeparators .vuuOverflowContainer-item:not(:first-child):before {\n content: '';\n position: absolute;\n left: calc(-1 * var(--overflow-item-gap));\n /* top: calc((var(--toolbar-height) - var(--toolbar-item-height)) /2); */\n top: 0px;\n width: 1px;\n height: var(--toolbar-item-height);\n background-color: var(--salt-separable-primary-borderColor);\n}\n\n\n.vuuToolbarItem.vuuFocusVisible {\n outline-color: var(--vuuToolbarItem-outlineColor, var(--salt-focused-outlineColor));\n outline-style: dashed;\n outline-width: 1px;\n outline-offset: 0px;\n }\n\n\n .vuuToolbarItem:focus,\n .vuuToolbarItem:focus-visible {\n\n outline-color: var(--vuuToolbarItem-outlineColor, var(--vuu-color-purple-10));\n outline-style: dashed;\n outline-width: 1px;\n outline-offset: 0px;\n\n}\n\n\n ";
|
|
2
2
|
|
|
3
3
|
export { toolbarCss as default };
|
|
4
4
|
//# sourceMappingURL=Toolbar.css.js.map
|
|
@@ -1 +1 @@
|
|
|
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
|
|
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\";\n\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 return (\n <ComboBox\n className={cx(classBase, className)}\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":";;;;;;;;;AAYA,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;AAED,EACE,uBAAA,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAG,CAAA,SAAA,EAAW,SAAS,CAAA;AAAA,MAClC,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;;;;"}
|
|
@@ -77,7 +77,15 @@ const useVuuTypeaheadInput = ({
|
|
|
77
77
|
} else {
|
|
78
78
|
setTypeaheadValues(suggestions);
|
|
79
79
|
if (pendingListFocusRef.current && inputRef.current) {
|
|
80
|
-
|
|
80
|
+
requestAnimationFrame(() => {
|
|
81
|
+
if (inputRef.current) {
|
|
82
|
+
dispatchKeyboardEvent(
|
|
83
|
+
inputRef.current,
|
|
84
|
+
"keydown",
|
|
85
|
+
"ArrowDown"
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
81
89
|
}
|
|
82
90
|
}
|
|
83
91
|
pendingListFocusRef.current = false;
|
|
@@ -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 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 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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"}
|
|
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 getVuuTable,\n useStateRef,\n NO_DATA_MATCH,\n type CommitHandler,\n dispatchKeyboardEvent,\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 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 requestAnimationFrame(() => {\n if (inputRef.current) {\n // highlight the first option. Doesn't work as expected on Safari\n dispatchKeyboardEvent(\n inputRef.current,\n \"keydown\",\n \"ArrowDown\",\n );\n }\n });\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,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.13.
|
|
2
|
+
"version": "0.13.108",
|
|
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.108",
|
|
8
|
+
"@vuu-ui/vuu-protocol-types": "0.13.108",
|
|
9
|
+
"@vuu-ui/vuu-table-types": "0.13.108"
|
|
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.
|
|
18
|
-
"@salt-ds/core": "1.
|
|
19
|
-
"@salt-ds/icons": "1.
|
|
12
|
+
"@vuu-ui/vuu-context-menu": "0.13.108",
|
|
13
|
+
"@vuu-ui/vuu-data-react": "0.13.108",
|
|
14
|
+
"@vuu-ui/vuu-layout": "0.13.108",
|
|
15
|
+
"@vuu-ui/vuu-popups": "0.13.108",
|
|
16
|
+
"@vuu-ui/vuu-table": "0.13.108",
|
|
17
|
+
"@vuu-ui/vuu-utils": "0.13.108",
|
|
18
|
+
"@salt-ds/core": "1.54.1",
|
|
19
|
+
"@salt-ds/icons": "1.16.0",
|
|
20
20
|
"@salt-ds/styles": "0.2.1",
|
|
21
21
|
"@salt-ds/window": "0.1.1",
|
|
22
22
|
"tabbable": "^6.0.0"
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import type { DataValueValidationChecker } from "@vuu-ui/vuu-data-types";
|
|
2
2
|
import { VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
|
|
3
|
-
import type {
|
|
3
|
+
import type { TableCellEditHandler } from "@vuu-ui/vuu-table-types";
|
|
4
4
|
import { FocusEventHandler, FormEventHandler, KeyboardEvent } from "react";
|
|
5
5
|
export interface EditableTextHookProps<T extends VuuRowDataItemType = VuuRowDataItemType> {
|
|
6
6
|
clientSideEditValidationCheck?: DataValueValidationChecker;
|
|
7
7
|
value?: T;
|
|
8
|
-
onEdit?:
|
|
8
|
+
onEdit?: TableCellEditHandler;
|
|
9
9
|
type?: "string" | "number" | "boolean";
|
|
10
10
|
}
|
|
11
11
|
export declare const useEditableText: <T extends string | number | boolean = string>({ clientSideEditValidationCheck, value, onEdit, type, }: EditableTextHookProps<T>) => {
|
|
12
12
|
inputProps: {
|
|
13
13
|
onBlur: FocusEventHandler<HTMLElement>;
|
|
14
|
-
|
|
14
|
+
onFocus: FocusEventHandler<HTMLElement>;
|
|
15
|
+
onKeyDown: (evt: KeyboardEvent<HTMLElement>) => Promise<void>;
|
|
15
16
|
};
|
|
16
17
|
onChange: FormEventHandler;
|
|
17
18
|
value: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PopupMenuProps } from "@vuu-ui/vuu-popups";
|
|
2
1
|
import { ButtonProps } from "@salt-ds/core";
|
|
2
|
+
import { PopupMenuProps } from "@vuu-ui/vuu-popups";
|
|
3
3
|
import { HTMLAttributes } from "react";
|
|
4
4
|
export interface SplitButtonProps extends Omit<HTMLAttributes<HTMLDivElement>, "onClick">, Pick<ButtonProps, "onClick"> {
|
|
5
5
|
ButtonProps?: Partial<Omit<ButtonProps, "onClick" | "variant">>;
|