@homebound/beam 2.101.2 → 2.102.0

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.
@@ -8,7 +8,7 @@ export declare type GridTableXss = Xss<Margin>;
8
8
  export declare const ASC: "ASC";
9
9
  export declare const DESC: "DESC";
10
10
  export declare type Direction = "ASC" | "DESC";
11
- export declare const emptyCell: () => ReactNode;
11
+ export declare const emptyCell: GridCellContent;
12
12
  /** Tells GridTable we're running in Jest, which forces as=virtual to be as=div, to work in jsdom. */
13
13
  export declare function setRunningInJest(): void;
14
14
  /** Completely static look & feel, i.e. nothing that is based on row kinds/content. */
@@ -212,7 +212,7 @@ declare type GridRowKind<R extends Kinded, P extends R["kind"]> = DiscriminateUn
212
212
  * column being sorted, in which case we use the GridCellContent.value.
213
213
  */
214
214
  export declare type GridColumn<R extends Kinded, S = {}> = {
215
- [K in R["kind"]]: string | (DiscriminateUnion<R, "kind", K> extends {
215
+ [K in R["kind"]]: string | GridCellContent | (DiscriminateUnion<R, "kind", K> extends {
216
216
  data: infer D;
217
217
  } ? (data: D, row: GridRowKind<R, K>) => ReactNode | GridCellContent : (row: GridRowKind<R, K>) => ReactNode | GridCellContent);
218
218
  } & {
@@ -42,8 +42,7 @@ const tinycolor2_1 = __importDefault(require("tinycolor2"));
42
42
  const _1 = require(".");
43
43
  exports.ASC = "ASC";
44
44
  exports.DESC = "DESC";
45
- const emptyCell = () => (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {}, void 0);
46
- exports.emptyCell = emptyCell;
45
+ exports.emptyCell = { content: () => (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {}, void 0), value: "" };
47
46
  let runningInJest = false;
48
47
  /** Tells GridTable we're running in Jest, which forces as=virtual to be as=div, to work in jsdom. */
49
48
  function setRunningInJest() {
@@ -493,7 +492,9 @@ function GridRow(props) {
493
492
  currentColspan = isGridCellContent(maybeContent) ? (_a = maybeContent.colspan) !== null && _a !== void 0 ? _a : 1 : 1;
494
493
  const canSortColumn = ((sorting === null || sorting === void 0 ? void 0 : sorting.on) === "client" && column.clientSideSort !== false) ||
495
494
  ((sorting === null || sorting === void 0 ? void 0 : sorting.on) === "server" && !!column.serverSideSortKey);
496
- const content = toContent(maybeContent, isHeader, canSortColumn, (sorting === null || sorting === void 0 ? void 0 : sorting.on) === "client", style, as);
495
+ const alignment = getAlignment(column, maybeContent);
496
+ const justificationCss = getJustification(column, maybeContent, as, alignment);
497
+ const content = toContent(maybeContent, isHeader, canSortColumn, (sorting === null || sorting === void 0 ? void 0 : sorting.on) === "client", style, as, alignment);
497
498
  (0, sortRows_1.ensureClientSideSortValueIsSortable)(sorting, isHeader, column, columnIndex, maybeContent);
498
499
  const maybeNestedCardColumnIndex = columnIndex + (style.nestedCards ? 1 : 0);
499
500
  // Note that it seems expensive to calc a per-cell class name/CSS-in-JS output,
@@ -513,7 +514,7 @@ function GridRow(props) {
513
514
  // Then override with first/last cell styling
514
515
  ...getFirstOrLastCellCss(style, columnIndex, columns),
515
516
  // Then override with per-cell/per-row justification/indentation
516
- ...getJustification(column, maybeContent, as),
517
+ ...justificationCss,
517
518
  ...getIndentationCss(style, rowStyle, columnIndex, maybeContent),
518
519
  // Then apply any header-specific override
519
520
  ...(isHeader && style.headerCellCss),
@@ -554,7 +555,7 @@ function isJSX(content) {
554
555
  return typeof content === "object" && content && "type" in content && "props" in content;
555
556
  }
556
557
  /** If a column def return just string text for a given row, apply some default styling. */
557
- function toContent(content, isHeader, canSortColumn, isClientSideSorting, style, as) {
558
+ function toContent(content, isHeader, canSortColumn, isClientSideSorting, style, as, alignment) {
558
559
  content = isGridCellContent(content) ? content.content : content;
559
560
  if (typeof content === "function") {
560
561
  // Actually create the JSX by calling `content()` here (which should be as late as
@@ -573,7 +574,7 @@ function toContent(content, isHeader, canSortColumn, isClientSideSorting, style,
573
574
  throw new Error("GridTables with as=virtual & sortable columns should use functions that return JSX, instead of JSX");
574
575
  }
575
576
  if (content && typeof content === "string" && isHeader && canSortColumn) {
576
- return (0, jsx_runtime_1.jsx)(SortHeader_1.SortHeader, { content: content }, void 0);
577
+ return (0, jsx_runtime_1.jsx)(SortHeader_1.SortHeader, { content: content, iconOnLeft: alignment === "right" }, void 0);
577
578
  }
578
579
  else if (style.emptyCell && isContentEmpty(content)) {
579
580
  // If the content is empty and the user specified an `emptyCell` node, return that.
@@ -651,9 +652,11 @@ const alignmentToTextAlign = {
651
652
  center: "center",
652
653
  right: "right",
653
654
  };
655
+ function getAlignment(column, maybeContent) {
656
+ return (isGridCellContent(maybeContent) && maybeContent.alignment) || column.align || "left";
657
+ }
654
658
  // For alignment, use: 1) cell def, else 2) column def, else 3) left.
655
- function getJustification(column, maybeContent, as) {
656
- const alignment = (isGridCellContent(maybeContent) && maybeContent.alignment) || column.align || "left";
659
+ function getJustification(column, maybeContent, as, alignment) {
657
660
  // Always apply text alignment.
658
661
  const textAlign = Css_1.Css.add("textAlign", alignmentToTextAlign[alignment]).$;
659
662
  if (as === "table") {
@@ -13,4 +13,5 @@ import { Properties } from "../../Css";
13
13
  export declare function SortHeader(props: {
14
14
  content: string;
15
15
  xss?: Properties;
16
+ iconOnLeft?: boolean;
16
17
  }): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -20,13 +20,16 @@ const useTestIds_1 = require("../../utils/useTestIds");
20
20
  * current sort state + `toggleSort` function
21
21
  */
22
22
  function SortHeader(props) {
23
- const { content, xss } = props;
23
+ const { content, xss, iconOnLeft = false } = props;
24
24
  const { isHovered, hoverProps } = (0, hooks_1.useHover)({});
25
25
  const { sorted, toggleSort } = (0, react_1.useContext)(GridSortContext_1.GridSortContext);
26
26
  const tid = (0, useTestIds_1.useTestIds)(props, "sortHeader");
27
- return ((0, jsx_runtime_1.jsxs)("div", Object.assign({}, tid, { css: { ...Css_1.Css.df.aic.h100.cursorPointer.selectNone.$, ...xss } }, hoverProps, { onClick: toggleSort }, { children: [content, (0, jsx_runtime_1.jsx)("span", Object.assign({ css: Css_1.Css.fs0.$ }, { children: (0, jsx_runtime_1.jsx)(Icon_1.Icon, Object.assign({ icon: sorted === "DESC" ? "sortDown" : "sortUp", color: sorted !== undefined ? Css_1.Palette.LightBlue700 : Css_1.Palette.Gray400, xss: Css_1.Css.ml1
28
- .visibility("hidden")
29
- .if(isHovered || sorted !== undefined)
30
- .visibility("visible").$, inc: 2 }, tid.icon), void 0) }), void 0)] }), void 0));
27
+ const icon = ((0, jsx_runtime_1.jsx)("span", Object.assign({ css: Css_1.Css.fs0.$ }, { children: (0, jsx_runtime_1.jsx)(Icon_1.Icon, Object.assign({ icon: sorted === "DESC" ? "sortDown" : "sortUp", color: sorted !== undefined ? Css_1.Palette.LightBlue700 : Css_1.Palette.Gray400, xss: {
28
+ ...Css_1.Css.ml1.if(iconOnLeft).mr1.ml0.$,
29
+ ...Css_1.Css.visibility("hidden")
30
+ .if(isHovered || sorted !== undefined)
31
+ .visibility("visible").$,
32
+ }, inc: 2 }, tid.icon), void 0) }), void 0));
33
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({}, tid, { css: { ...Css_1.Css.df.aic.h100.cursorPointer.selectNone.$, ...xss } }, hoverProps, { onClick: toggleSort }, { children: [iconOnLeft && icon, content, !iconOnLeft && icon] }), void 0));
31
34
  }
32
35
  exports.SortHeader = SortHeader;
@@ -8,3 +8,5 @@ export declare function dateColumn<T extends Kinded, S = {}>(columnDef: GridColu
8
8
  export declare function numericColumn<T extends Kinded, S = {}>(columnDef: GridColumn<T, S>): GridColumn<T, S>;
9
9
  /** Provides default styling for a GridColumn representing an Action. */
10
10
  export declare function actionColumn<T extends Kinded, S = {}>(columnDef: GridColumn<T, S>): GridColumn<T, S>;
11
+ /** Provides default styling for a GridColumn containing a checkbox. */
12
+ export declare function selectColumn<T extends Kinded, S = {}>(columnDef: GridColumn<T, S>): GridColumn<T, S>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.actionColumn = exports.numericColumn = exports.dateColumn = exports.column = void 0;
3
+ exports.selectColumn = exports.actionColumn = exports.numericColumn = exports.dateColumn = exports.column = void 0;
4
4
  /** Provides default styling for a GridColumn representing a Date. */
5
5
  function column(columnDef) {
6
6
  return { ...columnDef };
@@ -22,3 +22,9 @@ function actionColumn(columnDef) {
22
22
  return { clientSideSort: false, ...columnDef, align: "center" };
23
23
  }
24
24
  exports.actionColumn = actionColumn;
25
+ /** Provides default styling for a GridColumn containing a checkbox. */
26
+ function selectColumn(columnDef) {
27
+ // Defining `w: 48px` to accommodate for the `16px` wide checkbox and `16px` of padding on either side.
28
+ return { clientSideSort: false, ...columnDef, align: "center", w: "48px" };
29
+ }
30
+ exports.selectColumn = selectColumn;
@@ -5,3 +5,5 @@ export declare const defaultStyle: GridStyle;
5
5
  export declare const condensedStyle: GridStyle;
6
6
  /** Renders each row as a card. */
7
7
  export declare const cardStyle: GridStyle;
8
+ export declare const beamFixedStyle: GridStyle;
9
+ export declare const beamFlexibleStyle: GridStyle;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.cardStyle = exports.condensedStyle = exports.defaultStyle = void 0;
3
+ exports.beamFlexibleStyle = exports.beamFixedStyle = exports.cardStyle = exports.condensedStyle = exports.defaultStyle = void 0;
4
4
  const Css_1 = require("../../Css");
5
5
  /** Our original table look & feel/style. */
6
6
  exports.defaultStyle = {
@@ -39,3 +39,13 @@ exports.cardStyle = {
39
39
  }).p1.m0.xsEm.gray700.$,
40
40
  },
41
41
  };
42
+ // Once completely rolled out across all tables in Blueprint, this will change to be the `defaultStyle`.
43
+ exports.beamFixedStyle = {
44
+ rootCss: Css_1.Css.gray700.$,
45
+ // Doing a mix of `min` and `max` height of 40 as each cell is currently defining `h100`.
46
+ headerCellCss: Css_1.Css.xsEm.bgGray200.aic.nowrap.px2.mhPx(40).maxhPx(40).$,
47
+ // TODO: `cellCss` has incomplete styling at the moment. Will be done as part of SC-8145
48
+ cellCss: Css_1.Css.xs.bgWhite.aic.nowrap.px2.hPx(40).boxShadow(`inset 0 -1px 0 ${Css_1.Palette.Gray100}`).$,
49
+ };
50
+ // TODO: `cellCss` has incomplete styling at the moment. Will be done as part of SC-8145
51
+ exports.beamFlexibleStyle = { ...exports.beamFixedStyle, cellCss: Css_1.Css.p2.$ };
@@ -1,6 +1,7 @@
1
1
  import { ReactNode } from "react";
2
2
  export interface CheckboxProps {
3
3
  label: string;
4
+ checkboxOnly?: boolean;
4
5
  /** Handler that is called when the element's selection state changes. */
5
6
  onChange: (selected: boolean) => void;
6
7
  /** Additional text displayed below label */
@@ -16,6 +16,7 @@ export interface CheckboxBaseProps extends BeamFocusableProps {
16
16
  inputProps: InputHTMLAttributes<HTMLInputElement>;
17
17
  isSelected?: boolean;
18
18
  label: string;
19
+ checkboxOnly?: boolean;
19
20
  errorMsg?: string;
20
21
  helperText?: string | ReactNode;
21
22
  }
@@ -10,7 +10,7 @@ const ErrorMessage_1 = require("./ErrorMessage");
10
10
  const utils_1 = require("../utils");
11
11
  const defaultTestId_1 = require("../utils/defaultTestId");
12
12
  function CheckboxBase(props) {
13
- const { ariaProps, description, isDisabled = false, isIndeterminate = false, isSelected, inputProps, label, errorMsg, helperText, } = props;
13
+ const { ariaProps, description, isDisabled = false, isIndeterminate = false, isSelected, inputProps, label, errorMsg, helperText, checkboxOnly = false, } = props;
14
14
  const ref = (0, react_1.useRef)(null);
15
15
  const { isFocusVisible, focusProps } = (0, react_aria_1.useFocusRing)(ariaProps);
16
16
  const { hoverProps, isHovered } = (0, react_aria_1.useHover)({ isDisabled });
@@ -23,7 +23,7 @@ function CheckboxBase(props) {
23
23
  .maxw((0, Css_1.px)(320))
24
24
  .if(description !== undefined)
25
25
  .maxw((0, Css_1.px)(344))
26
- .if(isDisabled).cursorNotAllowed.$ }, { children: [(0, jsx_runtime_1.jsx)(react_aria_1.VisuallyHidden, { children: (0, jsx_runtime_1.jsx)("input", Object.assign({ ref: ref }, (0, react_aria_1.mergeProps)(inputProps, focusProps), tid), void 0) }, void 0), (0, jsx_runtime_1.jsx)("span", Object.assign({}, hoverProps, { css: {
26
+ .if(isDisabled).cursorNotAllowed.$, "aria-label": label }, { children: [(0, jsx_runtime_1.jsx)(react_aria_1.VisuallyHidden, { children: (0, jsx_runtime_1.jsx)("input", Object.assign({ ref: ref }, (0, react_aria_1.mergeProps)(inputProps, focusProps), tid), void 0) }, void 0), (0, jsx_runtime_1.jsx)("span", Object.assign({}, hoverProps, { css: {
27
27
  ...baseStyles,
28
28
  ...((isSelected || isIndeterminate) && filledBoxStyles),
29
29
  ...((isSelected || isIndeterminate) && isHovered && filledBoxHoverStyles),
@@ -31,7 +31,10 @@ function CheckboxBase(props) {
31
31
  ...(isFocusVisible && focusRingStyles),
32
32
  ...(isHovered && hoverBorderStyles),
33
33
  ...markStyles,
34
- }, "aria-hidden": "true" }, { children: markIcon }), void 0), (0, jsx_runtime_1.jsxs)("div", Object.assign({ css: Css_1.Css.ml1.mtPx(-2).$ }, { children: [label && (0, jsx_runtime_1.jsx)("div", Object.assign({ css: { ...labelStyles, ...(isDisabled && disabledColor) } }, { children: label }), void 0), description && (0, jsx_runtime_1.jsx)("div", Object.assign({ css: { ...descStyles, ...(isDisabled && disabledColor) } }, { children: description }), void 0), errorMsg && (0, jsx_runtime_1.jsx)(ErrorMessage_1.ErrorMessage, Object.assign({ errorMsg: errorMsg }, tid.errorMsg), void 0), helperText && (0, jsx_runtime_1.jsx)(HelperText_1.HelperText, Object.assign({ helperText: helperText }, tid.helperText), void 0)] }), void 0)] }), void 0));
34
+ }, "aria-hidden": "true" }, { children: markIcon }), void 0), !checkboxOnly && (
35
+ // Use a mtPx(-2) to better align the label with the checkbox.
36
+ // Not using align-items: center as the checkbox would align with all content below, where we really want it to stay only aligned with the label
37
+ (0, jsx_runtime_1.jsxs)("div", Object.assign({ css: Css_1.Css.ml1.mtPx(-2).$ }, { children: [label && (0, jsx_runtime_1.jsx)("div", Object.assign({ css: { ...labelStyles, ...(isDisabled && disabledColor) } }, { children: label }), void 0), description && (0, jsx_runtime_1.jsx)("div", Object.assign({ css: { ...descStyles, ...(isDisabled && disabledColor) } }, { children: description }), void 0), errorMsg && (0, jsx_runtime_1.jsx)(ErrorMessage_1.ErrorMessage, Object.assign({ errorMsg: errorMsg }, tid.errorMsg), void 0), helperText && (0, jsx_runtime_1.jsx)(HelperText_1.HelperText, Object.assign({ helperText: helperText }, tid.helperText), void 0)] }), void 0))] }), void 0));
35
38
  }
36
39
  exports.CheckboxBase = CheckboxBase;
37
40
  const baseStyles = Css_1.Css.hPx(16).mw((0, Css_1.px)(16)).relative.ba.bGray300.br4.bgWhite.transition.$;
@@ -19,6 +19,8 @@ export interface NumberFieldProps {
19
19
  /** Styles overrides */
20
20
  xss?: Xss<"textAlign" | "justifyContent">;
21
21
  displayDirection?: boolean;
22
+ numFractionDigits?: number;
23
+ truncate?: boolean;
22
24
  }
23
25
  export declare function NumberField(props: NumberFieldProps): import("@emotion/react/jsx-runtime").JSX.Element;
24
- export declare function parseRawInput(rawInputValue: string | undefined, factor: number, type?: NumberFieldType): number | undefined;
26
+ export declare function formatValue(value: number, factor: number, numFractionDigits: number | undefined): number | undefined;
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseRawInput = exports.NumberField = void 0;
3
+ exports.formatValue = exports.NumberField = void 0;
4
4
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
+ const number_1 = require("@internationalized/number");
5
6
  const react_1 = require("react");
6
7
  const react_aria_1 = require("react-aria");
7
8
  const react_stately_1 = require("react-stately");
@@ -12,34 +13,34 @@ function NumberField(props) {
12
13
  // Determine default alignment based on presentation context
13
14
  const { fieldProps } = (0, PresentationContext_1.usePresentationContext)();
14
15
  const alignment = (fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.numberAlignment) === "right" ? Css_1.Css.tr.jcfe.$ : Css_1.Css.tl.jcfs.$;
15
- const { disabled = false, required, readOnly = false, type, label, onBlur, onFocus, errorMsg, helperText, value, onChange, xss, displayDirection = false, ...otherProps } = props;
16
+ const { disabled = false, required, readOnly = false, type, label, onBlur, onFocus, errorMsg, helperText, value, onChange, xss, displayDirection = false, numFractionDigits, truncate = false, ...otherProps } = props;
16
17
  const factor = type === "percent" || type === "cents" ? 100 : type === "basisPoints" ? 10000 : 1;
17
18
  const signDisplay = displayDirection ? "exceptZero" : "auto";
19
+ const fractionFormatOptions = { [truncate ? "maximumFractionDigits" : "minimumFractionDigits"]: numFractionDigits };
20
+ const { locale } = (0, react_aria_1.useLocale)();
18
21
  // If formatOptions isn't memo'd, a useEffect in useNumberStateField will cause jank,
19
22
  // see: https://github.com/adobe/react-spectrum/issues/1893.
20
23
  const formatOptions = (0, react_1.useMemo)(() => {
21
24
  return type === "percent"
22
- ? { style: "percent", signDisplay }
25
+ ? { style: "percent", signDisplay, ...fractionFormatOptions }
23
26
  : type === "basisPoints"
24
27
  ? { style: "percent", minimumFractionDigits: 2, signDisplay }
25
28
  : type === "cents"
26
29
  ? { style: "currency", currency: "USD", minimumFractionDigits: 2, signDisplay }
27
30
  : type === "days"
28
31
  ? { style: "unit", unit: "day", unitDisplay: "long", maximumFractionDigits: 0, signDisplay }
29
- : undefined;
32
+ : fractionFormatOptions;
30
33
  }, [type]);
34
+ const numberParser = (0, react_1.useMemo)(() => new number_1.NumberParser(locale, formatOptions), [locale, formatOptions]);
31
35
  const valueRef = (0, react_1.useRef)({ wip: false });
32
- const { locale } = (0, react_aria_1.useLocale)();
33
36
  // We can use this for both useNumberFieldState + useNumberField
34
37
  const useProps = {
35
38
  locale,
36
39
  // We want percents && cents to be integers, useNumberFieldState excepts them as decimals
37
40
  value: valueRef.current.wip ? valueRef.current.value : value === undefined ? Number.NaN : value / factor,
38
- // This is called on blur with the final/committed value.
41
+ // // This is called on blur with the final/committed value.
39
42
  onChange: (value) => {
40
- // `value` for percentage style inputs will be in a number format, i.e. if input value is 4%, the `value` param will equal `.04`
41
- // Reverse the integer/decimal conversion
42
- onChange(Number.isNaN(value) ? undefined : factor !== 1 ? Math.round(value * factor) : value);
43
+ onChange(formatValue(value, factor, numFractionDigits));
43
44
  },
44
45
  onFocus: () => {
45
46
  valueRef.current = { wip: true, value: value === undefined ? Number.NaN : value / factor };
@@ -71,20 +72,17 @@ function NumberField(props) {
71
72
  return ((0, jsx_runtime_1.jsx)(TextFieldBase_1.TextFieldBase, Object.assign({ xss: { ...alignment, ...xss }, groupProps: groupProps, labelProps: labelProps, label: label, required: required, inputProps: inputProps,
72
73
  // This is called on each DOM change, to push the latest value into the field
73
74
  onChange: (rawInputValue) => {
74
- const changeValue = parseRawInput(rawInputValue, factor, type);
75
- onChange(changeValue);
75
+ const parsedValue = numberParser.parse(rawInputValue || "");
76
+ onChange(formatValue(parsedValue, factor, numFractionDigits));
76
77
  }, inputRef: inputRef, onBlur: onBlur, onFocus: onFocus, errorMsg: errorMsg, helperText: helperText, readOnly: readOnly }, otherProps), void 0));
77
78
  }
78
79
  exports.NumberField = NumberField;
79
- function parseRawInput(rawInputValue = "", factor, type) {
80
- // If the wip value is invalid, i.e. it's `10b`, don't push that back into the field state
81
- const wip = parseFloat(rawInputValue);
82
- if (isNaN(wip))
83
- return;
84
- // For percentage values we need to initially divide by 100 in order to get their "number value" ("4%" = .04) for the factor multiplier to be accurate.
85
- // For example, if the using basisPoints and the user enters "4.31%", then we would expect the response to be 431 basisPoints. If only basing off the `factor` value, then 4.31 * 10000 = 43100, which would not be correct.
86
- const value = type === "percent" || type === "basisPoints" ? wip / 100 : wip;
87
- // Since the values returned is exactly what is in the field
88
- return factor !== 1 ? Math.round(value * factor) : value;
80
+ function formatValue(value, factor, numFractionDigits) {
81
+ // We treat percents & cents as (mostly) integers, while useNumberField wants decimals, so
82
+ // undo that via `* factor` and `Math.round`, but also keep any specifically-requested `numFractionDigits`,
83
+ // i.e. for `type=percent value=12.34`, `value` will be `0.1234` that we want turn into `12.34`.
84
+ const maybeAdjustForDecimals = numFractionDigits ? Math.pow(10, numFractionDigits) : 1;
85
+ // Reverse the integer/decimal conversion
86
+ return Number.isNaN(value) ? undefined : Math.round(value * factor * maybeAdjustForDecimals) / maybeAdjustForDecimals;
89
87
  }
90
- exports.parseRawInput = parseRawInput;
88
+ exports.formatValue = formatValue;
@@ -33,7 +33,7 @@ function TextFieldBase(props) {
33
33
  const fieldHeight = 40;
34
34
  const compactFieldHeight = 32;
35
35
  const fieldStyles = {
36
- container: Css_1.Css.df.fdc.w100.maxw((0, Css_1.px)(550)).$,
36
+ container: Css_1.Css.df.fdc.w100.maxw((0, Css_1.px)(550)).relative.$,
37
37
  inputWrapper: {
38
38
  ...Css_1.Css[typeScale].df.aic.br4.px1.w100
39
39
  .hPx(fieldHeight - maybeSmaller)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.101.2",
3
+ "version": "2.102.0",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -34,6 +34,7 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@homebound/form-state": "^2.2.13",
37
+ "@internationalized/number": "^3.0.3",
37
38
  "@react-aria/utils": "^3.9.0",
38
39
  "@react-hook/resize-observer": "^1.2.2",
39
40
  "@types/tinycolor2": "^1.4.2",