@homebound/beam 2.334.3 → 2.335.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,21 +1,30 @@
1
1
  /// <reference types="react" />
2
2
  import { FieldState } from "@homebound/form-state";
3
3
  import { SelectFieldProps, Value } from "../inputs";
4
- import { HasIdAndName, Optional } from "../types";
4
+ import { HasIdIsh, HasNameIsh, Optional } from "../types";
5
5
  export type BoundSelectFieldProps<O, V extends Value> = Omit<SelectFieldProps<O, V>, "value" | "onSelect" | "label"> & {
6
+ /** Optional, to allow `onSelect` to be overridden to do more than just `field.set`. */
6
7
  onSelect?: (value: V | undefined, opt: O | undefined) => void;
8
+ /** The field we'll read/write data from. */
7
9
  field: FieldState<V | null | undefined>;
10
+ /** An optional label, defaults to the humanized field key, i.e. `authorId` -> `Author`. */
8
11
  label?: string;
9
12
  };
10
13
  /**
11
14
  * Wraps `SelectField` and binds it to a form field.
12
15
  *
13
- * To ease integration with "select this fooId" inputs, we can take a list
14
- * of objects, `T` (i.e. `TradePartner[]`), but accept a field of type `V`
15
- * (i.e. `string`).
16
+ * To ease integration with GraphQL inputs that want to put `{ authorId: "a:1" }` on
17
+ * the wire, we generally expect the FieldState type to be a string/tagged id, but the
18
+ * `options` prop to be the full list of id+name options like `AuthorFragment[]`.
16
19
  *
17
- * The caller has to tell us how to turn `T` into `V`, which is usually a
18
- * lambda like `t => t.id`.
20
+ * If `AuthorFragment` type matches `HasIdIsh` and `HasNameIsh`, we'll automatically use
21
+ * the `id` and `name` fields from it, otherwise callers need to provide `getOptionValue`
22
+ * and `getOptionLabel` to adapt the option, i.e. `getOptionLabel={(author) => author.otherName}`.
23
+ *
24
+ * Note: there are four overloads here to handle each combination of "HasIdIsh and HasNameId",
25
+ * "only has HasIdIsh", "only has HasNameIsh", and "neither".
19
26
  */
27
+ export declare function BoundSelectField<T extends HasIdIsh<V> & HasNameIsh, V extends Value>(props: Optional<BoundSelectFieldProps<T, V>, "getOptionLabel" | "getOptionValue">): JSX.Element;
28
+ export declare function BoundSelectField<T extends HasIdIsh<V>, V extends Value>(props: Optional<BoundSelectFieldProps<T, V>, "getOptionValue">): JSX.Element;
29
+ export declare function BoundSelectField<T extends HasNameIsh, V extends Value>(props: Optional<BoundSelectFieldProps<T, V>, "getOptionLabel">): JSX.Element;
20
30
  export declare function BoundSelectField<T, V extends Value>(props: BoundSelectFieldProps<T, V>): JSX.Element;
21
- export declare function BoundSelectField<T extends HasIdAndName<V>, V extends Value>(props: Optional<BoundSelectFieldProps<T, V>, "getOptionLabel" | "getOptionValue">): JSX.Element;
@@ -7,10 +7,9 @@ const inputs_1 = require("../inputs");
7
7
  const utils_1 = require("../utils");
8
8
  const defaultLabel_1 = require("../utils/defaultLabel");
9
9
  const useTestIds_1 = require("../utils/useTestIds");
