@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.js CHANGED
@@ -3488,14 +3488,9 @@ function MultiSelectPanel({
3488
3488
  const [unmatchedTokens, setUnmatchedTokens] = React25.useState([]);
3489
3489
  const [pasteError, setPasteError] = React25.useState(null);
3490
3490
  const pasteWrapRef = React25.useRef(null);
3491
- const [resolvedAt, setResolvedAt] = React25.useState(0);
3492
3491
  React25.useEffect(() => {
3493
3492
  if (mode2 === "paste") pasteWrapRef.current?.querySelector("textarea")?.focus();
3494
3493
  }, [mode2]);
3495
- React25.useLayoutEffect(() => {
3496
- if (resolvedAt === 0) return;
3497
- pasteWrapRef.current?.querySelector("textarea")?.focus();
3498
- }, [resolvedAt]);
3499
3494
  const doResolve = () => {
3500
3495
  if (!field.resolve) return;
3501
3496
  const tokens = Array.from(new Set(pasteText.split(/[\n,]/).map((t) => t.trim()).filter(Boolean)));
@@ -3518,7 +3513,6 @@ function MultiSelectPanel({
3518
3513
  return;
3519
3514
  }
3520
3515
  setPasteText("");
3521
- setResolvedAt((n) => n + 1);
3522
3516
  }, (err) => {
3523
3517
  if (!mountedRef.current) return;
3524
3518
  setPasteLoading(false);
@@ -3637,7 +3631,28 @@ function MultiSelectPanel({
3637
3631
  );
3638
3632
  }) }) : null
3639
3633
  ] });
3640
- const footer = mode2 === "paste" ? /* @__PURE__ */ jsx45(Button, { size: "sm", variant: "secondary", onClick: doResolve, disabled: pasteLoading || !pasteText.trim(), children: pasteLoading ? "Resolving\u2026" : "Resolve" }) : void 0;
3634
+ const resolveDisabled = pasteLoading || !pasteText.trim();
3635
+ const footer = mode2 === "paste" ? /* @__PURE__ */ jsx45(
3636
+ Button,
3637
+ {
3638
+ size: "sm",
3639
+ variant: "secondary",
3640
+ "aria-disabled": resolveDisabled,
3641
+ onClick: (e) => {
3642
+ if (resolveDisabled) {
3643
+ e.preventDefault();
3644
+ return;
3645
+ }
3646
+ doResolve();
3647
+ },
3648
+ onKeyDown: (e) => {
3649
+ if (resolveDisabled && (e.key === "Enter" || e.key === " ")) {
3650
+ e.preventDefault();
3651
+ }
3652
+ },
3653
+ children: pasteLoading ? "Resolving\u2026" : "Resolve"
3654
+ }
3655
+ ) : void 0;
3641
3656
  return /* @__PURE__ */ jsx45(
3642
3657
  Popover,
3643
3658
  {
@@ -3706,17 +3721,25 @@ function useReseedFromProps(value, applies, reseed) {
3706
3721
  if (!sameValue(value, applies())) reseed(value);
3707
3722
  }, [value, applies, reseed]);
3708
3723
  }
