@homebound/beam 2.309.0 → 2.309.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,9 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.useComputed = void 0;
7
- const fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
8
4
  const mobx_1 = require("mobx");
9
5
  const react_1 = require("react");
6
+ const shallowEqual_1 = require("../utils/shallowEqual");
10
7
  /** Evaluates a computed function `fn` to a regular value and triggers a re-render whenever it changes. */
11
8
  function useComputed(fn, deps) {
12
9
  // We always return the useRef value, and use this just to trigger re-renders
@@ -37,7 +34,11 @@ function useComputed(fn, deps) {
37
34
  // Only trigger a re-render if this is not the 1st autorun. Note
38
35
  // that if deps has changed, we're inherently in a re-render so also
39
36
  // don't need to trigger an additional re-render.
40
- if (oldHasRun && !(0, fast_deep_equal_1.default)(newValue, oldValue)) {
37
+ //
38
+ // Also, we avoid a deep equality, b/c if a `useComputed` is returning something
39
+ // complicated/cyclic, like ReactElement, deep equality will crawl into the guts
40
+ // of React/ReactFiber and cycle/infinite loop.
41
+ if (oldHasRun && !(0, shallowEqual_1.shallowEqual)(newValue, oldValue)) {
41
42
  setTick((tick) => tick + 1);
42
43
  }
43
44
  });
@@ -32,8 +32,11 @@ export declare function rowAnd(r: RenderResult, rowNum: number, testId: string):
32
32
  export declare function tableSnapshot(r: RenderResult): string;
33
33
  /** RTL wrapper for Beam's SuperDrawer/Modal context. */
34
34
  export declare const withBeamRTL: Wrapper;
35
- /** Selects an option from the Beam SelectField, MultiSelectField, and TreeSelectField components
35
+ /**
36
+ * Selects an option from the Beam SelectField, MultiSelectField, and TreeSelectField components.
37
+ *
36
38
  * For select fields that support multiple selections, subsequent calls to this function will toggle the selection state of an option.
39
+ *
37
40
  * @param value The value or label of the option.
38
41
  * */
39
42
  export declare function select(element: HTMLElement, value: string | string[]): void;
package/dist/utils/rtl.js CHANGED
@@ -135,44 +135,50 @@ function getTextFromTableCellNode(node) {
135
135
  exports.withBeamRTL = {
136
136
  wrap: (c) => (0, jsx_runtime_1.jsx)(components_1.BeamProvider, { children: c }),
137
137
  };
138
- /** Selects an option from the Beam SelectField, MultiSelectField, and TreeSelectField components
138
+ /**
139
+ * Selects an option from the Beam SelectField, MultiSelectField, and TreeSelectField components.
140
+ *
139
141
  * For select fields that support multiple selections, subsequent calls to this function will toggle the selection state of an option.
142
+ *
140
143
  * @param value The value or label of the option.
141
144
  * */
142
145
  function select(element, value) {
143
146
  const select = resolveIfNeeded(element);
144
- if (isSelectElement(select)) {
145
- throw new Error("Beam select helper does not support <select> elements.");
146
- }
147
- if (!isInputElement(select)) {
148
- throw new Error(`Expected element to be INPUT, but got ${select.nodeName}. This field may be read-only.`);
149
- }
150
- function maybeOpenAndSelect(optionValue) {
151
- const expanded = select.getAttribute("aria-expanded") === "true";
152
- if (!expanded) {
153
- (0, rtl_utils_1.click)(select);
154
- }
155
- const body = select.closest("body");
156
- const listboxId = select.getAttribute("aria-controls");
157
- const listbox = body.querySelector(`#${listboxId}`);
158
- const options = listbox.querySelectorAll("[role=option]");
159
- // Allow searching for options by their data-key (value) or textContent (label)
160
- const optionToSelect = Array.from(options).find((o) => o.dataset.key === optionValue || o.dataset.label === optionValue);
161
- if (!optionToSelect) {
162
- throw new Error(`Could not find option with value or text content of ${optionValue}`);
163
- }
164
- (0, rtl_utils_1.click)(optionToSelect);
165
- }
147
+ assertListBoxInput(select);
148
+ ensureListBoxOpen(select);
166
149
  const optionValues = Array.isArray(value) ? value : [value];
167
- optionValues.forEach((optionValue) => {
168
- maybeOpenAndSelect(optionValue);
169
- });
150
+ optionValues.forEach((optionValue) => selectOption(select, optionValue));
170
151
  }
171
152
  exports.select = select;
172
- function selectAndWait(input, value) {
173
- return (0, rtl_utils_1.allowAndWaitForAsyncBehavior)(() => select(input, value));
153
+ async function selectAndWait(input, value) {
154
+ const select = resolveIfNeeded(input);
155
+ // To work with React 18, we need to execute these as separate steps, otherwise
156
+ // the `ensureListBoxOpen` async render won't flush, and the `selectOption` will fail.
157
+ await (0, rtl_utils_1.allowAndWaitForAsyncBehavior)(() => ensureListBoxOpen(select));
158
+ return (0, rtl_utils_1.allowAndWaitForAsyncBehavior)(() => {
159
+ const optionValues = Array.isArray(value) ? value : [value];
160
+ optionValues.forEach((optionValue) => selectOption(select, optionValue));
161
+ });
174
162
  }
175
163
  exports.selectAndWait = selectAndWait;
164
+ function ensureListBoxOpen(select) {
165
+ const expanded = select.getAttribute("aria-expanded") === "true";
166
+ if (!expanded) {
167
+ (0, rtl_utils_1.click)(select);
168
+ }
169
+ }
170
+ function selectOption(select, optionValue) {
171
+ const body = select.closest("body");
172
+ const listboxId = select.getAttribute("aria-controls");
173
+ const listbox = body.querySelector(`#${listboxId}`);
174
+ const options = listbox.querySelectorAll("[role=option]");
175
+ // Allow searching for options by their data-key (value) or textContent (label)
176
+ const optionToSelect = Array.from(options).find((o) => o.dataset.key === optionValue || o.dataset.label === optionValue);
177
+ if (!optionToSelect) {
178
+ throw new Error(`Could not find option with value or text content of ${optionValue}`);
179
+ }
180
+ (0, rtl_utils_1.click)(optionToSelect);
181
+ }
176
182
  function getSelected(element) {
177
183
  var _a;
178
184
  const select = resolveIfNeeded(element);
@@ -183,10 +189,7 @@ function getSelected(element) {
183
189
  // For read-only fields that render as a 'div'
184
190
  return (_a = select.textContent) !== null && _a !== void 0 ? _a : undefined;
185
191
  }
186
- const expanded = select.getAttribute("aria-expanded") === "true";
187
- if (!expanded) {
188
- (0, rtl_utils_1.click)(select);
189
- }
192
+ ensureListBoxOpen(select);
190
193
  const body = select.closest("body");
191
194
  const listboxId = select.getAttribute("aria-controls");
192
195
  const listbox = body.querySelector(`#${listboxId}`);
@@ -201,16 +204,8 @@ function getSelected(element) {
201
204
  exports.getSelected = getSelected;
202
205
  function getOptions(element) {
203
206
  const select = resolveIfNeeded(element);
204
- if (isSelectElement(select)) {
205
- throw new Error("Beam getOptions helper does not support <select> elements");
206
- }
207
- if (!isInputElement(select)) {
208
- throw new Error(`Expected element to be INPUT, but got ${select.nodeName}. This field may be read-only. In that case we cannot get the list of options`);
209
- }
210
- const expanded = select.getAttribute("aria-expanded") === "true";
211
- if (!expanded) {
212
- (0, rtl_utils_1.click)(select);
213
- }
207
+ assertListBoxInput(select);
208
+ ensureListBoxOpen(select);
214
209
  const body = select.closest("body");
215
210
  const listboxId = select.getAttribute("aria-controls");
216
211
  const listbox = body.querySelector(`#${listboxId}`);
@@ -220,6 +215,15 @@ function getOptions(element) {
220
215
  .filter((o) => !!o);
221
216
  }
222
217
  exports.getOptions = getOptions;
218
+ function assertListBoxInput(select) {
219
+ if (isSelectElement(select)) {
220
+ throw new Error("Beam getOptions helper does not support <select> elements");
221
+ }
222
+ if (!isInputElement(select)) {
223
+ throw new Error(`Expected element to be INPUT, but got ${select.nodeName}. This field may be read-only. In that case we cannot get the list of options`);
224
+ }
225
+ return true;
226
+ }
223
227
  function resolveIfNeeded(element) {
224
228
  const maybeProxy = element;
225
229
  return maybeProxy instanceof Function ? maybeProxy() : element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.309.0",
3
+ "version": "2.309.2",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -76,21 +76,21 @@
76
76
  "@emotion/react": "^11.10.6",
77
77
  "@homebound/eslint-config": "1.6.1",
78
78
  "@homebound/rtl-react-router-utils": "1.0.3",
79
- "@homebound/rtl-utils": "^2.61.1",
79
+ "@homebound/rtl-utils": "^2.63.1",
80
80
  "@homebound/truss": "^1.129.0",
81
81
  "@homebound/tsconfig": "^1.0.3",
82
82
  "@semantic-release/exec": "^6.0.3",
83
83
  "@semantic-release/git": "^10.0.1",
84
- "@storybook/addon-docs": "^7.0.26",
85
- "@storybook/addon-essentials": "^7.0.26",
86
- "@storybook/addon-interactions": "^7.0.26",
87
- "@storybook/addon-links": "^7.0.26",
88
- "@storybook/addon-mdx-gfm": "^7.0.26",
89
- "@storybook/addons": "^7.0.26",
90
- "@storybook/manager-api": "^7.0.26",
91
- "@storybook/mdx2-csf": "1.1.0",
92
- "@storybook/react": "^7.0.26",
93
- "@storybook/react-vite": "^7.0.26",
84
+ "@storybook/addon-docs": "^7.3.0",
85
+ "@storybook/addon-essentials": "^7.3.0",
86
+ "@storybook/addon-interactions": "^7.3.0",
87
+ "@storybook/addon-links": "^7.3.0",
88
+ "@storybook/addon-mdx-gfm": "^7.3.0",
89
+ "@storybook/addons": "^7.3.0",
90
+ "@storybook/manager-api": "^7.3.0",
91
+ "@storybook/mdx2-csf": "^1.1.0",
92
+ "@storybook/react": "^7.3.0",
93
+ "@storybook/react-vite": "^7.3.0",
94
94
  "@storybook/testing-library": "^0.2.0",
95
95
  "@testing-library/jest-dom": "^5.16.5",
96
96
  "@tsconfig/recommended": "^1.0.2",
@@ -107,7 +107,7 @@
107
107
  "chromatic": "^6.17.0",
108
108
  "conventional-changelog-conventionalcommits": "^5.0.0",
109
109
  "eslint": "^8.12.0",
110
- "eslint-plugin-storybook": "^0.6.12",
110
+ "eslint-plugin-storybook": "^0.6.13",
111
111
  "husky": "^5.1.1",
112
112
  "identity-obj-proxy": "^3.0.0",
113
113
  "jest": "^29.4.3",
@@ -121,7 +121,7 @@
121
121
  "react": "^18.2.0",
122
122
  "react-dom": "^18.2.0",
123
123
  "semantic-release": "^20.1.0",
124
- "storybook": "^7.0.26",
124
+ "storybook": "^7.3.0",
125
125
  "storybook-addon-designs": "beta",
126
126
  "ts-jest": "^29.0.5",
127
127
  "ts-node": "^10.9.1",