@homebound/beam 2.91.7 → 2.91.8
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/Icon.d.ts +2 -2
- package/dist/components/Icon.js +6 -3
- package/dist/components/Label.d.ts +2 -2
- package/dist/components/Label.js +6 -3
- package/dist/inputs/ChipSelectField.js +36 -14
- 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
|
@@ -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
|
*
|
|
@@ -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));
|
|
@@ -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,17 +152,15 @@ 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
|
-
const field = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [showInput && onCreateNew && ((0, jsx_runtime_1.jsx)(
|
|
146
|
-
await onCreateNew(
|
|
159
|
+
}, [setShowInput]);
|
|
160
|
+
const field = ((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
|
-
}
|
|
163
|
+
} }, tid.createNewField), void 0)), (0, jsx_runtime_1.jsxs)("div", Object.assign({ ref: wrapperRef, css: {
|
|
149
164
|
...chipStyles,
|
|
150
165
|
...Css_1.Css.dif.relative.p0.mwPx(32).if(!value).bgGray200.$,
|
|
151
166
|
...(visualFocus ? Css_1.Css.bshFocus.$ : {}),
|
|
@@ -184,3 +199,10 @@ function isListBoxSection(obj) {
|
|
|
184
199
|
return typeof obj === "object" && "options" in obj;
|
|
185
200
|
}
|
|
186
201
|
exports.isListBoxSection = isListBoxSection;
|
|
202
|
+
// Wrapper for the ChipTextField used in the "Create New" flow on ChipSelectField
|
|
203
|
+
function CreateNewField(props) {
|
|
204
|
+
const { onBlur, onEnter } = props;
|
|
205
|
+
const [value, setValue] = (0, react_1.useState)("Add new");
|
|
206
|
+
const tid = (0, utils_1.useTestIds)(props);
|
|
207
|
+
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));
|
|
208
|
+
}
|
|
@@ -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.91.
|
|
3
|
+
"version": "2.91.8",
|
|
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",
|