3709
- function usePreserveFocusAcrossRemount(seed) {
3710
- const pendingId = React25.useRef(null);
3711
- const capture = (ids) => {
3724
+ function usePreserveFocusAcrossRemount(seed, fields) {
3725
+ const pendingName = React25.useRef(null);
3726
+ const fieldsRef = useLatest(fields);
3727
+ const capture = () => {
3712
3728
  const active = document.activeElement;
3713
- pendingId.current = active instanceof HTMLElement && ids.includes(active.id) ? active.id : null;
3729
+ pendingName.current = null;
3730
+ if (!(active instanceof HTMLElement)) return;
3731
+ for (const [name, ref] of Object.entries(fieldsRef.current)) {
3732
+ if (ref.current?.contains(active)) {
3733
+ pendingName.current = name;
3734
+ break;
3735
+ }
3736
+ }
3714
3737
  };
3715
3738
  React25.useLayoutEffect(() => {
3716
- const id = pendingId.current;
3717
- if (!id) return;
3718
- pendingId.current = null;
3719
- document.getElementById(id)?.focus();
3739
+ const name = pendingName.current;
3740
+ if (!name) return;
3741
+ pendingName.current = null;
3742
+ fieldsRef.current[name]?.current?.querySelector("input,textarea,select,button")?.focus();
3720
3743
  }, [seed]);
3721
3744
  return capture;
3722
3745
  }
@@ -3730,9 +3753,11 @@ function RangePanel({
3730
3753
  }) {
3731
3754
  const [draft, setDraft] = React25.useState(() => rangeDraft(value));
3732
3755
  const [seed, setSeed] = React25.useState(0);
3733
- const preserveFocus = usePreserveFocusAcrossRemount(seed);
3734
- const minId = field.key + "-min";
3735
- const maxId = field.key + "-max";
3756
+ const minId = React25.useId();
3757
+ const maxId = React25.useId();
3758
+ const minWrapRef = React25.useRef(null);
3759
+ const maxWrapRef = React25.useRef(null);
3760
+ const preserveFocus = usePreserveFocusAcrossRemount(seed, { min: minWrapRef, max: maxWrapRef });
3736
3761
  const draftRef = React25.useRef(draft);
3737
3762
  const shown = () => {
3738
3763
  const { min, max } = draftRef.current;
@@ -3743,7 +3768,7 @@ function RangePanel({
3743
3768
  };
3744
3769
  const validity = useTextValidity(publish);
3745
3770
  useReseedFromProps(value, shown, (next) => {
3746
- preserveFocus([minId, maxId]);
3771
+ preserveFocus();
3747
3772
  draftRef.current = rangeDraft(next);
3748
3773
  setDraft(draftRef.current);
3749
3774
  validity.reset();
@@ -3773,7 +3798,7 @@ function RangePanel({
3773
3798
  label: field.label,
3774
3799
  footer: /* @__PURE__ */ jsx45(Button, { size: "sm", variant: "secondary", onClick: onClose, disabled: doneDisabled, children: "Done" }),
3775
3800
  children: /* @__PURE__ */ jsxs39("span", { className: "fd-stack fd-gap-sm", children: [
3776
- /* @__PURE__ */ jsx45(
3801
+ /* @__PURE__ */ jsx45("span", { ref: minWrapRef, children: /* @__PURE__ */ jsx45(
3777
3802
  NumberInput,
3778
3803
  {
3779
3804
  id: minId,
@@ -3788,8 +3813,8 @@ function RangePanel({
3788
3813
  onValidityChange: validity.report("min")
3789
3814
  },
3790
3815
  "min-" + seed
3791
- ),
3792
- /* @__PURE__ */ jsx45(
3816
+ ) }),
3817
+ /* @__PURE__ */ jsx45("span", { ref: maxWrapRef, children: /* @__PURE__ */ jsx45(
3793
3818
  NumberInput,
3794
3819
  {
3795
3820
  id: maxId,
@@ -3805,7 +3830,7 @@ function RangePanel({
3805
3830
  onValidityChange: validity.report("max")
3806
3831
  },
3807
3832
  "max-" + seed
3808
- )
3833
+ ) })
3809
3834
  ] })
3810
3835
  }
3811
3836
  );
@@ -3832,8 +3857,9 @@ function DatePanel({
3832
3857
  const daysConfirmed = React25.useRef(value?.kind === "withinDays");
3833
3858
  const [between, setBetween] = React25.useState(initial.between);
3834
3859
  const [seed, setSeed] = React25.useState(0);
3835
- const preserveFocus = usePreserveFocusAcrossRemount(seed);
3836
- const daysId = field.key + "-days";
3860
+ const daysId = React25.useId();
3861
+ const daysWrapRef = React25.useRef(null);
3862
+ const preserveFocus = usePreserveFocusAcrossRemount(seed, { days: daysWrapRef });
3837
3863
  const shownWithinDays = () => {
3838
3864
  const days = daysRef.current;
3839
3865
  return applicable(field, days == null ? void 0 : { kind: "withinDays", days }, validity.allValid());
@@ -3849,7 +3875,7 @@ function DatePanel({
3849
3875
  return daysConfirmed.current ? shownWithinDays() : void 0;
3850
3876
  };
3851
3877
  useReseedFromProps(value, applies, (next) => {
3852
- preserveFocus([daysId]);
3878
+ preserveFocus();
3853
3879
  const d = dateDraft(field, next);
3854
3880
  setKind(d.kind);
3855
3881
  daysRef.current = d.days;
@@ -3916,7 +3942,7 @@ function DatePanel({
3916
3942
  onChange: (k) => switchKind(k)
3917
3943
  }
3918
3944
  ),
3919
- kind === "withinDays" ? /* @__PURE__ */ jsx45(
3945
+ kind === "withinDays" ? /* @__PURE__ */ jsx45("span", { ref: daysWrapRef, children: /* @__PURE__ */ jsx45(
3920
3946
  NumberInput,
3921
3947
  {
3922
3948
  id: daysId,
@@ -3930,7 +3956,7 @@ function DatePanel({
3930
3956
  onValidityChange: validity.report("days")
3931
3957
  },
3932
3958
  "days-" + seed
3933
- ) : /* @__PURE__ */ jsx45(
3959
+ ) }) : /* @__PURE__ */ jsx45(
3934
3960
  DatePicker,
3935
3961
  {
3936
3962
  range: true,