@flytedan/flytebot-design-system 0.32.0 → 0.33.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/README.md +6 -4
- package/dist/index.cjs +75 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -3
- package/dist/index.d.ts +8 -3
- package/dist/index.js +75 -21
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -81,7 +81,8 @@ pnpm run docs
|
|
|
81
81
|
pnpm run build # tsup — emits dist/{index.js,index.cjs,index.d.ts}
|
|
82
82
|
pnpm run typecheck # tsc --noEmit
|
|
83
83
|
pnpm run lint # eslint .
|
|
84
|
-
pnpm run test #
|
|
84
|
+
pnpm run test # vitest run — needs no build
|
|
85
|
+
pnpm run test:dist # tsup, then the checks of the built dist/ (scripts/vitest.dist.config.ts)
|
|
85
86
|
```
|
|
86
87
|
|
|
87
88
|
## Releasing
|
|
@@ -112,9 +113,10 @@ bash scripts/release.sh <new-version> "<summary>"
|
|
|
112
113
|
- fetches `origin` and checks out `origin/main`'s exact tip — never unmerged
|
|
113
114
|
work;
|
|
114
115
|
- installs with `pnpm install --frozen-lockfile`;
|
|
115
|
-
- runs the gates: `tsup
|
|
116
|
-
`vitest run
|
|
117
|
-
`
|
|
116
|
+
- runs the gates: `tsup`, then straight away the checks of that build
|
|
117
|
+
(`vitest run --config scripts/vitest.dist.config.ts`), then `vitest run`,
|
|
118
|
+
`tsc --noEmit`, `tsc --noEmit -p tsconfig.docs.json`, the docs `vite build`,
|
|
119
|
+
and `lint` if the repo has that script;
|
|
118
120
|
- refuses `<new-version>` unless it is greater than both the working
|
|
119
121
|
checkout's `package.json` version and npm's currently published `latest`;
|
|
120
122
|
- bumps `package.json`, commits `chore(release): <new-version> — <summary>`,
|
package/dist/index.cjs
CHANGED
|
@@ -3217,7 +3217,8 @@ function NumberInput({
|
|
|
3217
3217
|
)
|
|
3218
3218
|
] })
|
|
3219
3219
|
] }),
|
|
3220
|
-
|
|
3220
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { id: errorId, className: "fd-sr", role: "status", children: shownError ?? "" }),
|
|
3221
|
+
shownError ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "fd-field-error", "aria-hidden": "true", children: [
|
|
3221
3222
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3222
3223
|
shownError
|
|
3223
3224
|
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
@@ -3658,9 +3659,7 @@ function MultiSelectPanel({
|
|
|
3658
3659
|
mountedRef.current = false;
|
|
3659
3660
|
};
|
|
3660
3661
|
}, []);
|
|
3661
|
-
const commit = (nextValues, nextOperator = operator) => {
|
|
3662
|
-
onCommit({ operator: nextOperator, values: nextValues });
|
|
3663
|
-
};
|
|
3662
|
+
const commit = (nextValues, nextOperator = operator) => onCommit({ operator: nextOperator, values: nextValues });
|
|
3664
3663
|
const setOperator = (op) => {
|
|
3665
3664
|
setDraftOperator(op);
|
|
3666
3665
|
if (selectedRef.current.length > 0) commit(selectedRef.current, op);
|
|
@@ -3741,7 +3740,11 @@ function MultiSelectPanel({
|
|
|
3741
3740
|
setPasteError("This filter allows at most " + field.maxValues + " values; adding this list would make " + merged.size + ".");
|
|
3742
3741
|
return;
|
|
3743
3742
|
}
|
|
3744
|
-
commit(Array.from(merged.values()), operatorRef.current);
|
|
3743
|
+
const applied = commit(Array.from(merged.values()), operatorRef.current);
|
|
3744
|
+
if (!applied.ok) {
|
|
3745
|
+
setPasteError(applied.reason);
|
|
3746
|
+
return;
|
|
3747
|
+
}
|
|
3745
3748
|
setPasteText("");
|
|
3746
3749
|
}, (err) => {
|
|
3747
3750
|
if (!mountedRef.current) return;
|
|
@@ -3878,6 +3881,34 @@ function MultiSelectPanel({
|
|
|
3878
3881
|
}
|
|
3879
3882
|
);
|
|
3880
3883
|
}
|
|
3884
|
+
function useTextValidity(onFlip) {
|
|
3885
|
+
const invalidRef = React24.useRef(/* @__PURE__ */ new Set());
|
|
3886
|
+
const [, rerender] = React24.useReducer((n) => n + 1, 0);
|
|
3887
|
+
const onFlipRef = React24.useRef(onFlip);
|
|
3888
|
+
onFlipRef.current = onFlip;
|
|
3889
|
+
const record = (name, valid) => {
|
|
3890
|
+
const invalid = invalidRef.current;
|
|
3891
|
+
if (valid !== invalid.has(name)) return false;
|
|
3892
|
+
if (valid) invalid.delete(name);
|
|
3893
|
+
else invalid.add(name);
|
|
3894
|
+
rerender();
|
|
3895
|
+
return true;
|
|
3896
|
+
};
|
|
3897
|
+
return {
|
|
3898
|
+
allValid: () => invalidRef.current.size === 0,
|
|
3899
|
+
report: (name) => (valid) => {
|
|
3900
|
+
if (record(name, valid)) onFlipRef.current();
|
|
3901
|
+
},
|
|
3902
|
+
/** For an input that is about to unmount: it has nothing left to show. */
|
|
3903
|
+
forget: (name) => {
|
|
3904
|
+
record(name, true);
|
|
3905
|
+
}
|
|
3906
|
+
};
|
|
3907
|
+
}
|
|
3908
|
+
function applicable(field, candidate, textValid) {
|
|
3909
|
+
if (!textValid || candidate === void 0) return void 0;
|
|
3910
|
+
return validateFilterValue(field, candidate).ok ? candidate : void 0;
|
|
3911
|
+
}
|
|
3881
3912
|
function RangePanel({
|
|
3882
3913
|
field,
|
|
3883
3914
|
value,
|
|
@@ -3887,19 +3918,22 @@ function RangePanel({
|
|
|
3887
3918
|
}) {
|
|
3888
3919
|
const [draft, setDraft] = React24.useState({ min: value?.min, max: value?.max });
|
|
3889
3920
|
const draftRef = React24.useRef(draft);
|
|
3890
|
-
const
|
|
3891
|
-
|
|
3921
|
+
const publish = () => {
|
|
3922
|
+
const { min, max } = draftRef.current;
|
|
3923
|
+
onCommit(applicable(field, min == null && max == null ? void 0 : { min, max }, validity.allValid()));
|
|
3924
|
+
};
|
|
3925
|
+
const validity = useTextValidity(publish);
|
|
3892
3926
|
const draftMin = draft.min;
|
|
3893
3927
|
const draftMax = draft.max;
|
|
3894
3928
|
const isEmpty = draftMin == null && draftMax == null;
|
|
3895
3929
|
const validation = isEmpty ? { ok: true } : validateFilterValue(field, { min: draftMin, max: draftMax });
|
|
3896
3930
|
const comboError = !isEmpty && !validation.ok ? validation.reason : void 0;
|
|
3897
|
-
const doneDisabled = !
|
|
3931
|
+
const doneDisabled = !validity.allValid() || !!comboError;
|
|
3898
3932
|
const apply = (patch) => {
|
|
3899
3933
|
const next = { ...draftRef.current, ...patch };
|
|
3900
3934
|
draftRef.current = next;
|
|
3901
3935
|
setDraft(next);
|
|
3902
|
-
|
|
3936
|
+
publish();
|
|
3903
3937
|
};
|
|
3904
3938
|
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3905
3939
|
Popover,
|
|
@@ -3924,7 +3958,7 @@ function RangePanel({
|
|
|
3924
3958
|
integer: field.integer,
|
|
3925
3959
|
placeholder: field.minPlaceholder,
|
|
3926
3960
|
onChange: (e) => apply({ min: e.target.value }),
|
|
3927
|
-
onValidityChange:
|
|
3961
|
+
onValidityChange: validity.report("min")
|
|
3928
3962
|
}
|
|
3929
3963
|
),
|
|
3930
3964
|
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
@@ -3939,7 +3973,7 @@ function RangePanel({
|
|
|
3939
3973
|
error: comboError,
|
|
3940
3974
|
placeholder: field.maxPlaceholder,
|
|
3941
3975
|
onChange: (e) => apply({ max: e.target.value }),
|
|
3942
|
-
onValidityChange:
|
|
3976
|
+
onValidityChange: validity.report("max")
|
|
3943
3977
|
}
|
|
3944
3978
|
)
|
|
3945
3979
|
] })
|
|
@@ -3955,34 +3989,47 @@ function DatePanel({
|
|
|
3955
3989
|
}) {
|
|
3956
3990
|
const defaultDays = field.defaultDays ?? 30;
|
|
3957
3991
|
const maxDays = effectiveMaxDays(field);
|
|
3958
|
-
const [daysTextValid, setDaysTextValid] = React24.useState(true);
|
|
3959
3992
|
const [kind, setKind] = React24.useState(value?.kind ?? "withinDays");
|
|
3960
3993
|
const [daysDraft, setDaysDraft] = React24.useState(
|
|
3961
3994
|
value?.kind === "withinDays" ? value.days : defaultDays
|
|
3962
3995
|
);
|
|
3996
|
+
const daysRef = React24.useRef(daysDraft);
|
|
3963
3997
|
const [between, setBetween] = React24.useState(
|
|
3964
3998
|
value?.kind === "between" ? { from: value.from, to: value.to } : { from: "", to: "" }
|
|
3965
3999
|
);
|
|
4000
|
+
const shownWithinDays = () => {
|
|
4001
|
+
const days = daysRef.current;
|
|
4002
|
+
return applicable(field, days == null ? void 0 : { kind: "withinDays", days }, validity.allValid());
|
|
4003
|
+
};
|
|
4004
|
+
const validity = useTextValidity(() => onCommit(shownWithinDays()));
|
|
3966
4005
|
const applyWithinDays = (days) => {
|
|
4006
|
+
daysRef.current = days;
|
|
3967
4007
|
setDaysDraft(days);
|
|
3968
|
-
onCommit(
|
|
4008
|
+
onCommit(shownWithinDays());
|
|
3969
4009
|
};
|
|
3970
4010
|
const applyBetween = (from, to) => {
|
|
3971
4011
|
setBetween({ from, to });
|
|
3972
|
-
onCommit(from && to ? { kind: "between", from, to } : void 0);
|
|
4012
|
+
onCommit(applicable(field, from && to ? { kind: "between", from, to } : void 0, true));
|
|
3973
4013
|
};
|
|
3974
4014
|
const switchKind = (next) => {
|
|
3975
4015
|
if (next === kind) return;
|
|
3976
4016
|
setKind(next);
|
|
3977
|
-
if (next === "between")
|
|
3978
|
-
|
|
3979
|
-
|
|
4017
|
+
if (next === "between") {
|
|
4018
|
+
setBetween({ from: "", to: "" });
|
|
4019
|
+
validity.forget("days");
|
|
4020
|
+
} else {
|
|
4021
|
+
daysRef.current = defaultDays;
|
|
4022
|
+
setDaysDraft(defaultDays);
|
|
4023
|
+
}
|
|
3980
4024
|
onCommit(void 0);
|
|
3981
4025
|
};
|
|
3982
|
-
const doneDisabled = kind === "withinDays" && !
|
|
4026
|
+
const doneDisabled = kind === "withinDays" && !validity.allValid();
|
|
3983
4027
|
const confirm = () => {
|
|
3984
4028
|
if (doneDisabled) return;
|
|
3985
|
-
if (kind === "withinDays"
|
|
4029
|
+
if (kind === "withinDays") {
|
|
4030
|
+
const shown = shownWithinDays();
|
|
4031
|
+
if (shown) onCommit(shown);
|
|
4032
|
+
}
|
|
3986
4033
|
onClose();
|
|
3987
4034
|
};
|
|
3988
4035
|
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
@@ -4019,7 +4066,7 @@ function DatePanel({
|
|
|
4019
4066
|
integer: true,
|
|
4020
4067
|
value: daysDraft ?? "",
|
|
4021
4068
|
onChange: (e) => applyWithinDays(e.target.value),
|
|
4022
|
-
onValidityChange:
|
|
4069
|
+
onValidityChange: validity.report("days")
|
|
4023
4070
|
}
|
|
4024
4071
|
) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
4025
4072
|
DatePicker,
|
|
@@ -4044,7 +4091,14 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
4044
4091
|
for (const f of fields) assertValidFieldDefinition(f);
|
|
4045
4092
|
}
|
|
4046
4093
|
const latest = React24.useRef({ fields, filters, onFilterChange, onFilterRemove });
|
|
4047
|
-
|
|
4094
|
+
const filtersProp = React24.useRef(filters);
|
|
4095
|
+
if (filters !== filtersProp.current) {
|
|
4096
|
+
filtersProp.current = filters;
|
|
4097
|
+
latest.current.filters = filters;
|
|
4098
|
+
}
|
|
4099
|
+
latest.current.fields = fields;
|
|
4100
|
+
latest.current.onFilterChange = onFilterChange;
|
|
4101
|
+
latest.current.onFilterRemove = onFilterRemove;
|
|
4048
4102
|
const commit = (field, candidate) => {
|
|
4049
4103
|
const current2 = latest.current.fields.find((f) => f.key === field.key);
|
|
4050
4104
|
if (!current2) return { ok: false, reason: "This filter is no longer available" };
|