@flytedan/flytebot-design-system 0.35.0 → 0.36.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/index.cjs CHANGED
@@ -3728,14 +3728,9 @@ function MultiSelectPanel({
3728
3728
  const [unmatchedTokens, setUnmatchedTokens] = React25.useState([]);
3729
3729
  const [pasteError, setPasteError] = React25.useState(null);
3730
3730
  const pasteWrapRef = React25.useRef(null);
3731
- const [resolvedAt, setResolvedAt] = React25.useState(0);
3732
3731
  React25.useEffect(() => {
3733
3732
  if (mode2 === "paste") pasteWrapRef.current?.querySelector("textarea")?.focus();
3734
3733
  }, [mode2]);
3735
- React25.useLayoutEffect(() => {
3736
- if (resolvedAt === 0) return;
3737
- pasteWrapRef.current?.querySelector("textarea")?.focus();
3738
- }, [resolvedAt]);
3739
3734
  const doResolve = () => {
3740
3735
  if (!field.resolve) return;
3741
3736
  const tokens = Array.from(new Set(pasteText.split(/[\n,]/).map((t) => t.trim()).filter(Boolean)));
@@ -3758,7 +3753,6 @@ function MultiSelectPanel({
3758
3753
  return;
3759
3754
  }
3760
3755
  setPasteText("");
3761
- setResolvedAt((n) => n + 1);
3762
3756
  }, (err) => {
3763
3757
  if (!mountedRef.current) return;
3764
3758
  setPasteLoading(false);
@@ -3877,7 +3871,28 @@ function MultiSelectPanel({
3877
3871
  );
3878
3872
  }) }) : null
3879
3873
  ] });
3880
- const footer = mode2 === "paste" ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Button, { size: "sm", variant: "secondary", onClick: doResolve, disabled: pasteLoading || !pasteText.trim(), children: pasteLoading ? "Resolving\u2026" : "Resolve" }) : void 0;
3874
+ const resolveDisabled = pasteLoading || !pasteText.trim();
3875
+ const footer = mode2 === "paste" ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3876
+ Button,
3877
+ {
3878
+ size: "sm",
3879
+ variant: "secondary",
3880
+ "aria-disabled": resolveDisabled,
3881
+ onClick: (e) => {
3882
+ if (resolveDisabled) {
3883
+ e.preventDefault();
3884
+ return;
3885
+ }
3886
+ doResolve();
3887
+ },
3888
+ onKeyDown: (e) => {
3889
+ if (resolveDisabled && (e.key === "Enter" || e.key === " ")) {
3890
+ e.preventDefault();
3891
+ }
3892
+ },
3893
+ children: pasteLoading ? "Resolving\u2026" : "Resolve"
3894
+ }
3895
+ ) : void 0;
3881
3896
  return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3882
3897
  Popover,
3883
3898
  {
@@ -3946,17 +3961,25 @@ function useReseedFromProps(value, applies, reseed) {
3946
3961
  if (!sameValue(value, applies())) reseed(value);
3947
3962
  }, [value, applies, reseed]);
3948
3963
  }