10
+ const options_1 = require("../utils/options");
10
11
  function BoundSelectField(props) {
11
- const { field, options, readOnly, getOptionValue = (opt) => opt.id, // if unset, assume O implements HasId
12
- getOptionLabel = (opt) => opt.name, // if unset, assume O implements HasName
13
- onSelect = (value) => field.set(value), label = (0, defaultLabel_1.defaultLabel)(field.key), onBlur, onFocus, ...others } = props;
12
+ const { field, options, readOnly, getOptionValue = options_1.defaultOptionValue, getOptionLabel = options_1.defaultOptionLabel, onSelect = (value) => field.set(value), label = (0, defaultLabel_1.defaultLabel)(field.key), onBlur, onFocus, ...others } = props;
14
13
  const testId = (0, useTestIds_1.useTestIds)(props, field.key);
15
14
  return ((0, jsx_runtime_1.jsx)(mobx_react_1.Observer, { children: () => {
16
15
  var _a;
@@ -6,8 +6,13 @@ export declare const jan19: Date;
6
6
  export declare const jan29: Date;
7
7
  export declare const dd100: DeweyDecimalClassification;
8
8
  export declare const dd200: DeweyDecimalClassification;
9
+ export declare enum AuthorHeight {
10
+ SHORT = 0,
11
+ TALL = 1
12
+ }
9
13
  export interface AuthorInput {
10
14
  id?: string | null;
15
+ height?: AuthorHeight | null;
11
16
  firstName?: string | null;
12
17
  middleInitial?: string | null;
13
18
  lastName?: string | null;
@@ -3,7 +3,7 @@
3
3
  // by a GraphQL schema for a `saveAuthor` mutation that takes an author
4
4
  // plus the author's books.
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DateOnly = exports.dd200 = exports.dd100 = exports.jan29 = exports.jan19 = exports.jan10 = exports.jan2 = exports.jan1 = void 0;
6
+ exports.DateOnly = exports.AuthorHeight = exports.dd200 = exports.dd100 = exports.jan29 = exports.jan19 = exports.jan10 = exports.jan2 = exports.jan1 = void 0;
7
7
  exports.jan1 = new Date(2020, 0, 1);
8
8
  exports.jan2 = new Date(2020, 0, 2);
9
9
  exports.jan10 = new Date(2020, 0, 10);
@@ -11,6 +11,11 @@ exports.jan19 = new Date(2020, 0, 19);
11
11
  exports.jan29 = new Date(2020, 0, 29);
12
12
  exports.dd100 = { number: "100", category: "Philosophy" };
13
13
  exports.dd200 = { number: "200", category: "Religion" };
14
+ var AuthorHeight;
15
+ (function (AuthorHeight) {
16
+ AuthorHeight[AuthorHeight["SHORT"] = 0] = "SHORT";
17
+ AuthorHeight[AuthorHeight["TALL"] = 1] = "TALL";
18
+ })(AuthorHeight = exports.AuthorHeight || (exports.AuthorHeight = {}));
14
19
  class DateOnly {
15
20
  constructor(date) {
16
21
  this.date = date;
@@ -1,7 +1,7 @@
1
1
  /// <reference types="react" />
2
2
  import { Value } from "./";
3
3
  import { ComboBoxBaseProps } from "./internal/ComboBoxBase";
4
- import { HasIdAndName, Optional } from "../types";
4
+ import { HasIdIsh, HasNameIsh, Optional } from "../types";
5
5
  export interface SelectFieldProps<O, V extends Value> extends Omit<ComboBoxBaseProps<O, V>, "values" | "onSelect" | "multiselect"> {
6
6
  /** The current value; it can be `undefined`, even if `V` cannot be. */
7
7
  value: V | undefined;
@@ -18,5 +18,7 @@ export interface SelectFieldProps<O, V extends Value> extends Omit<ComboBoxBaseP
18
18
  * The `O` type is a list of options to show, the `V` is the primitive value of a
19
19
  * given `O` (i.e. it's id) that you want to use as the current/selected value.
20
20
  */
21
+ export declare function SelectField<O extends HasIdIsh<V> & HasNameIsh, V extends Value>(props: Optional<SelectFieldProps<O, V>, "getOptionValue" | "getOptionLabel">): JSX.Element;
22
+ export declare function SelectField<O extends HasIdIsh<V>, V extends Value>(props: Optional<SelectFieldProps<O, V>, "getOptionValue">): JSX.Element;
23
+ export declare function SelectField<O extends HasNameIsh, V extends Value>(props: Optional<SelectFieldProps<O, V>, "getOptionLabel">): JSX.Element;
21
24
  export declare function SelectField<O, V extends Value>(props: SelectFieldProps<O, V>): JSX.Element;
22
- export declare function SelectField<O extends HasIdAndName<V>, V extends Value>(props: Optional<SelectFieldProps<O, V>, "getOptionValue" | "getOptionLabel">): JSX.Element;
@@ -4,10 +4,9 @@ exports.SelectField = void 0;
4
4
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const ComboBoxBase_1 = require("./internal/ComboBoxBase");
7
+ const options_1 = require("../utils/options");
7
8
  function SelectField(props) {
8
- const { getOptionValue = (opt) => opt.id, // if unset, assume O implements HasId
9
- getOptionLabel = (opt) => opt.name, // if unset, assume O implements HasName
10
- options, onSelect, value, ...otherProps } = props;
9
+ const { getOptionValue = options_1.defaultOptionValue, getOptionLabel = options_1.defaultOptionLabel, options, onSelect, value, ...otherProps } = props;
11
10
  const values = (0, react_1.useMemo)(() => [value], [value]);
12
11
  return ((0, jsx_runtime_1.jsx)(ComboBoxBase_1.ComboBoxBase, { ...otherProps, options: options, getOptionLabel: getOptionLabel, getOptionValue: getOptionValue, values: values, onSelect: (values, options) => {
13
12
  // If the user used `unsetLabel`, then values will be `[undefined]` and options `[unsetOption]`
@@ -14,4 +14,4 @@ import { Key } from "react";
14
14
  */
15
15
  export type Value = string | number | null | undefined | boolean;
16
16
  export declare function keyToValue<V extends Value>(key: Key): V;
17
- export declare function valueToKey(value: Value): Key;
17
+ export declare function valueToKey(value: Value): string;
package/dist/types.d.ts CHANGED
@@ -1,6 +1,18 @@
1
1
  import React from "react";
2
2
  import { DateRange as _DateRange } from "react-day-picker";
3
3
  export type { _DateRange as DateRange };
4
+ export type HasIdIsh<V = string> = {
5
+ id: V;
6
+ } | {
7
+ code: V;
8
+ };
9
+ export type HasNameIsh = {
10
+ name: string;
11
+ } | {
12
+ displayName: string;
13
+ } | {
14
+ label: string;
15
+ };
4
16
  export type HasIdAndName<V = string> = {
5
17
  id: V;
6
18
  name: string;
@@ -1,5 +1,6 @@
1
1
  import { MutableRefObject } from "react";
2
2
  import type { CheckboxGroupState, ToggleState } from "react-stately";
3
+ export declare function fail(message?: string): never;
3
4
  /** Adapts our state to what useToggleState returns in a stateless manner. */
4
5
  export declare function toToggleState(isSelected: boolean, onChange: (value: boolean) => void): ToggleState;
5
6
  /** Adapts our state to what use*Group returns in a stateless manner. */
@@ -17,7 +18,7 @@ export * from "./useTestIds";
17
18
  /** Casts `Object.keys` to "what it should be", as long as your instance doesn't have keys it shouldn't. */
18
19
  export declare function safeKeys<T>(instance: T): (keyof T)[];
19
20
  export declare const omitKey: <T, K extends keyof T>(key: K, { [key]: _, ...obj }: T) => T;
20
- export declare const noop: () => void;
21
+ export declare const noop: (...args: any) => void;
21
22
  type Entries<T> = {
22
23
  [K in keyof T]: [K, T[K]];
23
24
  }[keyof T][];
@@ -14,7 +14,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.pluralize = exports.isDefined = exports.isFunction = exports.isPromise = exports.areArraysEqual = exports.isAbsoluteUrl = exports.EmptyRef = exports.safeEntries = exports.noop = exports.omitKey = exports.safeKeys = exports.maybeCall = exports.toGroupState = exports.toToggleState = void 0;
17
+ exports.pluralize = exports.isDefined = exports.isFunction = exports.isPromise = exports.areArraysEqual = exports.isAbsoluteUrl = exports.EmptyRef = exports.safeEntries = exports.noop = exports.omitKey = exports.safeKeys = exports.maybeCall = exports.toGroupState = exports.toToggleState = exports.fail = void 0;
18
+ function fail(message) {
19
+ throw new Error(message || "Failed");
20
+ }
21
+ exports.fail = fail;
18
22
  /** Adapts our state to what useToggleState returns in a stateless manner. */
19
23
  function toToggleState(isSelected, onChange) {
20
24
  return {
@@ -64,7 +68,7 @@ exports.safeKeys = safeKeys;
64
68
  // Returns object with specified key removed
65
69
  const omitKey = (key, { [key]: _, ...obj }) => obj;
66
70
  exports.omitKey = omitKey;
67
- const noop = () => { };
71
+ const noop = (...args) => { };
68
72
  exports.noop = noop;
69
73
  function safeEntries(obj) {
70
74
  return Object.entries(obj);
@@ -1,2 +1,2 @@
1
- export declare const defaultOptionValue: <O>(opt: O) => any;
2
- export declare const defaultOptionLabel: <O>(opt: O) => any;
1
+ export declare function defaultOptionValue<O>(opt: O): any;
2
+ export declare function defaultOptionLabel<O>(opt: O): any;
@@ -1,7 +1,25 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.defaultOptionLabel = exports.defaultOptionValue = void 0;
4
- const defaultOptionValue = (opt) => opt.id;
4
+ const utils_1 = require("./");
5
+ // This `any` is currently on purpose to ignore type errors in ChipSelectField
6
+ function defaultOptionValue(opt) {
7
+ if (typeof opt !== "object" || !opt)
8
+ (0, utils_1.fail)(`Option ${opt} has no id or code`);
9
+ // Use `in` because returning undefined is fine
10
+ return "id" in opt ? opt.id : "code" in opt ? opt.code : (0, utils_1.fail)(`Option ${JSON.stringify(opt)} has no id or code`);
11
+ }
5
12
  exports.defaultOptionValue = defaultOptionValue;
6
- const defaultOptionLabel = (opt) => opt.name;
13
+ function defaultOptionLabel(opt) {
14
+ if (typeof opt !== "object" || !opt)
15
+ (0, utils_1.fail)(`Option ${opt} has no id or code`);
16
+ // Use `in` because returning undefined is fine
17
+ return "name" in opt
18
+ ? opt.name
19
+ : "displayName" in opt
20
+ ? opt.displayName
21
+ : "label" in opt
22
+ ? opt.label
23
+ : (0, utils_1.fail)(`Option ${JSON.stringify(opt)} has no displayName, label, or name`);
24
+ }
7
25
  exports.defaultOptionLabel = defaultOptionLabel;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.334.3",
3
+ "version": "2.335.1",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",