@homebound/beam 2.371.2 → 2.372.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PropsWithChildren } from "react";
|
|
2
2
|
import { GridStyle } from "./Table";
|
|
3
3
|
import { Typography } from "../Css";
|
|
4
|
+
export type InputStylePalette = "success" | "warning" | "caution" | "info";
|
|
4
5
|
export interface PresentationFieldProps {
|
|
5
6
|
numberAlignment?: "left" | "right";
|
|
6
7
|
/** Sets the label position or visibility. Defaults to "above" */
|
|
@@ -16,9 +17,12 @@ export interface PresentationFieldProps {
|
|
|
16
17
|
errorInTooltip?: true;
|
|
17
18
|
/** Allow the fields to grow to the width of its container. By default, fields will extend up to 550px */
|
|
18
19
|
fullWidth?: boolean;
|
|
20
|
+
/** Changes bg and hoverBg; Takes priority over `contrast`; Useful when showing many fields w/in a table that require user attention; In no way should be used as a replacement for error/focus state */
|
|
21
|
+
inputStylePalette?: InputStylePalette;
|
|
19
22
|
}
|
|
20
23
|
export type PresentationContextProps = {
|
|
21
|
-
|
|
24
|
+
/** `inputStylePalette` omitted because it is too dependent on the individual field use case to be controlled at this level */
|
|
25
|
+
fieldProps?: Omit<PresentationFieldProps, "inputStylePalette">;
|
|
22
26
|
gridTableStyle?: GridStyle;
|
|
23
27
|
wrap?: boolean;
|
|
24
28
|
};
|
|
@@ -34,6 +34,7 @@ export * from "./Modal/useModal";
|
|
|
34
34
|
export { NavLink } from "./NavLink";
|
|
35
35
|
export * from "./Pagination";
|
|
36
36
|
export { PresentationProvider } from "./PresentationContext";
|
|
37
|
+
export type { InputStylePalette, PresentationFieldProps } from "./PresentationContext";
|
|
37
38
|
export * from "./ScrollShadows";
|
|
38
39
|
export * from "./Snackbar";
|
|
39
40
|
export * from "./Stepper";
|
|
@@ -2,7 +2,7 @@ import type { NumberFieldAria } from "@react-aria/numberfield";
|
|
|
2
2
|
import { InputHTMLAttributes, LabelHTMLAttributes, MutableRefObject, ReactNode, TextareaHTMLAttributes } from "react";
|
|
3
3
|
import { Only } from "../Css";
|
|
4
4
|
import { BeamTextFieldProps, TextFieldXss } from "../interfaces";
|
|
5
|
-
export interface TextFieldBaseProps<X> extends Pick<BeamTextFieldProps<X>, "label" | "required" | "errorMsg" | "errorInTooltip" | "onBlur" | "onFocus" | "helperText" | "labelStyle" | "placeholder" | "compact" | "borderless" | "borderOnHover" | "visuallyDisabled" | "fullWidth" | "xss">, Partial<Pick<BeamTextFieldProps<X>, "onChange">> {
|
|
5
|
+
export interface TextFieldBaseProps<X> extends Pick<BeamTextFieldProps<X>, "label" | "required" | "errorMsg" | "errorInTooltip" | "onBlur" | "onFocus" | "helperText" | "labelStyle" | "placeholder" | "compact" | "borderless" | "borderOnHover" | "visuallyDisabled" | "fullWidth" | "xss" | "inputStylePalette">, Partial<Pick<BeamTextFieldProps<X>, "onChange">> {
|
|
6
6
|
labelProps?: LabelHTMLAttributes<HTMLLabelElement>;
|
|
7
7
|
inputProps: InputHTMLAttributes<HTMLInputElement> | TextareaHTMLAttributes<HTMLTextAreaElement>;
|
|
8
8
|
inputRef?: MutableRefObject<HTMLInputElement | HTMLTextAreaElement | null>;
|
|
@@ -21,7 +21,7 @@ function TextFieldBase(props) {
|
|
|
21
21
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
22
22
|
const { fieldProps, wrap = false } = (0, PresentationContext_1.usePresentationContext)();
|
|
23
23
|
const { labelLeftFieldWidth = "50%" } = fieldProps !== null && fieldProps !== void 0 ? fieldProps : {};
|
|
24
|
-
const { label, required, labelProps, inputProps, inputRef, inputWrapRef, groupProps, compact = (_a = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.compact) !== null && _a !== void 0 ? _a : false, errorMsg, helperText, multiline = false, onChange, onBlur, onFocus, xss, endAdornment, startAdornment, labelStyle = (_b = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.labelStyle) !== null && _b !== void 0 ? _b : "above", contrast = false, borderless = (_c = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.borderless) !== null && _c !== void 0 ? _c : false, borderOnHover = (_d = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.borderOnHover) !== null && _d !== void 0 ? _d : false, textAreaMinHeight = 96, clearable = false, tooltip, visuallyDisabled = (_e = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.visuallyDisabled) !== null && _e !== void 0 ? _e : true, errorInTooltip = (_f = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.errorInTooltip) !== null && _f !== void 0 ? _f : false, hideErrorMessage = false, alwaysShowHelperText = false, fullWidth = (_g = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.fullWidth) !== null && _g !== void 0 ? _g : false, unfocusedPlaceholder, selectOnFocus = true, } = props;
|
|
24
|
+
const { label, required, labelProps, inputProps, inputRef, inputWrapRef, groupProps, compact = (_a = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.compact) !== null && _a !== void 0 ? _a : false, errorMsg, helperText, multiline = false, onChange, onBlur, onFocus, xss, endAdornment, startAdornment, labelStyle = (_b = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.labelStyle) !== null && _b !== void 0 ? _b : "above", contrast = false, borderless = (_c = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.borderless) !== null && _c !== void 0 ? _c : false, borderOnHover = (_d = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.borderOnHover) !== null && _d !== void 0 ? _d : false, textAreaMinHeight = 96, clearable = false, tooltip, visuallyDisabled = (_e = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.visuallyDisabled) !== null && _e !== void 0 ? _e : true, errorInTooltip = (_f = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.errorInTooltip) !== null && _f !== void 0 ? _f : false, hideErrorMessage = false, alwaysShowHelperText = false, fullWidth = (_g = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.fullWidth) !== null && _g !== void 0 ? _g : false, unfocusedPlaceholder, selectOnFocus = true, inputStylePalette, } = props;
|
|
25
25
|
const typeScale = (_h = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.typeScale) !== null && _h !== void 0 ? _h : (inputProps.readOnly && labelStyle !== "hidden" ? "smMd" : "sm");
|
|
26
26
|
const internalProps = props.internalProps || {};
|
|
27
27
|
const { compound = false, forceFocus = false, forceHover = false } = internalProps;
|
|
@@ -36,21 +36,23 @@ function TextFieldBase(props) {
|
|
|
36
36
|
const maybeSmaller = compound ? 2 : 0;
|
|
37
37
|
const fieldHeight = 40;
|
|
38
38
|
const compactFieldHeight = 32;
|
|
39
|
-
const [bgColor, hoverBgColor, disabledBgColor] =
|
|
40
|
-
?
|
|
41
|
-
:
|
|
42
|
-
?
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
:
|
|
39
|
+
const [bgColor, hoverBgColor, disabledBgColor] = inputStylePalette
|
|
40
|
+
? getInputStylePalette(inputStylePalette)
|
|
41
|
+
: contrast
|
|
42
|
+
? [Css_1.Palette.Gray700, Css_1.Palette.Gray600, Css_1.Palette.Gray700]
|
|
43
|
+
: borderOnHover
|
|
44
|
+
? // Use transparent backgrounds to blend with the table row hover color
|
|
45
|
+
[Css_1.Palette.Transparent, Css_1.Palette.Blue100, Css_1.Palette.Gray100]
|
|
46
|
+
: borderless && !compound
|
|
47
|
+
? [Css_1.Palette.Gray100, Css_1.Palette.Gray200, Css_1.Palette.Gray200]
|
|
48
|
+
: [Css_1.Palette.White, Css_1.Palette.Gray100, Css_1.Palette.Gray100];
|
|
47
49
|
const fieldMaxWidth = (0, utils_1.getFieldWidth)(fullWidth);
|
|
48
50
|
const fieldStyles = {
|
|
49
51
|
container: Css_1.Css.df.fdc.w100.maxw(fieldMaxWidth).relative.if(labelStyle === "left").maxw100.fdr.gap2.jcsb.aic.$,
|
|
50
52
|
inputWrapper: {
|
|
51
53
|
...Css_1.Css[typeScale].df.aic.br4.px1.w100
|
|
52
54
|
.bgColor(bgColor)
|
|
53
|
-
.gray900.if(contrast)
|
|
55
|
+
.gray900.if(contrast && !inputStylePalette)
|
|
54
56
|
.white.if(labelStyle === "left")
|
|
55
57
|
.w(labelLeftFieldWidth).$,
|
|
56
58
|
// When borderless then perceived vertical alignments are misaligned. As there is no longer a border, then the field looks oddly indented.
|
|
@@ -63,7 +65,7 @@ function TextFieldBase(props) {
|
|
|
63
65
|
// Do not add borders to compound fields. A compound field is responsible for drawing its own borders
|
|
64
66
|
...(!compound ? Css_1.Css.ba.$ : {}),
|
|
65
67
|
...(borderOnHover && Css_1.Css.br4.ba.bcTransparent.add("transition", "border-color 200ms").$),
|
|
66
|
-
...(borderOnHover && Css_1.Css.if(isHovered).
|
|
68
|
+
...(borderOnHover && Css_1.Css.if(isHovered).bgColor(hoverBgColor).ba.bcBlue300.$),
|
|
67
69
|
...{
|
|
68
70
|
// Highlight the field when hovering over the row in a table, unless some other edit component (including ourselves) is hovered
|
|
69
71
|
[`.${Row_1.BorderHoverParent}:hover:not(:has(.${Row_1.BorderHoverChild}:hover)) &`]: Css_1.Css.ba.bcBlue300.$,
|
|
@@ -80,7 +82,7 @@ function TextFieldBase(props) {
|
|
|
80
82
|
},
|
|
81
83
|
inputWrapperReadOnly: {
|
|
82
84
|
...Css_1.Css[typeScale].df.aic.w100.gray900
|
|
83
|
-
.if(contrast)
|
|
85
|
+
.if(contrast && !inputStylePalette)
|
|
84
86
|
.white.if(labelStyle === "left")
|
|
85
87
|
.w(labelLeftFieldWidth).$,
|
|
86
88
|
// If we are hiding the label, then we are typically in a table. Keep the `mh` in this case to ensure editable and non-editable fields in a single table row line up properly
|
|
@@ -92,14 +94,14 @@ function TextFieldBase(props) {
|
|
|
92
94
|
input: {
|
|
93
95
|
...Css_1.Css.w100.mw0.outline0.fg1.bgColor(bgColor).$,
|
|
94
96
|
// Not using Truss's inline `if` statement here because `addIn` properties do not respect the if statement.
|
|
95
|
-
...(contrast && Css_1.Css.addIn("&::selection", Css_1.Css.bgGray800.$).$),
|
|
97
|
+
...(contrast && !inputStylePalette && Css_1.Css.addIn("&::selection", Css_1.Css.bgGray800.$).$),
|
|
96
98
|
// Make the background transparent when highlighting the field on hover
|
|
97
99
|
...(borderOnHover && Css_1.Css.bgTransparent.$),
|
|
98
100
|
// For "multiline" fields we add top and bottom padding of 7px for compact, or 11px for non-compact, to properly match the height of the single line fields
|
|
99
101
|
...(multiline ? Css_1.Css.br4.pyPx(compact ? 7 : 11).add("resize", "none").$ : Css_1.Css.truncate.$),
|
|
100
102
|
},
|
|
101
103
|
hover: Css_1.Css.bgColor(hoverBgColor).if(contrast).bcGray600.$,
|
|
102
|
-
focus: Css_1.Css.bcBlue700.if(contrast).bcBlue500.if(borderOnHover).
|
|
104
|
+
focus: Css_1.Css.bcBlue700.if(contrast).bcBlue500.if(borderOnHover).bgColor(hoverBgColor).bcBlue500.$,
|
|
103
105
|
disabled: visuallyDisabled
|
|
104
106
|
? Css_1.Css.cursorNotAllowed.gray600.bgColor(disabledBgColor).if(contrast).gray500.$
|
|
105
107
|
: Css_1.Css.cursorNotAllowed.$,
|
|
@@ -178,3 +180,17 @@ function TextFieldBase(props) {
|
|
|
178
180
|
// Reduces the margin between the error/helper text and input field
|
|
179
181
|
(0, jsx_runtime_1.jsxs)("div", { css: Css_1.Css.mtPx(-8).$, children: [errorMsg && !errorInTooltip && ((0, jsx_runtime_1.jsx)(ErrorMessage_1.ErrorMessage, { id: errorMessageId, errorMsg: errorMsg, hidden: hideErrorMessage, ...tid.errorMsg })), helperText && (0, jsx_runtime_1.jsx)(HelperText_1.HelperText, { helperText: helperText, ...tid.helperText })] }))] }));
|
|
180
182
|
}
|
|
183
|
+
function getInputStylePalette(inputStylePalette) {
|
|
184
|
+
switch (inputStylePalette) {
|
|
185
|
+
case "success":
|
|
186
|
+
return [Css_1.Palette.Green50, Css_1.Palette.Green100, Css_1.Palette.Green50];
|
|
187
|
+
case "caution":
|
|
188
|
+
return [Css_1.Palette.Yellow50, Css_1.Palette.Yellow100, Css_1.Palette.Yellow50];
|
|
189
|
+
case "warning":
|
|
190
|
+
return [Css_1.Palette.Red50, Css_1.Palette.Red100, Css_1.Palette.Red50];
|
|
191
|
+
case "info":
|
|
192
|
+
return [Css_1.Palette.Blue50, Css_1.Palette.Blue100, Css_1.Palette.Blue50];
|
|
193
|
+
default:
|
|
194
|
+
return [Css_1.Palette.White, Css_1.Palette.Gray100, Css_1.Palette.Gray100];
|
|
195
|
+
}
|
|
196
|
+
}
|
|
@@ -33,7 +33,7 @@ const use_debounce_1 = require("use-debounce");
|
|
|
33
33
|
function ComboBoxBase(props) {
|
|
34
34
|
var _a, _b, _c, _d, _e;
|
|
35
35
|
const { fieldProps } = (0, PresentationContext_1.usePresentationContext)();
|
|
36
|
-
const { disabled, readOnly, onSelect, options: propOptions, multiselect = false, values: propValues, nothingSelectedText = "", contrast, disabledOptions, borderless, unsetLabel, getOptionLabel: propOptionLabel, getOptionValue: propOptionValue, getOptionMenuLabel: propOptionMenuLabel, fullWidth = (_a = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.fullWidth) !== null && _a !== void 0 ? _a : false, onSearch, onAddNew, ...otherProps } = props;
|
|
36
|
+
const { disabled, readOnly, onSelect, options: propOptions, multiselect = false, values: propValues, nothingSelectedText = "", contrast, disabledOptions, borderless, unsetLabel, inputStylePalette: propsInputStylePalette, getOptionLabel: propOptionLabel, getOptionValue: propOptionValue, getOptionMenuLabel: propOptionMenuLabel, fullWidth = (_a = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.fullWidth) !== null && _a !== void 0 ? _a : false, onSearch, onAddNew, ...otherProps } = props;
|
|
37
37
|
const labelStyle = (_c = (_b = otherProps.labelStyle) !== null && _b !== void 0 ? _b : fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.labelStyle) !== null && _c !== void 0 ? _c : "above";
|
|
38
38
|
// Memoize the callback functions and handle the `unset` option if provided.
|
|
39
39
|
const getOptionLabel = (0, react_1.useCallback)((o) => unsetLabel && o === exports.unsetOption
|
|
@@ -67,6 +67,7 @@ function ComboBoxBase(props) {
|
|
|
67
67
|
? [propOptions, unsetLabel, onAddNew]
|
|
68
68
|
: [propOptions.current, propOptions.options, unsetLabel, onAddNew]);
|
|
69
69
|
const values = (0, react_1.useMemo)(() => propValues !== null && propValues !== void 0 ? propValues : [], [propValues]);
|
|
70
|
+
const inputStylePalette = (0, react_1.useMemo)(() => propsInputStylePalette, [propsInputStylePalette]);
|
|
70
71
|
const selectedOptionsRef = (0, react_1.useRef)(options.filter((o) => values.includes(getOptionValue(o))));
|
|
71
72
|
const selectedOptions = (0, react_1.useMemo)(() => {
|
|
72
73
|
// `selectedOptions` should only ever update if the `values` prop actually change.
|
|
@@ -252,7 +253,7 @@ function ComboBoxBase(props) {
|
|
|
252
253
|
minWidth: 200,
|
|
253
254
|
};
|
|
254
255
|
const fieldMaxWidth = (0, utils_1.getFieldWidth)(fullWidth);
|
|
255
|
-
return ((0, jsx_runtime_1.jsxs)("div", { css: Css_1.Css.df.fdc.w100.maxw(fieldMaxWidth).if(labelStyle === "left").maxw100.$, ref: comboBoxRef, children: [(0, jsx_runtime_1.jsx)(ComboBoxInput_1.ComboBoxInput, { ...otherProps, fullWidth: fullWidth, buttonProps: buttonProps, buttonRef: triggerRef, inputProps: inputProps, inputRef: inputRef, inputWrapRef: inputWrapRef, listBoxRef: listBoxRef, state: state, labelProps: labelProps, selectedOptions: selectedOptions, getOptionValue: getOptionValue, getOptionLabel: getOptionLabel, contrast: contrast, nothingSelectedText: nothingSelectedText, borderless: borderless, tooltip: (0, components_1.resolveTooltip)(disabled, undefined, readOnly), resetField: resetField }), state.isOpen && ((0, jsx_runtime_1.jsx)(internal_1.Popover, { triggerRef: triggerRef, popoverRef: popoverRef, positionProps: positionProps, onClose: () => state.close(), isOpen: state.isOpen, minWidth: 200, children: (0, jsx_runtime_1.jsx)(ListBox_1.ListBox, { ...listBoxProps, positionProps: positionProps, state: state, listBoxRef: listBoxRef, selectedOptions: selectedOptions, getOptionLabel: getOptionLabel, getOptionValue: (o) => (0, Value_1.valueToKey)(getOptionValue(o)), contrast: contrast, horizontalLayout: labelStyle === "left", loading: fieldState.optionsLoading, disabledOptionsWithReasons: disabledOptionsWithReasons }) }))] }));
|
|
256
|
+
return ((0, jsx_runtime_1.jsxs)("div", { css: Css_1.Css.df.fdc.w100.maxw(fieldMaxWidth).if(labelStyle === "left").maxw100.$, ref: comboBoxRef, children: [(0, jsx_runtime_1.jsx)(ComboBoxInput_1.ComboBoxInput, { ...otherProps, inputStylePalette: inputStylePalette, fullWidth: fullWidth, buttonProps: buttonProps, buttonRef: triggerRef, inputProps: inputProps, inputRef: inputRef, inputWrapRef: inputWrapRef, listBoxRef: listBoxRef, state: state, labelProps: labelProps, selectedOptions: selectedOptions, getOptionValue: getOptionValue, getOptionLabel: getOptionLabel, contrast: contrast, nothingSelectedText: nothingSelectedText, borderless: borderless, tooltip: (0, components_1.resolveTooltip)(disabled, undefined, readOnly), resetField: resetField }), state.isOpen && ((0, jsx_runtime_1.jsx)(internal_1.Popover, { triggerRef: triggerRef, popoverRef: popoverRef, positionProps: positionProps, onClose: () => state.close(), isOpen: state.isOpen, minWidth: 200, children: (0, jsx_runtime_1.jsx)(ListBox_1.ListBox, { ...listBoxProps, positionProps: positionProps, state: state, listBoxRef: listBoxRef, selectedOptions: selectedOptions, getOptionLabel: getOptionLabel, getOptionValue: (o) => (0, Value_1.valueToKey)(getOptionValue(o)), contrast: contrast, horizontalLayout: labelStyle === "left", loading: fieldState.optionsLoading, disabledOptionsWithReasons: disabledOptionsWithReasons }) }))] }));
|
|
256
257
|
}
|
|
257
258
|
function getInputValue(selectedOptions, getOptionLabel, multiselect, nothingSelectedText, readOnly) {
|
|
258
259
|
return selectedOptions.length === 1
|