3949
- function usePreserveFocusAcrossRemount(seed) {
3950
- const pendingId = React25.useRef(null);
3951
- const capture = (ids) => {
3964
+ function usePreserveFocusAcrossRemount(seed, fields) {
3965
+ const pendingName = React25.useRef(null);
3966
+ const fieldsRef = useLatest(fields);
3967
+ const capture = () => {
3952
3968
  const active = document.activeElement;
3953
- pendingId.current = active instanceof HTMLElement && ids.includes(active.id) ? active.id : null;
3969
+ pendingName.current = null;
3970
+ if (!(active instanceof HTMLElement)) return;
3971
+ for (const [name, ref] of Object.entries(fieldsRef.current)) {
3972
+ if (ref.current?.contains(active)) {
3973
+ pendingName.current = name;
3974
+ break;
3975
+ }
3976
+ }
3954
3977
  };
3955
3978
  React25.useLayoutEffect(() => {
3956
- const id = pendingId.current;
3957
- if (!id) return;
3958
- pendingId.current = null;
3959
- document.getElementById(id)?.focus();
3979
+ const name = pendingName.current;
3980
+ if (!name) return;
3981
+ pendingName.current = null;
3982
+ fieldsRef.current[name]?.current?.querySelector("input,textarea,select,button")?.focus();
3960
3983
  }, [seed]);
3961
3984
  return capture;
3962
3985
  }
@@ -3970,9 +3993,11 @@ function RangePanel({
3970
3993
  }) {
3971
3994
  const [draft, setDraft] = React25.useState(() => rangeDraft(value));
3972
3995
  const [seed, setSeed] = React25.useState(0);
3973
- const preserveFocus = usePreserveFocusAcrossRemount(seed);
3974
- const minId = field.key + "-min";
3975
- const maxId = field.key + "-max";
3996
+ const minId = React25.useId();
3997
+ const maxId = React25.useId();
3998
+ const minWrapRef = React25.useRef(null);
3999
+ const maxWrapRef = React25.useRef(null);
4000
+ const preserveFocus = usePreserveFocusAcrossRemount(seed, { min: minWrapRef, max: maxWrapRef });
3976
4001
  const draftRef = React25.useRef(draft);
3977
4002
  const shown = () => {
3978
4003
  const { min, max } = draftRef.current;
@@ -3983,7 +4008,7 @@ function RangePanel({
3983
4008
  };
3984
4009
  const validity = useTextValidity(publish);
3985
4010
  useReseedFromProps(value, shown, (next) => {
3986
- preserveFocus([minId, maxId]);
4011
+ preserveFocus();
3987
4012
  draftRef.current = rangeDraft(next);
3988
4013
  setDraft(draftRef.current);
3989
4014
  validity.reset();
@@ -4013,7 +4038,7 @@ function RangePanel({
4013
4038
  label: field.label,
4014
4039
  footer: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Button, { size: "sm", variant: "secondary", onClick: onClose, disabled: doneDisabled, children: "Done" }),
4015
4040
  children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-stack fd-gap-sm", children: [
4016
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
4041
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { ref: minWrapRef, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
4017
4042
  NumberInput,
4018
4043
  {
4019
4044
  id: minId,
@@ -4028,8 +4053,8 @@ function RangePanel({
4028
4053
  onValidityChange: validity.report("min")
4029
4054
  },
4030
4055
  "min-" + seed
4031
- ),
4032
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
4056
+ ) }),
4057
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { ref: maxWrapRef, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
4033
4058
  NumberInput,
4034
4059
  {
4035
4060
  id: maxId,
@@ -4045,7 +4070,7 @@ function RangePanel({
4045
4070
  onValidityChange: validity.report("max")
4046
4071
  },
4047
4072
  "max-" + seed
4048
- )
4073
+ ) })
4049
4074
  ] })
4050
4075
  }
4051
4076
  );
@@ -4072,8 +4097,9 @@ function DatePanel({
4072
4097
  const daysConfirmed = React25.useRef(value?.kind === "withinDays");
4073
4098
  const [between, setBetween] = React25.useState(initial.between);
4074
4099
  const [seed, setSeed] = React25.useState(0);
4075
- const preserveFocus = usePreserveFocusAcrossRemount(seed);
4076
- const daysId = field.key + "-days";
4100
+ const daysId = React25.useId();
4101
+ const daysWrapRef = React25.useRef(null);
4102
+ const preserveFocus = usePreserveFocusAcrossRemount(seed, { days: daysWrapRef });
4077
4103
  const shownWithinDays = () => {
4078
4104
  const days = daysRef.current;
4079
4105
  return applicable(field, days == null ? void 0 : { kind: "withinDays", days }, validity.allValid());
@@ -4089,7 +4115,7 @@ function DatePanel({
4089
4115
  return daysConfirmed.current ? shownWithinDays() : void 0;
4090
4116
  };
4091
4117
  useReseedFromProps(value, applies, (next) => {
4092
- preserveFocus([daysId]);
4118
+ preserveFocus();
4093
4119
  const d = dateDraft(field, next);
4094
4120
  setKind(d.kind);
4095
4121
  daysRef.current = d.days;
@@ -4156,7 +4182,7 @@ function DatePanel({
4156
4182
  onChange: (k) => switchKind(k)
4157
4183
  }
4158
4184
  ),
4159
- kind === "withinDays" ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
4185
+ kind === "withinDays" ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { ref: daysWrapRef, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
4160
4186
  NumberInput,
4161
4187
  {
4162
4188
  id: daysId,
@@ -4170,7 +4196,7 @@ function DatePanel({
4170
4196
  onValidityChange: validity.report("days")
4171
4197
  },
4172
4198
  "days-" + seed
4173
- ) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
4199
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
4174
4200
  DatePicker,
4175
4201
  {
4176
4202
  range: true,