@homebound/beam 2.91.6 → 2.92.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.
- package/dist/components/Button.js +8 -8
- package/dist/components/Icon.d.ts +2 -2
- package/dist/components/Icon.js +6 -3
- package/dist/components/IconButton.js +5 -4
- package/dist/components/Label.d.ts +2 -2
- package/dist/components/Label.js +6 -3
- package/dist/components/PresentationContext.d.ts +1 -0
- package/dist/components/Table/GridTable.js +10 -4
- package/dist/components/Table/nestedCards.d.ts +11 -3
- package/dist/components/Table/nestedCards.js +44 -48
- package/dist/components/Tooltip.d.ts +2 -0
- package/dist/components/Tooltip.js +12 -1
- package/dist/inputs/ChipSelectField.js +57 -33
- package/dist/inputs/DateField.d.ts +3 -5
- package/dist/inputs/DateField.js +6 -5
- package/dist/inputs/TextFieldBase.d.ts +2 -2
- package/dist/inputs/TextFieldBase.js +29 -22
- package/dist/inputs/internal/ListBox.js +2 -9
- package/dist/inputs/internal/ListBoxChip.d.ts +5 -0
- package/dist/inputs/internal/ListBoxChip.js +12 -0
- package/dist/inputs/internal/ListBoxToggleChip.d.ts +12 -0
- package/dist/inputs/internal/ListBoxToggleChip.js +14 -0
- package/dist/utils/options.d.ts +2 -0
- package/dist/utils/options.js +7 -0
- package/package.json +2 -1
|
@@ -5,18 +5,17 @@ const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
|
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const react_aria_1 = require("react-aria");
|
|
7
7
|
const react_router_dom_1 = require("react-router-dom");
|
|
8
|
-
const src_1 = require("..");
|
|
9
8
|
const components_1 = require("./");
|
|
10
|
-
const Tooltip_1 = require("./Tooltip");
|
|
11
9
|
const Css_1 = require("../Css");
|
|
12
10
|
const utils_1 = require("../utils");
|
|
11
|
+
const useTestIds_1 = require("../utils/useTestIds");
|
|
13
12
|
function Button(props) {
|
|
14
13
|
const { onClick: onPress, disabled, endAdornment, menuTriggerProps, tooltip, openInNew, ...otherProps } = props;
|
|
15
14
|
const isDisabled = !!disabled;
|
|
16
15
|
const ariaProps = { onPress, isDisabled, ...otherProps, ...menuTriggerProps };
|
|
17
16
|
const { label, icon, variant = "primary", size = "sm", buttonRef } = ariaProps;
|
|
18
17
|
const ref = buttonRef || (0, react_1.useRef)(null);
|
|
19
|
-
const tid = (0,
|
|
18
|
+
const tid = (0, useTestIds_1.useTestIds)(props, label);
|
|
20
19
|
const { buttonProps, isPressed } = (0, react_aria_1.useButton)({
|
|
21
20
|
...ariaProps,
|
|
22
21
|
onPress: typeof onPress === "string" ? utils_1.noop : onPress,
|
|
@@ -42,12 +41,13 @@ function Button(props) {
|
|
|
42
41
|
},
|
|
43
42
|
...tid,
|
|
44
43
|
};
|
|
45
|
-
const button = typeof onPress === "string" ? ((0, utils_1.isAbsoluteUrl)(onPress) || openInNew ? ((0, jsx_runtime_1.jsxs)("a", Object.assign({}, buttonAttrs, { href: onPress, className:
|
|
44
|
+
const button = typeof onPress === "string" ? ((0, utils_1.isAbsoluteUrl)(onPress) || openInNew ? ((0, jsx_runtime_1.jsxs)("a", Object.assign({}, buttonAttrs, { href: onPress, className: components_1.navLink, target: "_blank", rel: "noreferrer noopener" }, { children: [buttonContent, (0, jsx_runtime_1.jsx)("span", Object.assign({ css: Css_1.Css.ml1.$ }, { children: (0, jsx_runtime_1.jsx)(components_1.Icon, { icon: "linkExternal" }, void 0) }), void 0)] }), void 0)) : ((0, jsx_runtime_1.jsx)(react_router_dom_1.Link, Object.assign({}, buttonAttrs, { to: onPress, className: components_1.navLink }, { children: buttonContent }), void 0))) : ((0, jsx_runtime_1.jsx)("button", Object.assign({}, buttonAttrs, { children: buttonContent }), void 0));
|
|
46
45
|
// If we're disabled b/c of a non-boolean ReactNode, or the caller specified tooltip text, then show it in a tooltip
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
return (0, components_1.maybeTooltip)({
|
|
47
|
+
title: (0, components_1.resolveTooltip)(disabled, tooltip),
|
|
48
|
+
placement: "top",
|
|
49
|
+
children: button,
|
|
50
|
+
});
|
|
51
51
|
}
|
|
52
52
|
exports.Button = Button;
|
|
53
53
|
function getButtonStyles(variant, size) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DOMProps } from "@react-types/shared";
|
|
2
|
-
import { AriaAttributes } from "react";
|
|
2
|
+
import React, { AriaAttributes } from "react";
|
|
3
3
|
import { Margin, Palette, Xss } from "../Css";
|
|
4
4
|
export interface IconProps extends AriaAttributes, DOMProps {
|
|
5
5
|
/** The name of an icon */
|
|
@@ -11,7 +11,7 @@ export interface IconProps extends AriaAttributes, DOMProps {
|
|
|
11
11
|
/** Styles overrides */
|
|
12
12
|
xss?: Xss<Margin>;
|
|
13
13
|
}
|
|
14
|
-
export declare
|
|
14
|
+
export declare const Icon: React.MemoExoticComponent<(props: IconProps) => import("@emotion/react/jsx-runtime").JSX.Element>;
|
|
15
15
|
/**
|
|
16
16
|
* Map of icons paths mapped to their respective name.
|
|
17
17
|
*
|
package/dist/components/Icon.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.Icons = exports.Icon = void 0;
|
|
4
7
|
const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
|
|
8
|
+
const react_1 = __importDefault(require("react"));
|
|
5
9
|
const Css_1 = require("../Css");
|
|
6
|
-
|
|
10
|
+
exports.Icon = react_1.default.memo((props) => {
|
|
7
11
|
const { icon, inc = 3, color = "currentColor", xss, ...other } = props;
|
|
8
12
|
const size = (0, Css_1.increment)(inc);
|
|
9
13
|
return ((0, jsx_runtime_1.jsx)("svg", Object.assign({ "aria-hidden": true, width: size, height: size, viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", css: { path: Css_1.Css.fill(color).$, ...xss }, "data-icon": icon }, other, { children: exports.Icons[icon] }), void 0));
|
|
10
|
-
}
|
|
11
|
-
exports.Icon = Icon;
|
|
14
|
+
});
|
|
12
15
|
/**
|
|
13
16
|
* Map of icons paths mapped to their respective name.
|
|
14
17
|
*
|
|
@@ -33,10 +33,11 @@ function IconButton(props) {
|
|
|
33
33
|
const buttonContent = ((0, jsx_runtime_1.jsx)(components_1.Icon, { icon: icon, color: color || (isDisabled ? Css_1.Palette.Gray400 : Css_1.Palette.Gray900), inc: inc }, void 0));
|
|
34
34
|
const button = typeof onPress === "string" ? ((0, utils_1.isAbsoluteUrl)(onPress) || openInNew ? ((0, jsx_runtime_1.jsx)("a", Object.assign({}, buttonAttrs, { href: onPress, className: components_1.navLink, target: "_blank", rel: "noreferrer noopener" }, { children: buttonContent }), void 0)) : ((0, jsx_runtime_1.jsx)(react_router_dom_1.Link, Object.assign({}, buttonAttrs, { to: onPress, className: components_1.navLink }, { children: buttonContent }), void 0))) : ((0, jsx_runtime_1.jsx)("button", Object.assign({}, buttonAttrs, { children: buttonContent }), void 0));
|
|
35
35
|
// If we're disabled b/c of a non-boolean ReactNode, or the caller specified tooltip text, then show it in a tooltip
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
return (0, components_1.maybeTooltip)({
|
|
37
|
+
title: (0, components_1.resolveTooltip)(disabled, tooltip),
|
|
38
|
+
placement: "top",
|
|
39
|
+
children: button,
|
|
40
|
+
});
|
|
40
41
|
}
|
|
41
42
|
exports.IconButton = IconButton;
|
|
42
43
|
const iconButtonStylesReset = Css_1.Css.hPx(28).wPx(28).br8.bTransparent.bsSolid.bw2.bgTransparent.cursorPointer.outline0.p0.dif.aic.jcc.transition.$;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LabelHTMLAttributes } from "react";
|
|
1
|
+
import React, { LabelHTMLAttributes } from "react";
|
|
2
2
|
interface LabelProps {
|
|
3
3
|
labelProps?: LabelHTMLAttributes<HTMLLabelElement>;
|
|
4
4
|
label: string;
|
|
@@ -7,7 +7,7 @@ interface LabelProps {
|
|
|
7
7
|
contrast?: boolean;
|
|
8
8
|
}
|
|
9
9
|
/** An internal helper component for rendering form labels. */
|
|
10
|
-
export declare
|
|
10
|
+
export declare const Label: React.MemoExoticComponent<(props: LabelProps) => import("@emotion/react/jsx-runtime").JSX.Element>;
|
|
11
11
|
/** Used for showing labels within text fields. */
|
|
12
12
|
export declare function InlineLabel({ labelProps, label, contrast, ...others }: LabelProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
13
13
|
export {};
|
package/dist/components/Label.js
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.InlineLabel = exports.Label = void 0;
|
|
4
7
|
const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
|
|
8
|
+
const react_1 = __importDefault(require("react"));
|
|
5
9
|
const react_aria_1 = require("react-aria");
|
|
6
10
|
const Css_1 = require("../Css");
|
|
7
11
|
/** An internal helper component for rendering form labels. */
|
|
8
|
-
|
|
12
|
+
exports.Label = react_1.default.memo((props) => {
|
|
9
13
|
const { labelProps, label, hidden, suffix, contrast = false, ...others } = props;
|
|
10
14
|
const labelEl = ((0, jsx_runtime_1.jsxs)("label", Object.assign({}, labelProps, others, { css: Css_1.Css.dib.sm.gray700.mbPx(4).if(contrast).white.$ }, { children: [label, suffix && ` ${suffix}`] }), void 0));
|
|
11
15
|
return hidden ? (0, jsx_runtime_1.jsx)(react_aria_1.VisuallyHidden, { children: labelEl }, void 0) : labelEl;
|
|
12
|
-
}
|
|
13
|
-
exports.Label = Label;
|
|
16
|
+
});
|
|
14
17
|
/** Used for showing labels within text fields. */
|
|
15
18
|
function InlineLabel({ labelProps, label, contrast, ...others }) {
|
|
16
19
|
return ((0, jsx_runtime_1.jsxs)("label", Object.assign({}, labelProps, others, { css: Css_1.Css.smEm.nowrap.gray900.prPx(4).add("color", "currentColor").$ }, { children: [label, ":"] }), void 0));
|
|
@@ -260,10 +260,16 @@ function renderTable(style, id, columns, headerRows, filteredRows, firstRowMessa
|
|
|
260
260
|
function renderVirtual(style, id, columns, headerRows, filteredRows, firstRowMessage, stickyHeader, firstLastColumnWidth, xss, virtuosoRef) {
|
|
261
261
|
return ((0, jsx_runtime_1.jsx)(react_virtuoso_1.Virtuoso, { ref: virtuosoRef, components: { List: VirtualRoot(style, columns, id, firstLastColumnWidth, xss) },
|
|
262
262
|
// Pin/sticky both the header row(s) + firstRowMessage to the top
|
|
263
|
-
topItemCount: (stickyHeader ? headerRows.length : 0) + (firstRowMessage ? 1 : 0),
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
263
|
+
topItemCount: (stickyHeader ? headerRows.length : 0) + (firstRowMessage ? 1 : 0), itemSize: (el) => {
|
|
264
|
+
const maybeContentsDiv = el.firstElementChild;
|
|
265
|
+
// If it is a chrome row, then we are not using `display: contents;`, return the height of this element.
|
|
266
|
+
if ("chrome" in maybeContentsDiv.dataset) {
|
|
267
|
+
return maybeContentsDiv.offsetHeight;
|
|
268
|
+
}
|
|
269
|
+
// Both the `Item` and `itemContent` use `display: contents`, so their height is 0,
|
|
270
|
+
// so instead drill into the 1st real content cell.
|
|
271
|
+
return maybeContentsDiv.firstElementChild.offsetHeight;
|
|
272
|
+
}, itemContent: (index) => {
|
|
267
273
|
// We keep header and filter rows separate, but react-virtuoso is a flat list,
|
|
268
274
|
// so we pick the right header / first row message / actual row.
|
|
269
275
|
let i = index;
|
|
@@ -12,6 +12,8 @@ import { GridColumn, GridDataRow, GridStyle, Kinded, NestedCardStyle, RowTuple }
|
|
|
12
12
|
* a content row itself, the nested padding is handled separately by the
|
|
13
13
|
* GridRow component.
|
|
14
14
|
*/
|
|
15
|
+
declare type Chrome = () => JSX.Element;
|
|
16
|
+
declare type ChromeBuffer = Chrome[];
|
|
15
17
|
export declare class NestedCards {
|
|
16
18
|
private columns;
|
|
17
19
|
private filteredRows;
|
|
@@ -40,7 +42,7 @@ export declare class NestedCards {
|
|
|
40
42
|
* I.e. due to the flatness of our DOM, we inherently have to add a "close"
|
|
41
43
|
* row separate from the card's actual content.
|
|
42
44
|
*/
|
|
43
|
-
export declare function makeOpenOrCloseCard(openCards: NestedCardStyle[], kind: "open" | "close"):
|
|
45
|
+
export declare function makeOpenOrCloseCard(openCards: NestedCardStyle[], kind: "open" | "close"): Chrome;
|
|
44
46
|
/**
|
|
45
47
|
* For the first or last cell of actual content, wrap them in divs that re-create the
|
|
46
48
|
* outer cards' padding + background.
|
|
@@ -52,7 +54,7 @@ export declare function maybeAddCardPadding(openCards: NestedCardStyle[], column
|
|
|
52
54
|
* Our height is not based on `openCards`, b/c for the top-most level, we won't
|
|
53
55
|
* have any open cards, but still want a space between top-level cards.
|
|
54
56
|
*/
|
|
55
|
-
export declare function makeSpacer(height: number, openCards: NestedCardStyle[]):
|
|
57
|
+
export declare function makeSpacer(height: number, openCards: NestedCardStyle[]): Chrome;
|
|
56
58
|
/**
|
|
57
59
|
* Takes the current buffer of close row(s), spacers, and open row, and creates a single chrome DOM row.
|
|
58
60
|
*
|
|
@@ -65,5 +67,11 @@ export declare function makeSpacer(height: number, openCards: NestedCardStyle[])
|
|
|
65
67
|
* - nested card2 content row
|
|
66
68
|
* - chrome row (card2 close, card1 close)
|
|
67
69
|
*/
|
|
68
|
-
export declare function maybeCreateChromeRow(columns: GridColumn<any>[], filteredRows: RowTuple<any>[], chromeBuffer:
|
|
70
|
+
export declare function maybeCreateChromeRow(columns: GridColumn<any>[], filteredRows: RowTuple<any>[], chromeBuffer: ChromeBuffer): void;
|
|
71
|
+
interface ChromeRowProps {
|
|
72
|
+
chromeBuffer: ChromeBuffer;
|
|
73
|
+
columns: number;
|
|
74
|
+
}
|
|
75
|
+
export declare function ChromeRow({ chromeBuffer, columns }: ChromeRowProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
69
76
|
export declare function dropChromeRows<R extends Kinded>(filteredRows: RowTuple<R>[]): [GridDataRow<R>, ReactElement][];
|
|
77
|
+
export {};
|
|
@@ -1,21 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.dropChromeRows = exports.maybeCreateChromeRow = exports.makeSpacer = exports.maybeAddCardPadding = exports.makeOpenOrCloseCard = exports.NestedCards = void 0;
|
|
3
|
+
exports.dropChromeRows = exports.ChromeRow = exports.maybeCreateChromeRow = exports.makeSpacer = exports.maybeAddCardPadding = exports.makeOpenOrCloseCard = exports.NestedCards = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const Css_1 = require("../../Css");
|
|
7
|
-
/**
|
|
8
|
-
* A helper class to create our nested card DOM shenanigans.
|
|
9
|
-
*
|
|
10
|
-
* This acts as a one-off visitor that accepts "begin row", "between row",
|
|
11
|
-
* "end row" calls from GridTable while its translating the user's nested
|
|
12
|
-
* GridDataRows into a flat list of RowTuples, and interjects fake/chrome
|
|
13
|
-
* rows into `filteredRows` as necessary.
|
|
14
|
-
*
|
|
15
|
-
* Note that this class only handles *between row* chrome and that within
|
|
16
|
-
* a content row itself, the nested padding is handled separately by the
|
|
17
|
-
* GridRow component.
|
|
18
|
-
*/
|
|
19
7
|
class NestedCards {
|
|
20
8
|
constructor(columns, filteredRows, style) {
|
|
21
9
|
this.columns = columns;
|
|
@@ -68,29 +56,32 @@ exports.NestedCards = NestedCards;
|
|
|
68
56
|
* row separate from the card's actual content.
|
|
69
57
|
*/
|
|
70
58
|
function makeOpenOrCloseCard(openCards, kind) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
59
|
+
const scopeCards = [...openCards];
|
|
60
|
+
return () => {
|
|
61
|
+
let div = (0, jsx_runtime_1.jsx)("div", {}, void 0);
|
|
62
|
+
const place = kind === "open" ? "Top" : "Bottom";
|
|
63
|
+
const btOrBb = kind === "open" ? "bt" : "bb";
|
|
64
|
+
// Create nesting for the all open cards, i.e.:
|
|
65
|
+
//
|
|
66
|
+
// | card1 | card2 -------------- card2 | card1 |
|
|
67
|
+
// | card1 | card2 / ... card3 ... \ card2 | card1 |
|
|
68
|
+
// | card1 | card2 | ... card3 ... | card2 | card1 |
|
|
69
|
+
//
|
|
70
|
+
[...scopeCards].reverse().forEach((card, i) => {
|
|
71
|
+
const first = i === 0;
|
|
72
|
+
div = ((0, jsx_runtime_1.jsx)("div", Object.assign({ css: {
|
|
73
|
+
...Css_1.Css.bgColor(card.bgColor).pxPx(card.pxPx).$,
|
|
74
|
+
// Only the 1st div needs border left/right radius + border top/bottom.
|
|
75
|
+
...(first &&
|
|
76
|
+
Css_1.Css.add({
|
|
77
|
+
[`border${place}RightRadius`]: `${card.brPx}px`,
|
|
78
|
+
[`border${place}LeftRadius`]: `${card.brPx}px`,
|
|
79
|
+
}).hPx(card.brPx).$),
|
|
80
|
+
...(card.bColor && Css_1.Css.bc(card.bColor).bl.br.if(first)[btOrBb].$),
|
|
81
|
+
} }, { children: div }), void 0));
|
|
82
|
+
});
|
|
83
|
+
return div;
|
|
84
|
+
};
|
|
94
85
|
}
|
|
95
86
|
exports.makeOpenOrCloseCard = makeOpenOrCloseCard;
|
|
96
87
|
/**
|
|
@@ -116,13 +107,16 @@ exports.maybeAddCardPadding = maybeAddCardPadding;
|
|
|
116
107
|
* have any open cards, but still want a space between top-level cards.
|
|
117
108
|
*/
|
|
118
109
|
function makeSpacer(height, openCards) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
110
|
+
const scopeCards = [...openCards];
|
|
111
|
+
return () => {
|
|
112
|
+
let div = (0, jsx_runtime_1.jsx)("div", { css: Css_1.Css.hPx(height).$ }, void 0);
|
|
113
|
+
// Start at the current/inside card, and wrap outward padding + borders.
|
|
114
|
+
// | card1 | card2 | ... card3 ... | card2 | card1 |
|
|
115
|
+
[...scopeCards].reverse().forEach((card) => {
|
|
116
|
+
div = (0, jsx_runtime_1.jsx)("div", Object.assign({ css: Css_1.Css.bgColor(card.bgColor).pxPx(card.pxPx).if(!!card.bColor).bc(card.bColor).bl.br.$ }, { children: div }), void 0);
|
|
117
|
+
});
|
|
118
|
+
return div;
|
|
119
|
+
};
|
|
126
120
|
}
|
|
127
121
|
exports.makeSpacer = makeSpacer;
|
|
128
122
|
/**
|
|
@@ -139,16 +133,18 @@ exports.makeSpacer = makeSpacer;
|
|
|
139
133
|
*/
|
|
140
134
|
function maybeCreateChromeRow(columns, filteredRows, chromeBuffer) {
|
|
141
135
|
if (chromeBuffer.length > 0) {
|
|
142
|
-
filteredRows.push([
|
|
143
|
-
undefined,
|
|
144
|
-
// We add 2 to account for our dedicated open/close columns
|
|
145
|
-
(0, jsx_runtime_1.jsx)("div", Object.assign({ css: Css_1.Css.gc(`span ${columns.length + 2}`).$, "data-chrome": "true" }, { children: chromeBuffer.map((c, i) => ((0, jsx_runtime_1.jsx)(react_1.Fragment, { children: c }, i))) }), void 0),
|
|
146
|
-
]);
|
|
136
|
+
filteredRows.push([undefined, (0, jsx_runtime_1.jsx)(ChromeRow, { chromeBuffer: [...chromeBuffer], columns: columns.length }, void 0)]);
|
|
147
137
|
// clear the buffer
|
|
148
138
|
chromeBuffer.splice(0, chromeBuffer.length);
|
|
149
139
|
}
|
|
150
140
|
}
|
|
151
141
|
exports.maybeCreateChromeRow = maybeCreateChromeRow;
|
|
142
|
+
function ChromeRow({ chromeBuffer, columns }) {
|
|
143
|
+
return (
|
|
144
|
+
// We add 2 to account for our dedicated open/close columns
|
|
145
|
+
(0, jsx_runtime_1.jsx)("div", Object.assign({ css: Css_1.Css.gc(`span ${columns + 2}`).$, "data-chrome": "true" }, { children: chromeBuffer.map((c, i) => ((0, jsx_runtime_1.jsx)(react_1.Fragment, { children: c() }, i))) }), void 0));
|
|
146
|
+
}
|
|
147
|
+
exports.ChromeRow = ChromeRow;
|
|
152
148
|
function dropChromeRows(filteredRows) {
|
|
153
149
|
return filteredRows.filter(([r]) => !!r);
|
|
154
150
|
}
|
|
@@ -9,4 +9,6 @@ interface TooltipProps {
|
|
|
9
9
|
}
|
|
10
10
|
export declare function Tooltip(props: TooltipProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
11
11
|
export declare type Placement = "top" | "bottom" | "left" | "right" | "auto";
|
|
12
|
+
export declare function maybeTooltip(props: TooltipProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
13
|
+
export declare function resolveTooltip(disabled?: boolean | ReactNode, tooltip?: ReactNode): ReactNode | undefined;
|
|
12
14
|
export {};
|
|
@@ -19,7 +19,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
21
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.Tooltip = void 0;
|
|
22
|
+
exports.resolveTooltip = exports.maybeTooltip = exports.Tooltip = void 0;
|
|
23
23
|
const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
|
|
24
24
|
const react_1 = __importStar(require("react"));
|
|
25
25
|
const react_aria_1 = require("react-aria");
|
|
@@ -48,3 +48,14 @@ function Popper({ triggerRef, content, placement = "auto" }) {
|
|
|
48
48
|
});
|
|
49
49
|
return (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsxs)("div", Object.assign({ ref: popperRef, style: styles.popper }, attributes.popper, { css: Css_1.Css.maxw("320px").bgGray900.white.px1.py("4px").br4.xs.z999.$ }, { children: [(0, jsx_runtime_1.jsx)("div", { ref: setArrowRef, style: { ...styles.arrow }, id: "arrow" }, void 0), content] }), void 0), document.body);
|
|
50
50
|
}
|
|
51
|
+
// Helper function to conditionally wrap component with Tooltip if necessary.
|
|
52
|
+
function maybeTooltip(props) {
|
|
53
|
+
return props.title ? (0, jsx_runtime_1.jsx)(Tooltip, Object.assign({}, props), void 0) : props.children;
|
|
54
|
+
}
|
|
55
|
+
exports.maybeTooltip = maybeTooltip;
|
|
56
|
+
// Helper function for resolving showing the Tooltip text via a 'disabled' prop, or the 'tooltip' prop.
|
|
57
|
+
function resolveTooltip(disabled, tooltip) {
|
|
58
|
+
// If `disabled` is a ReactNode, then return that. Otherwise, return `tooltip`
|
|
59
|
+
return typeof disabled !== "boolean" && disabled ? disabled : tooltip !== null && tooltip !== void 0 ? tooltip : undefined;
|
|
60
|
+
}
|
|
61
|
+
exports.resolveTooltip = resolveTooltip;
|
|
@@ -13,19 +13,22 @@ const PresentationContext_1 = require("../components/PresentationContext");
|
|
|
13
13
|
const Css_1 = require("../Css");
|
|
14
14
|
const ChipTextField_1 = require("./ChipTextField");
|
|
15
15
|
const ListBox_1 = require("./internal/ListBox");
|
|
16
|
+
const ListBoxChip_1 = require("./internal/ListBoxChip");
|
|
16
17
|
const Value_1 = require("./Value");
|
|
17
18
|
const utils_1 = require("../utils");
|
|
19
|
+
const options_1 = require("../utils/options");
|
|
18
20
|
function ChipSelectField(props) {
|
|
19
21
|
var _a, _b;
|
|
22
|
+
const firstRender = (0, react_1.useRef)(true);
|
|
20
23
|
const { fieldProps } = (0, PresentationContext_1.usePresentationContext)();
|
|
21
|
-
const { label, value, disabled = false, placeholder = "Select an option", options, onSelect, getOptionValue =
|
|
22
|
-
getOptionLabel =
|
|
24
|
+
const { label, value, disabled = false, placeholder = "Select an option", options, onSelect, getOptionValue = options_1.defaultOptionValue, // if unset, assume O implements HasId
|
|
25
|
+
getOptionLabel = options_1.defaultOptionLabel, // if unset, assume O implements HasName
|
|
23
26
|
onFocus, onBlur, clearable = false, onCreateNew, } = props;
|
|
24
27
|
const tid = (0, utils_1.useTestIds)(props, "chipSelectField");
|
|
25
28
|
const typeScale = (_a = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.typeScale) !== null && _a !== void 0 ? _a : "sm";
|
|
26
29
|
const isDisabled = !!disabled;
|
|
27
30
|
const showClearButton = !disabled && clearable && !!value;
|
|
28
|
-
const chipStyles = Css_1.Css[typeScale].tl.bgGray300.gray900.br16.pxPx(10).pyPx(2)
|
|
31
|
+
const chipStyles = (0, react_1.useMemo)(() => Css_1.Css[typeScale].tl.bgGray300.gray900.br16.pxPx(10).pyPx(2).$, [typeScale]);
|
|
29
32
|
// Controls showing the focus border styles.
|
|
30
33
|
const [visualFocus, setVisualFocus] = (0, react_1.useState)(false);
|
|
31
34
|
const [isClearFocused, setIsClearFocused] = (0, react_1.useState)(false);
|
|
@@ -63,20 +66,34 @@ function ChipSelectField(props) {
|
|
|
63
66
|
initialSelectedKeys: [(0, Value_1.valueToKey)(value)],
|
|
64
67
|
getKey: (item) => (isListBoxSection(item) ? item.title : getOptionValue(item)),
|
|
65
68
|
});
|
|
66
|
-
(0, react_1.useEffect)(() =>
|
|
67
|
-
|
|
69
|
+
(0, react_1.useEffect)(() => {
|
|
70
|
+
// Avoid unnecessary update of `options` on first render. We define the initial set of items based on the options in the `useListData` hook.
|
|
71
|
+
if (!firstRender.current) {
|
|
72
|
+
if (onCreateNew) {
|
|
73
|
+
// if we have the options in a section, update that section
|
|
74
|
+
listData.update("Options", { title: "Options", options });
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
// otherwise, reset the list completely. We could traverse through the list and update/add/remove when needed, though this is simpler for now.
|
|
78
|
+
listData.remove(...state.collection.getKeys());
|
|
79
|
+
listData.append(...options);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
firstRender.current = false;
|
|
83
|
+
}, [options]);
|
|
84
|
+
const selectChildren = (0, react_1.useMemo)(() => listData.items.map((s) => {
|
|
68
85
|
if (isListBoxSection(s)) {
|
|
69
86
|
return ((0, jsx_runtime_1.jsx)(react_stately_1.Section, Object.assign({ title: s.title, items: s.options }, { children: (item) => {
|
|
70
87
|
if (isPersistentItem(item)) {
|
|
71
88
|
return ((0, jsx_runtime_1.jsx)(react_stately_1.Item, Object.assign({ textValue: item.name }, { children: item.name }), item.id));
|
|
72
89
|
}
|
|
73
90
|
const label = getOptionLabel(item);
|
|
74
|
-
return ((0, jsx_runtime_1.jsx)(react_stately_1.Item, Object.assign({ textValue: label }, { children: (0, jsx_runtime_1.jsx)(
|
|
91
|
+
return ((0, jsx_runtime_1.jsx)(react_stately_1.Item, Object.assign({ textValue: label }, { children: (0, jsx_runtime_1.jsx)(ListBoxChip_1.ListBoxChip, { label: label }, void 0) }), getOptionValue(item)));
|
|
75
92
|
} }), (0, change_case_1.camelCase)(s.title)));
|
|
76
93
|
}
|
|
77
94
|
const label = getOptionLabel(s);
|
|
78
|
-
return ((0, jsx_runtime_1.jsx)(react_stately_1.Item, Object.assign({ textValue: label }, { children: (0, jsx_runtime_1.jsx)(
|
|
79
|
-
});
|
|
95
|
+
return ((0, jsx_runtime_1.jsx)(react_stately_1.Item, Object.assign({ textValue: label }, { children: (0, jsx_runtime_1.jsx)(ListBoxChip_1.ListBoxChip, { label: label }, void 0) }), getOptionValue(s)));
|
|
96
|
+
}), [listData.items, getOptionLabel, getOptionValue]);
|
|
80
97
|
const selectHookProps = {
|
|
81
98
|
label,
|
|
82
99
|
isDisabled,
|
|
@@ -135,36 +152,36 @@ function ChipSelectField(props) {
|
|
|
135
152
|
};
|
|
136
153
|
// State management for the "Create new" flow with ChipTextField.
|
|
137
154
|
const [showInput, setShowInput] = (0, react_1.useState)(false);
|
|
138
|
-
const [inputValue, setInputValue] = (0, react_1.useState)("Add new");
|
|
139
155
|
const removeCreateNewField = (0, react_1.useCallback)(() => {
|
|
140
156
|
setShowInput(false);
|
|
141
|
-
setInputValue("Add new");
|
|
142
157
|
// Trigger onBlur to initiate any auto-saving behavior.
|
|
143
158
|
(0, utils_1.maybeCall)(onBlur);
|
|
144
|
-
}, [setShowInput
|
|
145
|
-
|
|
146
|
-
await onCreateNew(
|
|
159
|
+
}, [setShowInput]);
|
|
160
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [showInput && onCreateNew && ((0, jsx_runtime_1.jsx)(CreateNewField, Object.assign({ onBlur: removeCreateNewField, onEnter: async (value) => {
|
|
161
|
+
await onCreateNew(value);
|
|
147
162
|
removeCreateNewField();
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
163
|
+
} }, tid.createNewField), void 0)), (0, components_1.maybeTooltip)({
|
|
164
|
+
title: (0, components_1.resolveTooltip)(disabled),
|
|
165
|
+
placement: "top",
|
|
166
|
+
children: ((0, jsx_runtime_1.jsxs)("div", Object.assign({ ref: wrapperRef, css: {
|
|
167
|
+
...chipStyles,
|
|
168
|
+
...Css_1.Css.dif.relative.p0.mwPx(32).if(!value).bgGray200.$,
|
|
169
|
+
...(visualFocus ? Css_1.Css.bshFocus.$ : {}),
|
|
170
|
+
...(showInput ? Css_1.Css.dn.$ : {}),
|
|
171
|
+
} }, { children: [(0, jsx_runtime_1.jsx)(Label_1.Label, Object.assign({ label: label, labelProps: labelProps, hidden: true }, tid.label), void 0), (0, jsx_runtime_1.jsx)("button", Object.assign({}, (0, react_aria_1.mergeProps)(focusProps, buttonProps), { ref: buttonRef, css: {
|
|
172
|
+
...Css_1.Css.tl.br16.pxPx(10).pyPx(2).outline0.if(showClearButton).prPx(4).borderRadius("16px 0 0 16px").$,
|
|
173
|
+
...(isDisabled ? Css_1.Css.cursorNotAllowed.gray700.$ : {}),
|
|
174
|
+
"&:hover:not(:disabled)": Css_1.Css.bgGray400.if(!value).bgGray300.$,
|
|
175
|
+
}, title: state.selectedItem ? state.selectedItem.textValue : placeholder }, tid, { children: (0, jsx_runtime_1.jsx)("span", Object.assign({}, valueProps, { css: Css_1.Css.lineClamp1.breakAll.$ }, { children: state.selectedItem ? state.selectedItem.textValue : placeholder }), void 0) }), void 0), showClearButton && ((0, jsx_runtime_1.jsx)("button", Object.assign({}, clearFocusProps, { css: {
|
|
176
|
+
...Css_1.Css.prPx(4).borderRadius("0 16px 16px 0").outline0.$,
|
|
177
|
+
"&:hover": Css_1.Css.bgGray400.$,
|
|
178
|
+
...(isClearFocused ? Css_1.Css.boxShadow(`0px 0px 0px 2px rgba(3,105,161,1)`).$ : {}),
|
|
179
|
+
}, onClick: () => {
|
|
180
|
+
onSelect(undefined, undefined);
|
|
181
|
+
(0, utils_1.maybeCall)(onBlur);
|
|
182
|
+
setIsClearFocused(false);
|
|
183
|
+
}, "aria-label": "Remove" }, tid.clearButton, { children: (0, jsx_runtime_1.jsx)(components_1.Icon, { icon: "x", inc: typeScale === "xs" ? 2 : undefined }, void 0) }), void 0))] }), void 0)),
|
|
184
|
+
}), state.isOpen && ((0, jsx_runtime_1.jsx)(internal_1.Popover, Object.assign({ triggerRef: buttonRef, popoverRef: popoverRef, positionProps: overlayProps, onClose: state.close, isOpen: state.isOpen, shouldCloseOnBlur: true }, { children: (0, jsx_runtime_1.jsx)(ListBox_1.ListBox, Object.assign({}, menuProps, { listBoxRef: listBoxRef, state: state, getOptionLabel: getOptionLabel, getOptionValue: getOptionValue, positionProps: overlayProps }), void 0) }), void 0))] }, void 0));
|
|
168
185
|
}
|
|
169
186
|
exports.ChipSelectField = ChipSelectField;
|
|
170
187
|
exports.persistentItemPrefix = "persistentItem:";
|
|
@@ -184,3 +201,10 @@ function isListBoxSection(obj) {
|
|
|
184
201
|
return typeof obj === "object" && "options" in obj;
|
|
185
202
|
}
|
|
186
203
|
exports.isListBoxSection = isListBoxSection;
|
|
204
|
+
// Wrapper for the ChipTextField used in the "Create New" flow on ChipSelectField
|
|
205
|
+
function CreateNewField(props) {
|
|
206
|
+
const { onBlur, onEnter } = props;
|
|
207
|
+
const [value, setValue] = (0, react_1.useState)("Add new");
|
|
208
|
+
const tid = (0, utils_1.useTestIds)(props);
|
|
209
|
+
return ((0, jsx_runtime_1.jsx)(ChipTextField_1.ChipTextField, Object.assign({ autoFocus: true, label: "Add new", value: value, onChange: setValue, onEnter: () => onEnter(value), onBlur: onBlur }, tid), void 0));
|
|
210
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
|
+
import { TextFieldBaseProps } from "./TextFieldBase";
|
|
2
3
|
import "./DateField.css";
|
|
3
|
-
export interface DateFieldProps {
|
|
4
|
+
export interface DateFieldProps extends Pick<TextFieldBaseProps<{}>, "borderless" | "visuallyDisabled" | "hideLabel" | "compact"> {
|
|
4
5
|
value: Date | undefined;
|
|
5
6
|
label: string;
|
|
6
7
|
onChange: (value: Date) => void;
|
|
@@ -8,7 +9,7 @@ export interface DateFieldProps {
|
|
|
8
9
|
onBlur?: () => void;
|
|
9
10
|
/** Called when the component is in focus. */
|
|
10
11
|
onFocus?: () => void;
|
|
11
|
-
disabled?: boolean;
|
|
12
|
+
disabled?: boolean | ReactNode;
|
|
12
13
|
errorMsg?: string;
|
|
13
14
|
required?: boolean;
|
|
14
15
|
readOnly?: boolean;
|
|
@@ -16,11 +17,8 @@ export interface DateFieldProps {
|
|
|
16
17
|
/** Renders the label inside the input field, i.e. for filters. */
|
|
17
18
|
inlineLabel?: boolean;
|
|
18
19
|
placeholder?: string;
|
|
19
|
-
compact?: boolean;
|
|
20
20
|
format?: keyof typeof dateFormats;
|
|
21
21
|
iconLeft?: boolean;
|
|
22
|
-
hideLabel?: boolean;
|
|
23
|
-
borderless?: boolean;
|
|
24
22
|
}
|
|
25
23
|
export declare function DateField(props: DateFieldProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
26
24
|
declare const dateFormats: {
|
package/dist/inputs/DateField.js
CHANGED
|
@@ -16,7 +16,7 @@ const utils_1 = require("../utils");
|
|
|
16
16
|
const defaultTestId_1 = require("../utils/defaultTestId");
|
|
17
17
|
require("./DateField.css");
|
|
18
18
|
function DateField(props) {
|
|
19
|
-
const { label, disabled
|
|
19
|
+
const { label, disabled, required, value, onChange, onFocus, onBlur, errorMsg, helperText, inlineLabel = false, readOnly = false, format = "short", iconLeft = false, ...others } = props;
|
|
20
20
|
const inputRef = (0, react_1.useRef)(null);
|
|
21
21
|
const inputWrapRef = (0, react_1.useRef)(null);
|
|
22
22
|
const buttonRef = (0, react_1.useRef)(null);
|
|
@@ -26,6 +26,7 @@ function DateField(props) {
|
|
|
26
26
|
const dateFormat = getDateFormat(format);
|
|
27
27
|
const [inputValue, setInputValue] = (0, react_1.useState)(value ? formatDate(value, dateFormat) : "");
|
|
28
28
|
const tid = (0, utils_1.useTestIds)(props, (0, defaultTestId_1.defaultTestId)(label));
|
|
29
|
+
const isDisabled = !!disabled;
|
|
29
30
|
(0, react_1.useEffect)(() => {
|
|
30
31
|
// Avoid updating any WIP values.
|
|
31
32
|
if (!isFocused) {
|
|
@@ -35,7 +36,7 @@ function DateField(props) {
|
|
|
35
36
|
const textFieldProps = {
|
|
36
37
|
...others,
|
|
37
38
|
label,
|
|
38
|
-
isDisabled
|
|
39
|
+
isDisabled,
|
|
39
40
|
isReadOnly: readOnly,
|
|
40
41
|
"aria-haspopup": "dialog",
|
|
41
42
|
value: inputValue,
|
|
@@ -86,7 +87,7 @@ function DateField(props) {
|
|
|
86
87
|
const { triggerProps, overlayProps } = (0, react_aria_1.useOverlayTrigger)({ type: "dialog" }, state, buttonRef);
|
|
87
88
|
const { buttonProps } = (0, react_aria_1.useButton)({
|
|
88
89
|
...triggerProps,
|
|
89
|
-
isDisabled:
|
|
90
|
+
isDisabled: isDisabled || readOnly,
|
|
90
91
|
// When pressed or focused then move focus the input, which will select the text and trigger the DatePicker to open
|
|
91
92
|
onPress: () => { var _a; return (_a = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _a === void 0 ? void 0 : _a.focus(); },
|
|
92
93
|
onFocus: () => { var _a; return (_a = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _a === void 0 ? void 0 : _a.focus(); },
|
|
@@ -107,7 +108,7 @@ function DateField(props) {
|
|
|
107
108
|
// How do other applications handle this defined sizing? Appears they use hard coded widths depending on format, which is similar here (using `size` instead of css `width`).
|
|
108
109
|
// But would also need to allow for the input to be `fullWidth`, which is basically also what we're accomplishing here... so maybe fine?
|
|
109
110
|
const inputSize = format === "short" ? 8 : format === "medium" ? 10 : undefined;
|
|
110
|
-
const calendarButton = ((0, jsx_runtime_1.jsx)("button", Object.assign({ ref: buttonRef }, buttonProps, { disabled:
|
|
111
|
+
const calendarButton = ((0, jsx_runtime_1.jsx)("button", Object.assign({ ref: buttonRef }, buttonProps, { disabled: isDisabled, css: Css_1.Css.if(isDisabled).cursorNotAllowed.$, tabIndex: -1 }, tid.calendarButton, { children: (0, jsx_runtime_1.jsx)(components_1.Icon, { icon: "calendar", color: Css_1.Palette.Gray700 }, void 0) }), void 0));
|
|
111
112
|
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(TextFieldBase_1.TextFieldBase, Object.assign({}, textFieldProps, { readOnly: readOnly, errorMsg: errorMsg, helperText: helperText, required: required, labelProps: labelProps, inputProps: { ...triggerProps, ...inputProps, size: inputSize }, inputRef: inputRef, inputWrapRef: inputWrapRef, inlineLabel: inlineLabel, onChange: (v) => {
|
|
112
113
|
// hide the calendar if the user is manually entering the date
|
|
113
114
|
state.close();
|
|
@@ -119,7 +120,7 @@ function DateField(props) {
|
|
|
119
120
|
onChange(parsed);
|
|
120
121
|
}
|
|
121
122
|
}
|
|
122
|
-
}, endAdornment: !iconLeft && calendarButton, startAdornment: iconLeft && calendarButton }, others), void 0), state.isOpen && ((0, jsx_runtime_1.jsx)(internal_1.Popover, Object.assign({ triggerRef: inputWrapRef, popoverRef: overlayRef, positionProps: { ...overlayProps, ...positionProps }, onClose: state.close, isOpen: state.isOpen }, { children: (0, jsx_runtime_1.jsx)(DatePickerOverlay_1.DatePickerOverlay, Object.assign({ state: state, value: value, positionProps: positionProps, onChange: (d) => {
|
|
123
|
+
}, endAdornment: !iconLeft && calendarButton, startAdornment: iconLeft && calendarButton, tooltip: isDisabled && typeof disabled !== "boolean" ? disabled : undefined }, others), void 0), state.isOpen && ((0, jsx_runtime_1.jsx)(internal_1.Popover, Object.assign({ triggerRef: inputWrapRef, popoverRef: overlayRef, positionProps: { ...overlayProps, ...positionProps }, onClose: state.close, isOpen: state.isOpen }, { children: (0, jsx_runtime_1.jsx)(DatePickerOverlay_1.DatePickerOverlay, Object.assign({ state: state, value: value, positionProps: positionProps, onChange: (d) => {
|
|
123
124
|
setInputValue(formatDate(d, dateFormat));
|
|
124
125
|
onChange(d);
|
|
125
126
|
} }, tid.datePicker), void 0) }), void 0))] }, void 0));
|
|
@@ -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
|
-
interface TextFieldBaseProps<X> extends Pick<BeamTextFieldProps<X>, "label" | "required" | "readOnly" | "errorMsg" | "onBlur" | "onFocus" | "helperText" | "hideLabel" | "placeholder" | "compact" | "borderless" | "xss">, Partial<Pick<BeamTextFieldProps<X>, "onChange">> {
|
|
5
|
+
export interface TextFieldBaseProps<X> extends Pick<BeamTextFieldProps<X>, "label" | "required" | "readOnly" | "errorMsg" | "onBlur" | "onFocus" | "helperText" | "hideLabel" | "placeholder" | "compact" | "borderless" | "visuallyDisabled" | "xss">, Partial<Pick<BeamTextFieldProps<X>, "onChange">> {
|
|
6
6
|
labelProps?: LabelHTMLAttributes<HTMLLabelElement>;
|
|
7
7
|
inputProps: InputHTMLAttributes<HTMLInputElement> | TextareaHTMLAttributes<HTMLTextAreaElement>;
|
|
8
8
|
inputRef?: MutableRefObject<HTMLInputElement | HTMLTextAreaElement | null>;
|
|
@@ -15,6 +15,6 @@ interface TextFieldBaseProps<X> extends Pick<BeamTextFieldProps<X>, "label" | "r
|
|
|
15
15
|
contrast?: boolean;
|
|
16
16
|
clearable?: boolean;
|
|
17
17
|
textAreaMinHeight?: number;
|
|
18
|
+
tooltip?: ReactNode;
|
|
18
19
|
}
|
|
19
20
|
export declare function TextFieldBase<X extends Only<TextFieldXss, X>>(props: TextFieldBaseProps<X>): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
20
|
-
export {};
|
|
@@ -15,10 +15,10 @@ const defaultTestId_1 = require("../utils/defaultTestId");
|
|
|
15
15
|
const useTestIds_1 = require("../utils/useTestIds");
|
|
16
16
|
// Used by both TextField and TextArea
|
|
17
17
|
function TextFieldBase(props) {
|
|
18
|
-
var _a, _b, _c, _d, _e;
|
|
18
|
+
var _a, _b, _c, _d, _e, _f;
|
|
19
19
|
const { fieldProps } = (0, PresentationContext_1.usePresentationContext)();
|
|
20
|
-
const { label, required, labelProps, hideLabel = (_a = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.hideLabel) !== null && _a !== void 0 ? _a : false, inputProps, inputRef, inputWrapRef, groupProps, compact = (_b = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.compact) !== null && _b !== void 0 ? _b : false, errorMsg, helperText, multiline = false, readOnly, onChange, onBlur, onFocus, xss, endAdornment, startAdornment, inlineLabel, contrast = false, borderless = (_c = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.borderless) !== null && _c !== void 0 ? _c : false, textAreaMinHeight = 96, clearable = false, } = props;
|
|
21
|
-
const typeScale = (
|
|
20
|
+
const { label, required, labelProps, hideLabel = (_a = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.hideLabel) !== null && _a !== void 0 ? _a : false, inputProps, inputRef, inputWrapRef, groupProps, compact = (_b = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.compact) !== null && _b !== void 0 ? _b : false, errorMsg, helperText, multiline = false, readOnly, onChange, onBlur, onFocus, xss, endAdornment, startAdornment, inlineLabel, contrast = false, borderless = (_c = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.borderless) !== null && _c !== void 0 ? _c : false, textAreaMinHeight = 96, clearable = false, tooltip, visuallyDisabled = (_d = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.visuallyDisabled) !== null && _d !== void 0 ? _d : true, } = props;
|
|
21
|
+
const typeScale = (_e = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.typeScale) !== null && _e !== void 0 ? _e : "sm";
|
|
22
22
|
const internalProps = props.internalProps || {};
|
|
23
23
|
const { compound = false } = internalProps;
|
|
24
24
|
const errorMessageId = `${inputProps.id}-error`;
|
|
@@ -57,7 +57,9 @@ function TextFieldBase(props) {
|
|
|
57
57
|
},
|
|
58
58
|
hover: Css_1.Css.bgGray100.if(contrast).bgGray600.bGray600.$,
|
|
59
59
|
focus: borderless ? Css_1.Css.bshFocus.$ : Css_1.Css.bLightBlue700.if(contrast).bLightBlue500.$,
|
|
60
|
-
disabled:
|
|
60
|
+
disabled: visuallyDisabled
|
|
61
|
+
? Css_1.Css.cursorNotAllowed.gray400.bgGray100.if(contrast).gray500.bgGray700.$
|
|
62
|
+
: Css_1.Css.cursorNotAllowed.$,
|
|
61
63
|
error: Css_1.Css.bRed600.if(contrast).bRed400.$,
|
|
62
64
|
};
|
|
63
65
|
// Watch for each WIP change, convert empty to undefined, and call the user's onChange
|
|
@@ -81,25 +83,30 @@ function TextFieldBase(props) {
|
|
|
81
83
|
...(multiline ? Css_1.Css.fdc.aifs.childGap2.$ : Css_1.Css.truncate.$),
|
|
82
84
|
...xss,
|
|
83
85
|
}, "data-readonly": "true" }, tid, { children: [!multiline && inlineLabel && label && !hideLabel && ((0, jsx_runtime_1.jsx)(Label_1.InlineLabel, Object.assign({ labelProps: labelProps, label: label }, tid.label), void 0)), multiline
|
|
84
|
-
? (
|
|
85
|
-
: inputProps.value] }), void 0)), !readOnly &&
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
...Css_1.Css.if(multiline).aifs.px0.mhPx(textAreaMinHeight).$,
|
|
92
|
-
} }, hoverProps, { ref: inputWrapRef }, { children: [!multiline && inlineLabel && label && !hideLabel && ((0, jsx_runtime_1.jsx)(Label_1.InlineLabel, Object.assign({ labelProps: labelProps, label: label }, tid.label), void 0)), !multiline && startAdornment && (0, jsx_runtime_1.jsx)("span", Object.assign({ css: Css_1.Css.df.aic.fs0.br4.pr1.$ }, { children: startAdornment }), void 0), (0, jsx_runtime_1.jsx)(ElementType, Object.assign({}, (0, react_aria_1.mergeProps)(inputProps, { onBlur, onFocus: onFocusChained, onChange: onDomChange }, { "aria-invalid": Boolean(errorMsg), ...(hideLabel ? { "aria-label": label } : {}) }), (errorMsg ? { "aria-errormessage": errorMessageId } : {}), { ref: fieldRef, rows: multiline ? 1 : undefined, css: {
|
|
93
|
-
...fieldStyles.input,
|
|
86
|
+
? (_f = inputProps.value) === null || _f === void 0 ? void 0 : _f.split("\n\n").map((p, i) => ((0, jsx_runtime_1.jsx)("p", Object.assign({ css: Css_1.Css.my1.$ }, { children: p.split("\n").map((sentence, j) => ((0, jsx_runtime_1.jsxs)("span", { children: [sentence, (0, jsx_runtime_1.jsx)("br", {}, void 0)] }, j))) }), i)))
|
|
87
|
+
: inputProps.value] }), void 0)), !readOnly &&
|
|
88
|
+
(0, components_1.maybeTooltip)({
|
|
89
|
+
title: tooltip,
|
|
90
|
+
placement: "top",
|
|
91
|
+
children: ((0, jsx_runtime_1.jsxs)("div", Object.assign({ css: {
|
|
92
|
+
...fieldStyles.inputWrapper,
|
|
94
93
|
...(inputProps.disabled ? fieldStyles.disabled : {}),
|
|
94
|
+
...(isFocused && !readOnly ? fieldStyles.focus : {}),
|
|
95
95
|
...(isHovered && !inputProps.disabled && !readOnly && !isFocused ? fieldStyles.hover : {}),
|
|
96
|
-
...(
|
|
97
|
-
...
|
|
98
|
-
} },
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
96
|
+
...(errorMsg ? fieldStyles.error : {}),
|
|
97
|
+
...Css_1.Css.if(multiline).aifs.px0.mhPx(textAreaMinHeight).$,
|
|
98
|
+
} }, hoverProps, { ref: inputWrapRef }, { children: [!multiline && inlineLabel && label && !hideLabel && ((0, jsx_runtime_1.jsx)(Label_1.InlineLabel, Object.assign({ labelProps: labelProps, label: label }, tid.label), void 0)), !multiline && startAdornment && (0, jsx_runtime_1.jsx)("span", Object.assign({ css: Css_1.Css.df.aic.fs0.br4.pr1.$ }, { children: startAdornment }), void 0), (0, jsx_runtime_1.jsx)(ElementType, Object.assign({}, (0, react_aria_1.mergeProps)(inputProps, { onBlur, onFocus: onFocusChained, onChange: onDomChange }, { "aria-invalid": Boolean(errorMsg), ...(hideLabel ? { "aria-label": label } : {}) }), (errorMsg ? { "aria-errormessage": errorMessageId } : {}), { ref: fieldRef, rows: multiline ? 1 : undefined, css: {
|
|
99
|
+
...fieldStyles.input,
|
|
100
|
+
...(inputProps.disabled ? fieldStyles.disabled : {}),
|
|
101
|
+
...(isHovered && !inputProps.disabled && !readOnly && !isFocused ? fieldStyles.hover : {}),
|
|
102
|
+
...(multiline ? Css_1.Css.h100.p1.add("resize", "none").if(borderless).pPx(4).$ : Css_1.Css.truncate.$),
|
|
103
|
+
...xss,
|
|
104
|
+
} }, tid), void 0), isFocused && clearable && onChange && inputProps.value && ((0, jsx_runtime_1.jsx)(components_1.IconButton, { icon: "xCircle", color: Css_1.Palette.Gray700, onClick: () => {
|
|
105
|
+
var _a;
|
|
106
|
+
onChange(undefined);
|
|
107
|
+
// Reset focus to input element
|
|
108
|
+
(_a = fieldRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
109
|
+
} }, void 0)), !multiline && endAdornment && (0, jsx_runtime_1.jsx)("span", Object.assign({ css: Css_1.Css.df.aic.pl1.fs0.$ }, { children: endAdornment }), void 0)] }), void 0)),
|
|
110
|
+
}), errorMsg && !compound && (0, jsx_runtime_1.jsx)(ErrorMessage_1.ErrorMessage, Object.assign({ id: errorMessageId, errorMsg: errorMsg }, tid.errorMsg), void 0), helperText && !compound && (0, jsx_runtime_1.jsx)(HelperText_1.HelperText, Object.assign({ helperText: helperText }, tid.helperText), void 0)] }), void 0));
|
|
104
111
|
}
|
|
105
112
|
exports.TextFieldBase = TextFieldBase;
|
|
@@ -4,10 +4,10 @@ exports.ListBox = void 0;
|
|
|
4
4
|
const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const react_aria_1 = require("react-aria");
|
|
7
|
-
const ToggleChip_1 = require("../../components/ToggleChip");
|
|
8
7
|
const Css_1 = require("../../Css");
|
|
9
8
|
const constants_1 = require("./constants");
|
|
10
9
|
const ListBoxSection_1 = require("./ListBoxSection");
|
|
10
|
+
const ListBoxToggleChip_1 = require("./ListBoxToggleChip");
|
|
11
11
|
const VirtualizedOptions_1 = require("./VirtualizedOptions");
|
|
12
12
|
/** A ListBox is an internal component used by SelectField and MultiSelectField to display the list of options */
|
|
13
13
|
function ListBox(props) {
|
|
@@ -33,19 +33,12 @@ function ListBox(props) {
|
|
|
33
33
|
return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ css: {
|
|
34
34
|
...Css_1.Css.bgWhite.br4.w100.bshBasic.if(contrast).bgGray700.$,
|
|
35
35
|
"&:hover": Css_1.Css.bshHover.$,
|
|
36
|
-
}, ref: listBoxRef }, listBoxProps, { children: [isMultiSelect && state.selectionManager.selectedKeys.size > 0 && ((0, jsx_runtime_1.jsx)("ul", Object.assign({ css: Css_1.Css.listReset.pt2.pl2.pb1.pr1.df.bb.bGray200.add("flexWrap", "wrap").$ }, { children: selectedOptions.map((o) => ((0, jsx_runtime_1.jsx)(
|
|
36
|
+
}, ref: listBoxRef }, listBoxProps, { children: [isMultiSelect && state.selectionManager.selectedKeys.size > 0 && ((0, jsx_runtime_1.jsx)("ul", Object.assign({ css: Css_1.Css.listReset.pt2.pl2.pb1.pr1.df.bb.bGray200.add("flexWrap", "wrap").$ }, { children: selectedOptions.map((o) => ((0, jsx_runtime_1.jsx)(ListBoxToggleChip_1.ListBoxToggleChip, { state: state, option: o, getOptionValue: getOptionValue, getOptionLabel: getOptionLabel, disabled: state.disabledKeys.has(getOptionValue(o)) }, getOptionValue(o)))) }), void 0)), (0, jsx_runtime_1.jsx)("ul", Object.assign({ css: Css_1.Css.listReset.hPx(popoverHeight).$ }, { children: hasSections ? ([...state.collection].map((section) => ((0, jsx_runtime_1.jsx)(ListBoxSection_1.ListBoxSection, { section: section, state: state, contrast: contrast, onListHeightChange: onListHeightChange, popoverHeight: popoverHeight,
|
|
37
37
|
// Only scroll on focus if using VirtualFocus (used for ComboBoxState (SelectField), but not SelectState (ChipSelectField))
|
|
38
38
|
scrollOnFocus: props.shouldUseVirtualFocus }, section.key)))) : ((0, jsx_runtime_1.jsx)(VirtualizedOptions_1.VirtualizedOptions, { state: state, items: [...state.collection], onListHeightChange: onListHeightChange, contrast: contrast,
|
|
39
39
|
// Only scroll on focus if using VirtualFocus (used for ComboBoxState (SelectField), but not SelectState (ChipSelectField))
|
|
40
40
|
scrollOnFocus: props.shouldUseVirtualFocus }, void 0)) }), void 0)] }), void 0));
|
|
41
41
|
}
|
|
42
42
|
exports.ListBox = ListBox;
|
|
43
|
-
/** Chip used to display selections within ListBox when using the MultiSelectField */
|
|
44
|
-
function ListBoxChip(props) {
|
|
45
|
-
const { state, option, getOptionLabel, getOptionValue, disabled = false } = props;
|
|
46
|
-
return ((0, jsx_runtime_1.jsx)("li", Object.assign({ css: Css_1.Css.mr1.mb1.$ }, { children: (0, jsx_runtime_1.jsx)(ToggleChip_1.ToggleChip, { text: getOptionLabel(option), onClick: () => {
|
|
47
|
-
state.selectionManager.toggleSelection(String(getOptionValue(option)));
|
|
48
|
-
}, disabled: disabled }, void 0) }), void 0));
|
|
49
|
-
}
|
|
50
43
|
// UX specified maximum height for a ListBox (in pixels)
|
|
51
44
|
const maxPopoverHeight = 512;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ListBoxChip = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
|
|
5
|
+
const PresentationContext_1 = require("../../components/PresentationContext");
|
|
6
|
+
const Css_1 = require("../../Css");
|
|
7
|
+
function ListBoxChip({ label }) {
|
|
8
|
+
var _a;
|
|
9
|
+
const { fieldProps } = (0, PresentationContext_1.usePresentationContext)();
|
|
10
|
+
return ((0, jsx_runtime_1.jsx)("span", Object.assign({ css: Css_1.Css[(_a = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.typeScale) !== null && _a !== void 0 ? _a : "sm"].tl.bgGray300.gray900.br16.pxPx(10).pyPx(2).lineClamp1.breakAll.$, title: label }, { children: label }), void 0));
|
|
11
|
+
}
|
|
12
|
+
exports.ListBoxChip = ListBoxChip;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Key } from "react";
|
|
2
|
+
import { SelectState } from "react-stately";
|
|
3
|
+
interface ListBoxToggleChipProps<O, V extends Key> {
|
|
4
|
+
state: SelectState<O>;
|
|
5
|
+
option: O;
|
|
6
|
+
getOptionLabel: (opt: O) => string;
|
|
7
|
+
getOptionValue: (opt: O) => V;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/** Chip used to display selections within ListBox when using the MultiSelectField */
|
|
11
|
+
export declare function ListBoxToggleChip<O, V extends Key>(props: ListBoxToggleChipProps<O, V>): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ListBoxToggleChip = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
|
|
5
|
+
const components_1 = require("../../components");
|
|
6
|
+
const Css_1 = require("../../Css");
|
|
7
|
+
/** Chip used to display selections within ListBox when using the MultiSelectField */
|
|
8
|
+
function ListBoxToggleChip(props) {
|
|
9
|
+
const { state, option, getOptionLabel, getOptionValue, disabled = false } = props;
|
|
10
|
+
return ((0, jsx_runtime_1.jsx)("li", Object.assign({ css: Css_1.Css.mr1.mb1.$ }, { children: (0, jsx_runtime_1.jsx)(components_1.ToggleChip, { text: getOptionLabel(option), onClick: () => {
|
|
11
|
+
state.selectionManager.toggleSelection(String(getOptionValue(option)));
|
|
12
|
+
}, disabled: disabled }, void 0) }), void 0));
|
|
13
|
+
}
|
|
14
|
+
exports.ListBoxToggleChip = ListBoxToggleChip;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultOptionLabel = exports.defaultOptionValue = void 0;
|
|
4
|
+
const defaultOptionValue = (opt) => opt.id;
|
|
5
|
+
exports.defaultOptionValue = defaultOptionValue;
|
|
6
|
+
const defaultOptionLabel = (opt) => opt.name;
|
|
7
|
+
exports.defaultOptionLabel = defaultOptionLabel;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@homebound/beam",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.92.0",
|
|
4
4
|
"author": "Homebound",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -119,6 +119,7 @@
|
|
|
119
119
|
"react-beautiful-dnd": "^13.1.0",
|
|
120
120
|
"react-dom": "^16.14.0",
|
|
121
121
|
"semantic-release": "^17.4.0",
|
|
122
|
+
"storybook-addon-performance": "^0.16.1",
|
|
122
123
|
"ts-jest": "^26.5.3",
|
|
123
124
|
"ts-node": "^9.1.1",
|
|
124
125
|
"tslib": "^2.1.0",
|