@ai-matrx/records-ui 0.106.0 → 0.107.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.
package/dist/pickers.cjs CHANGED
@@ -3036,7 +3036,8 @@ function formatControl(args) {
3036
3036
  {
3037
3037
  id,
3038
3038
  type: def.editor,
3039
- ...ownDetails && def.editor !== "url" ? { autoComplete: def.editor === "email" ? "email" : "tel" } : {},
3039
+ inputMode: def.editor,
3040
+ ...ownDetails ? { autoComplete: def.editor } : {},
3040
3041
  value: text,
3041
3042
  disabled,
3042
3043
  onChange: (e) => commit(e.target.value)
@@ -3491,7 +3492,7 @@ function isPersonsName(field) {
3491
3492
  const words = `${field.key} ${field.label ?? ""}`.toLowerCase();
3492
3493
  return /(^|[\s_])(full[\s_]?)?name(\s|$)/.test(words) && !/(therapist|doctor|physician|company|business|pet|room)/.test(words);
3493
3494
  }
3494
- function FieldControl({ field, value, onChange, disabled, id, autoOpen, onClose, onCommit, onCancel, addsChoices, initialSearch, asForm }) {
3495
+ function FieldControl({ field, value, onChange, disabled, id, autoOpen, onClose, onCommit, onCancel, addsChoices, initialSearch, asForm, onChosen }) {
3495
3496
  const host = useRecordsUi();
3496
3497
  const kind = editorKindFor(field);
3497
3498
  const inputId = id ?? `field-${field.key}`;
@@ -3555,7 +3556,8 @@ function FieldControl({ field, value, onChange, disabled, id, autoOpen, onClose,
3555
3556
  {
3556
3557
  id: inputId,
3557
3558
  type: kind === "email" ? "email" : kind === "phone" ? "tel" : "url",
3558
- ...ownDetails && kind !== "url" ? { autoComplete: kind === "email" ? "email" : "tel" } : {},
3559
+ inputMode: kind === "email" ? "email" : kind === "phone" ? "tel" : "url",
3560
+ ...ownDetails ? { autoComplete: kind === "email" ? "email" : kind === "phone" ? "tel" : "url" } : {},
3559
3561
  value: value === null || value === void 0 ? "" : String(value),
3560
3562
  disabled,
3561
3563
  onChange: (e) => onChange(e.target.value === "" ? null : e.target.value)
@@ -3565,7 +3567,7 @@ function FieldControl({ field, value, onChange, disabled, id, autoOpen, onClose,
3565
3567
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(CheckboxControl, { field, value, onChange, disabled, id: inputId });
3566
3568
  case "select":
3567
3569
  case "multi_select":
3568
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(OptionControl, { field, value, onChange, disabled, id: inputId, autoOpen, onClose, onCancel, addsChoices, initialSearch, asForm });
3570
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(OptionControl, { field, value, onChange, disabled, id: inputId, autoOpen, onClose, onCancel, addsChoices, initialSearch, asForm, onChosen });
3569
3571
  case "member":
3570
3572
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(PersonPicker, { field, value, onChange, disabled, id: inputId, autoOpen, onClose, onCancel, initialSearch });
3571
3573
  case "entity_reference":
@@ -3747,7 +3749,7 @@ function inTheStoresOrder(options) {
3747
3749
  const made = (o) => String(o.created_at ?? "");
3748
3750
  return [...options].sort((a, b) => position(a) - position(b) || made(a).localeCompare(made(b)));
3749
3751
  }
3750
- function OptionControl({ field, value, onChange, disabled, id, autoOpen, onClose, onCancel, addsChoices, initialSearch, asForm }) {
3752
+ function OptionControl({ field, value, onChange, disabled, id, autoOpen, onClose, onCancel, addsChoices, initialSearch, asForm, onChosen }) {
3751
3753
  const client = (0, import_react26.useOptionalRecordsClient)();
3752
3754
  const [options, setOptions] = (0, import_react25.useState)(null);
3753
3755
  const [refusal2, setRefusal] = (0, import_react25.useState)(null);
@@ -3766,7 +3768,7 @@ function OptionControl({ field, value, onChange, disabled, id, autoOpen, onClose
3766
3768
  }, [client, field.id, reread]);
3767
3769
  const handed = publicChoicesOf(field);
3768
3770
  if (!client && handed.length > 0) {
3769
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ChoiceAnswer, { field, choices: handed, value, onChange, disabled, id });
3771
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ChoiceAnswer, { field, choices: handed, value, onChange, disabled, id, onChosen });
3770
3772
  }
3771
3773
  if (!client) {
3772
3774
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex flex-col gap-1", children: [
@@ -3796,6 +3798,7 @@ function OptionControl({ field, value, onChange, disabled, id, autoOpen, onClose
3796
3798
  onChange,
3797
3799
  disabled,
3798
3800
  id,
3801
+ onChosen,
3799
3802
  isChosen: (choice, v) => {
3800
3803
  const option = options.find((o) => (0, import_records10.optionKey)(o) === choice.key);
3801
3804
  return option ? (0, import_records10.isTheChosen)(option, v) : false;
@@ -4066,20 +4069,24 @@ function ChoiceAnswer({
4066
4069
  onChange,
4067
4070
  disabled,
4068
4071
  id,
4069
- isChosen
4072
+ isChosen,
4073
+ onChosen
4070
4074
  }) {
4071
4075
  const [search, setSearch] = (0, import_react25.useState)("");
4072
4076
  const held = field.multi ? (0, import_records10.choiceValuesOf)(value) : value === null || value === void 0 || value === "" ? [] : [value];
4073
4077
  const on = (choice) => held.some((v) => isChosen ? isChosen(choice, v) : String(v) === choice.key || String(v) === choice.label);
4074
4078
  const press = (choice) => {
4075
4079
  if (!field.multi) {
4076
- onChange(on(choice) ? null : choice.key);
4080
+ const picking = !on(choice);
4081
+ onChange(picking ? choice.key : null);
4082
+ if (picking) onChosen?.();
4077
4083
  return;
4078
4084
  }
4079
4085
  const keys = choices.filter((c) => c.key === choice.key ? !on(c) : on(c)).map((c) => c.key);
4080
4086
  onChange(keys.length === 0 ? null : keys);
4081
4087
  };
4082
4088
  const lettered = choices.length <= CHOICE_LETTERS.length;
4089
+ const tabStop = choices.find((c) => on(c))?.key ?? choices[0]?.key;
4083
4090
  const option = (choice) => {
4084
4091
  const chosen = on(choice);
4085
4092
  const letter = lettered ? CHOICE_LETTERS[choices.indexOf(choice)] : null;
@@ -4091,6 +4098,7 @@ function ChoiceAnswer({
4091
4098
  "aria-checked": chosen,
4092
4099
  "aria-label": choice.label,
4093
4100
  disabled,
4101
+ tabIndex: field.multi || choice.key === tabStop ? 0 : -1,
4094
4102
  onClick: () => press(choice),
4095
4103
  "data-records-choice-answer": choice.key,
4096
4104
  className: (0, import_design_system15.cn)(
@@ -4117,8 +4125,25 @@ function ChoiceAnswer({
4117
4125
  );
4118
4126
  };
4119
4127
  const onKeyDown = (event) => {
4120
- if (!lettered || disabled || event.metaKey || event.ctrlKey || event.altKey) return;
4128
+ if (disabled || event.metaKey || event.ctrlKey || event.altKey) return;
4121
4129
  if (event.target.tagName === "INPUT") return;
4130
+ const arrow = { ArrowDown: 1, ArrowRight: 1, ArrowUp: -1, ArrowLeft: -1 }[event.key];
4131
+ if (arrow) {
4132
+ const buttons = Array.from(
4133
+ event.currentTarget.querySelectorAll("[data-records-choice-answer]")
4134
+ );
4135
+ const here = buttons.indexOf(event.target);
4136
+ if (buttons.length === 0) return;
4137
+ event.preventDefault();
4138
+ const next = buttons[(Math.max(here, 0) + arrow + buttons.length) % buttons.length];
4139
+ next.focus();
4140
+ if (!field.multi) {
4141
+ const choice = choices.find((c) => c.key === next.dataset["recordsChoiceAnswer"]);
4142
+ if (choice && !on(choice)) onChange(choice.key);
4143
+ }
4144
+ return;
4145
+ }
4146
+ if (!lettered) return;
4122
4147
  const at = CHOICE_LETTERS.indexOf(event.key.toUpperCase());
4123
4148
  if (event.key.length !== 1 || at < 0 || at >= choices.length) return;
4124
4149
  event.preventDefault();