@geomak/ui 5.6.0 → 5.7.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/index.cjs +471 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +534 -188
- package/dist/index.d.ts +534 -188
- package/dist/index.js +460 -22
- package/dist/index.js.map +1 -1
- package/dist/styles.css +18 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -75,7 +75,7 @@ var FleetIcon = ({ color = "#fff", size = 30 }) => /* @__PURE__ */ jsxRuntime.js
|
|
|
75
75
|
/* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: "clip0_327_836", children: /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "30", height: "30", fill: color }) }) })
|
|
76
76
|
] });
|
|
77
77
|
var Performance = ({ color = "#fff", size = 30 }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 30 30", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5.64 25.515H24.36C26.0709 23.3842 27.0024 20.7327 27 18C27 11.385 21.63 6 15 6C8.37 6 3 11.385 3 18C3 20.85 3.99 23.445 5.64 25.515ZM13.5 9C13.5 8.175 14.175 7.5 15 7.5C15.825 7.5 16.5 8.175 16.5 9C16.5 9.84 15.825 10.5 15 10.5C14.175 10.5 13.5 9.84 13.5 9ZM6 12C6 11.175 6.675 10.5 7.5 10.5C8.325 10.5 9 11.175 9 12C9 12.84 8.325 13.5 7.5 13.5C6.675 13.5 6 12.84 6 12ZM12.78 17.1C14.04 15.855 22.545 11.85 22.545 11.85C22.545 11.85 18.555 20.37 17.31 21.615C16.05 22.875 14.04 22.875 12.78 21.615C12.1819 21.016 11.8459 20.204 11.8459 19.3575C11.8459 18.511 12.1819 17.699 12.78 17.1ZM4.5 19.5C4.5 18.675 5.175 18 6 18C6.825 18 7.5 18.675 7.5 19.5C7.5 20.34 6.825 21 6 21C5.175 21 4.5 20.34 4.5 19.5ZM13.5 19.5C13.5 18.675 14.175 18 15 18C15.825 18 16.5 18.675 16.5 19.5C16.5 20.34 15.825 21 15 21C14.175 21 13.5 20.34 13.5 19.5ZM22.5 19.5C22.5 18.675 23.175 18 24 18C24.825 18 25.5 18.675 25.5 19.5C25.5 20.34 24.825 21 24 21C23.175 21 22.5 20.34 22.5 19.5Z", fill: color }) });
|
|
78
|
-
var
|
|
78
|
+
var Map2 = ({ color = "#fff", size = 30 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: size, height: size, viewBox: "0 0 34 30", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
79
79
|
/* @__PURE__ */ jsxRuntime.jsx("g", { clipPath: "url(#clip0_327_830)", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16.875 0C12.7975 0 9.49219 3.30527 9.49219 7.38281C9.49219 10.6793 14.3174 16.6875 16.166 18.8684C16.5404 19.3102 17.2102 19.3102 17.584 18.8684C19.4326 16.6875 24.2578 10.6793 24.2578 7.38281C24.2578 3.30527 20.9525 0 16.875 0ZM16.875 9.84375C15.5156 9.84375 14.4141 8.74219 14.4141 7.38281C14.4141 6.02344 15.5156 4.92188 16.875 4.92188C18.2344 4.92188 19.3359 6.02344 19.3359 7.38281C19.3359 8.74219 18.2344 9.84375 16.875 9.84375ZM1.17891 12.6533C0.830964 12.7925 0.532694 13.0327 0.322564 13.343C0.112435 13.6533 8.33325e-05 14.0194 0 14.3941L0 29.0613C0 29.7246 0.669727 30.1781 1.28555 29.932L9.375 26.25V12.593C8.85703 11.6566 8.4334 10.7449 8.12988 9.87305L1.17891 12.6533ZM16.875 21.0744C16.0506 21.0744 15.2707 20.7123 14.7357 20.0807C13.5838 18.7213 12.3586 17.1732 11.25 15.5854V26.2494L22.5 29.9994V15.5859C21.3914 17.1732 20.1668 18.7219 19.0143 20.0812C18.4793 20.7123 17.6994 21.0744 16.875 21.0744ZM32.4645 9.44297L24.375 13.125V30L32.5711 26.7217C32.9191 26.5826 33.2174 26.3424 33.4275 26.0321C33.6377 25.7218 33.75 25.3556 33.75 24.9809V10.3137C33.75 9.65039 33.0803 9.19688 32.4645 9.44297Z", fill: color }) }),
|
|
80
80
|
/* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: "clip0_327_830", children: /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "33.75", height: "30", fill: color }) }) })
|
|
81
81
|
] });
|
|
@@ -162,7 +162,7 @@ Icon.Minus = Minus;
|
|
|
162
162
|
Icon.Dashboard = Dashboard;
|
|
163
163
|
Icon.FleetIcon = FleetIcon;
|
|
164
164
|
Icon.Performance = Performance;
|
|
165
|
-
Icon.Map =
|
|
165
|
+
Icon.Map = Map2;
|
|
166
166
|
Icon.CharterParty = CharterParty;
|
|
167
167
|
Icon.Compliance = Compliance;
|
|
168
168
|
Icon.Applications = Applications;
|
|
@@ -3852,29 +3852,35 @@ function RadioGroup({
|
|
|
3852
3852
|
children: /* @__PURE__ */ jsxRuntime.jsx(RadioGroupPrimitive__namespace.Indicator, { className: "flex h-full w-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block h-1/2 w-1/2 rounded-full bg-accent" }) })
|
|
3853
3853
|
}
|
|
3854
3854
|
);
|
|
3855
|
-
const
|
|
3855
|
+
const labelClass = [
|
|
3856
|
+
"block select-none",
|
|
3857
|
+
opt.disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer"
|
|
3858
|
+
].join(" ");
|
|
3859
|
+
const labelTextEl = /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: itemId, className: labelClass, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: `block ${TEXT_SIZE[size]} text-foreground`, children: opt.label }) });
|
|
3860
|
+
const descriptionEl = opt.description ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3856
3861
|
"label",
|
|
3857
3862
|
{
|
|
3858
3863
|
htmlFor: itemId,
|
|
3859
|
-
className:
|
|
3860
|
-
|
|
3861
|
-
opt.disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer",
|
|
3862
|
-
labelFirst ? "text-right" : ""
|
|
3863
|
-
].filter(Boolean).join(" "),
|
|
3864
|
-
children: [
|
|
3865
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `block ${TEXT_SIZE[size]} text-foreground`, children: opt.label }),
|
|
3866
|
-
opt.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-xs text-foreground-secondary mt-0.5", children: opt.description })
|
|
3867
|
-
]
|
|
3864
|
+
className: `block text-xs text-foreground-secondary mt-0.5 ${opt.disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}`,
|
|
3865
|
+
children: opt.description
|
|
3868
3866
|
}
|
|
3869
|
-
);
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3867
|
+
) : null;
|
|
3868
|
+
if (labelFirst) {
|
|
3869
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
3870
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2.5", children: [
|
|
3871
|
+
labelTextEl,
|
|
3872
|
+
dot
|
|
3873
|
+
] }),
|
|
3874
|
+
descriptionEl
|
|
3875
|
+
] }, opt.value);
|
|
3876
|
+
}
|
|
3877
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2.5", children: [
|
|
3875
3878
|
dot,
|
|
3876
|
-
|
|
3877
|
-
|
|
3879
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-col", children: [
|
|
3880
|
+
labelTextEl,
|
|
3881
|
+
descriptionEl
|
|
3882
|
+
] })
|
|
3883
|
+
] }, opt.value);
|
|
3878
3884
|
})
|
|
3879
3885
|
}
|
|
3880
3886
|
)
|
|
@@ -5920,6 +5926,438 @@ function ColorPicker({
|
|
|
5920
5926
|
] });
|
|
5921
5927
|
}
|
|
5922
5928
|
|
|
5929
|
+
// src/form/path.ts
|
|
5930
|
+
function deepClone(v) {
|
|
5931
|
+
if (v === null || typeof v !== "object") return v;
|
|
5932
|
+
if (v instanceof Date) return new Date(v.getTime());
|
|
5933
|
+
if (Array.isArray(v)) return v.map(deepClone);
|
|
5934
|
+
const out = {};
|
|
5935
|
+
for (const k in v) out[k] = deepClone(v[k]);
|
|
5936
|
+
return out;
|
|
5937
|
+
}
|
|
5938
|
+
function getPath(obj, path) {
|
|
5939
|
+
if (!path) return obj;
|
|
5940
|
+
const parts = path.split(".");
|
|
5941
|
+
let cur = obj;
|
|
5942
|
+
for (const p of parts) {
|
|
5943
|
+
if (cur == null || typeof cur !== "object") return void 0;
|
|
5944
|
+
cur = cur[p];
|
|
5945
|
+
}
|
|
5946
|
+
return cur;
|
|
5947
|
+
}
|
|
5948
|
+
function setPath(obj, path, value) {
|
|
5949
|
+
const parts = path.split(".");
|
|
5950
|
+
const root = Array.isArray(obj) ? [...obj] : { ...obj ?? {} };
|
|
5951
|
+
let cur = root;
|
|
5952
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
5953
|
+
const p = parts[i];
|
|
5954
|
+
const nextIsIndex = /^\d+$/.test(parts[i + 1]);
|
|
5955
|
+
const child = cur[p];
|
|
5956
|
+
const next = Array.isArray(child) ? [...child] : child && typeof child === "object" ? { ...child } : nextIsIndex ? [] : {};
|
|
5957
|
+
cur[p] = next;
|
|
5958
|
+
cur = next;
|
|
5959
|
+
}
|
|
5960
|
+
cur[parts[parts.length - 1]] = value;
|
|
5961
|
+
return root;
|
|
5962
|
+
}
|
|
5963
|
+
|
|
5964
|
+
// src/form/validate.ts
|
|
5965
|
+
function isEmpty(v) {
|
|
5966
|
+
return v == null || v === "" || v === false || Array.isArray(v) && v.length === 0;
|
|
5967
|
+
}
|
|
5968
|
+
var boundValue = (b) => typeof b === "number" ? b : b.value;
|
|
5969
|
+
var boundMessage = (b, fallback) => typeof b === "number" ? fallback : b.message ?? fallback;
|
|
5970
|
+
function isRequired(rules) {
|
|
5971
|
+
if (!rules) return false;
|
|
5972
|
+
const list = Array.isArray(rules) ? rules : [rules];
|
|
5973
|
+
return list.some((r) => !!r.required);
|
|
5974
|
+
}
|
|
5975
|
+
async function runFieldRules(value, rules, values) {
|
|
5976
|
+
if (!rules) return void 0;
|
|
5977
|
+
const list = Array.isArray(rules) ? rules : [rules];
|
|
5978
|
+
for (const rule of list) {
|
|
5979
|
+
if (rule.required && isEmpty(value)) {
|
|
5980
|
+
return typeof rule.required === "string" ? rule.required : rule.message ?? "This field is required";
|
|
5981
|
+
}
|
|
5982
|
+
if (isEmpty(value)) {
|
|
5983
|
+
if (rule.validate) {
|
|
5984
|
+
const res = await rule.validate(value, values);
|
|
5985
|
+
if (res) return typeof res === "string" ? res : rule.message ?? "Invalid value";
|
|
5986
|
+
}
|
|
5987
|
+
continue;
|
|
5988
|
+
}
|
|
5989
|
+
if (rule.pattern) {
|
|
5990
|
+
const re = rule.pattern instanceof RegExp ? rule.pattern : rule.pattern.value;
|
|
5991
|
+
const msg = rule.pattern instanceof RegExp ? rule.message ?? "Invalid format" : rule.pattern.message ?? rule.message ?? "Invalid format";
|
|
5992
|
+
if (typeof value === "string" && !re.test(value)) return msg;
|
|
5993
|
+
}
|
|
5994
|
+
if (rule.min != null && typeof value === "number") {
|
|
5995
|
+
const m = boundValue(rule.min);
|
|
5996
|
+
if (value < m) return boundMessage(rule.min, rule.message ?? `Must be at least ${m}`);
|
|
5997
|
+
}
|
|
5998
|
+
if (rule.max != null && typeof value === "number") {
|
|
5999
|
+
const m = boundValue(rule.max);
|
|
6000
|
+
if (value > m) return boundMessage(rule.max, rule.message ?? `Must be at most ${m}`);
|
|
6001
|
+
}
|
|
6002
|
+
if (rule.minLength != null) {
|
|
6003
|
+
const len = value?.length;
|
|
6004
|
+
const m = boundValue(rule.minLength);
|
|
6005
|
+
if (typeof len === "number" && len < m)
|
|
6006
|
+
return boundMessage(rule.minLength, rule.message ?? `Must be at least ${m} characters`);
|
|
6007
|
+
}
|
|
6008
|
+
if (rule.maxLength != null) {
|
|
6009
|
+
const len = value?.length;
|
|
6010
|
+
const m = boundValue(rule.maxLength);
|
|
6011
|
+
if (typeof len === "number" && len > m)
|
|
6012
|
+
return boundMessage(rule.maxLength, rule.message ?? `Must be at most ${m} characters`);
|
|
6013
|
+
}
|
|
6014
|
+
if (rule.validate) {
|
|
6015
|
+
const res = await rule.validate(value, values);
|
|
6016
|
+
if (res) return typeof res === "string" ? res : rule.message ?? "Invalid value";
|
|
6017
|
+
}
|
|
6018
|
+
}
|
|
6019
|
+
return void 0;
|
|
6020
|
+
}
|
|
6021
|
+
var patterns = {
|
|
6022
|
+
email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
|
6023
|
+
url: /^https?:\/\/[^\s/$.?#].[^\s]*$/i,
|
|
6024
|
+
// Loose international phone: + and 7-15 digits, spaces/dashes allowed.
|
|
6025
|
+
phone: /^\+?[\d\s-]{7,15}$/,
|
|
6026
|
+
// Digits only.
|
|
6027
|
+
digits: /^\d+$/
|
|
6028
|
+
};
|
|
6029
|
+
|
|
6030
|
+
// src/form/store.ts
|
|
6031
|
+
var FormStore = class {
|
|
6032
|
+
listeners = /* @__PURE__ */ new Set();
|
|
6033
|
+
fieldCache = /* @__PURE__ */ new Map();
|
|
6034
|
+
values;
|
|
6035
|
+
errors = {};
|
|
6036
|
+
touched = {};
|
|
6037
|
+
submitted = false;
|
|
6038
|
+
validating = false;
|
|
6039
|
+
initialValues;
|
|
6040
|
+
rules;
|
|
6041
|
+
validateOn;
|
|
6042
|
+
// Field-array key bookkeeping (stable React keys across reorder/removal).
|
|
6043
|
+
keys = {};
|
|
6044
|
+
keySeq = 1;
|
|
6045
|
+
// Root snapshot — a new ref on every change, for form-level subscribers.
|
|
6046
|
+
rootSnap = { v: 0 };
|
|
6047
|
+
constructor(opts = {}) {
|
|
6048
|
+
this.initialValues = deepClone(opts.initialValues ?? {});
|
|
6049
|
+
this.values = deepClone(opts.initialValues ?? {});
|
|
6050
|
+
this.rules = { ...opts.rules ?? {} };
|
|
6051
|
+
this.validateOn = opts.validateOn ?? ["onChange", "onBlur", "onSubmit"];
|
|
6052
|
+
}
|
|
6053
|
+
// ── subscription ────────────────────────────────────────────────────────
|
|
6054
|
+
subscribe = (l) => {
|
|
6055
|
+
this.listeners.add(l);
|
|
6056
|
+
return () => {
|
|
6057
|
+
this.listeners.delete(l);
|
|
6058
|
+
};
|
|
6059
|
+
};
|
|
6060
|
+
emit() {
|
|
6061
|
+
this.rootSnap = { v: this.rootSnap.v + 1 };
|
|
6062
|
+
this.listeners.forEach((l) => l());
|
|
6063
|
+
}
|
|
6064
|
+
getRootSnapshot = () => this.rootSnap;
|
|
6065
|
+
getFieldSnapshot = (name) => {
|
|
6066
|
+
const value = getPath(this.values, name);
|
|
6067
|
+
const error = this.errors[name];
|
|
6068
|
+
const showError = (!!this.touched[name] || this.submitted) && error != null;
|
|
6069
|
+
const prev = this.fieldCache.get(name);
|
|
6070
|
+
if (prev && Object.is(prev.value, value) && prev.error === error && prev.showError === showError) {
|
|
6071
|
+
return prev.snap;
|
|
6072
|
+
}
|
|
6073
|
+
const snap = { value, error, showError };
|
|
6074
|
+
this.fieldCache.set(name, { value, error, showError, snap });
|
|
6075
|
+
return snap;
|
|
6076
|
+
};
|
|
6077
|
+
// ── rule registry (for dynamic / array fields) ──────────────────────────
|
|
6078
|
+
setRule(name, rules) {
|
|
6079
|
+
if (rules == null) delete this.rules[name];
|
|
6080
|
+
else this.rules[name] = rules;
|
|
6081
|
+
}
|
|
6082
|
+
removeRule(name) {
|
|
6083
|
+
delete this.rules[name];
|
|
6084
|
+
}
|
|
6085
|
+
getRule(name) {
|
|
6086
|
+
return this.rules[name];
|
|
6087
|
+
}
|
|
6088
|
+
// ── reads ────────────────────────────────────────────────────────────────
|
|
6089
|
+
getValues = () => this.values;
|
|
6090
|
+
getValue = (name) => getPath(this.values, name);
|
|
6091
|
+
get isValid() {
|
|
6092
|
+
return Object.values(this.errors).every((e) => !e);
|
|
6093
|
+
}
|
|
6094
|
+
// ── writes ────────────────────────────────────────────────────────────────
|
|
6095
|
+
setValue = (name, value, opts = {}) => {
|
|
6096
|
+
this.values = setPath(this.values, name, value);
|
|
6097
|
+
if (opts.touch) this.touched = { ...this.touched, [name]: true };
|
|
6098
|
+
this.emit();
|
|
6099
|
+
const shouldValidate = opts.validate ?? this.validateOn.includes("onChange");
|
|
6100
|
+
if (shouldValidate) void this.validateField(name);
|
|
6101
|
+
};
|
|
6102
|
+
setValues = (patch, opts = {}) => {
|
|
6103
|
+
for (const k of Object.keys(patch)) this.values = setPath(this.values, k, patch[k]);
|
|
6104
|
+
this.emit();
|
|
6105
|
+
if (opts.validate) void this.validateAll();
|
|
6106
|
+
};
|
|
6107
|
+
setError = (name, error) => {
|
|
6108
|
+
if (this.errors[name] === error) return;
|
|
6109
|
+
this.errors = { ...this.errors, [name]: error || void 0 };
|
|
6110
|
+
this.emit();
|
|
6111
|
+
};
|
|
6112
|
+
touch = (name, opts = {}) => {
|
|
6113
|
+
if (!this.touched[name]) {
|
|
6114
|
+
this.touched = { ...this.touched, [name]: true };
|
|
6115
|
+
this.emit();
|
|
6116
|
+
}
|
|
6117
|
+
if (opts.validate ?? this.validateOn.includes("onBlur")) void this.validateField(name);
|
|
6118
|
+
};
|
|
6119
|
+
setSubmitted = (v) => {
|
|
6120
|
+
this.submitted = v;
|
|
6121
|
+
this.emit();
|
|
6122
|
+
};
|
|
6123
|
+
// ── validation ─────────────────────────────────────────────────────────────
|
|
6124
|
+
async validateField(name) {
|
|
6125
|
+
const err = await runFieldRules(getPath(this.values, name), this.rules[name], this.values);
|
|
6126
|
+
this.setError(name, err);
|
|
6127
|
+
return err;
|
|
6128
|
+
}
|
|
6129
|
+
async validateAll() {
|
|
6130
|
+
this.validating = true;
|
|
6131
|
+
this.emit();
|
|
6132
|
+
const names = Object.keys(this.rules);
|
|
6133
|
+
const entries = await Promise.all(
|
|
6134
|
+
names.map(async (n) => [n, await runFieldRules(getPath(this.values, n), this.rules[n], this.values)])
|
|
6135
|
+
);
|
|
6136
|
+
const errors = {};
|
|
6137
|
+
for (const [n, e] of entries) errors[n] = e;
|
|
6138
|
+
this.errors = errors;
|
|
6139
|
+
this.validating = false;
|
|
6140
|
+
this.emit();
|
|
6141
|
+
return errors;
|
|
6142
|
+
}
|
|
6143
|
+
reset = (values) => {
|
|
6144
|
+
this.values = deepClone(values ?? this.initialValues);
|
|
6145
|
+
this.errors = {};
|
|
6146
|
+
this.touched = {};
|
|
6147
|
+
this.submitted = false;
|
|
6148
|
+
this.keys = {};
|
|
6149
|
+
this.fieldCache.clear();
|
|
6150
|
+
this.emit();
|
|
6151
|
+
};
|
|
6152
|
+
// ── field arrays ───────────────────────────────────────────────────────────
|
|
6153
|
+
getKeys(name) {
|
|
6154
|
+
const arr = getPath(this.values, name) ?? [];
|
|
6155
|
+
let keys = this.keys[name];
|
|
6156
|
+
if (!keys || keys.length !== arr.length) {
|
|
6157
|
+
keys = arr.map((_, i) => keys && keys[i] != null ? keys[i] : this.keySeq++);
|
|
6158
|
+
this.keys[name] = keys;
|
|
6159
|
+
}
|
|
6160
|
+
return keys;
|
|
6161
|
+
}
|
|
6162
|
+
arrayAppend = (name, item = {}) => {
|
|
6163
|
+
const arr = [...getPath(this.values, name) ?? []];
|
|
6164
|
+
arr.push(item);
|
|
6165
|
+
this.keys[name] = [...this.getKeys(name), this.keySeq++];
|
|
6166
|
+
this.setValue(name, arr, { validate: false });
|
|
6167
|
+
};
|
|
6168
|
+
arrayRemove = (name, index) => {
|
|
6169
|
+
const arr = [...getPath(this.values, name) ?? []];
|
|
6170
|
+
arr.splice(index, 1);
|
|
6171
|
+
const k = [...this.getKeys(name)];
|
|
6172
|
+
k.splice(index, 1);
|
|
6173
|
+
this.keys[name] = k;
|
|
6174
|
+
this.clearBranch(name);
|
|
6175
|
+
this.setValue(name, arr, { validate: false });
|
|
6176
|
+
};
|
|
6177
|
+
arrayMove = (name, from, to) => {
|
|
6178
|
+
const arr = [...getPath(this.values, name) ?? []];
|
|
6179
|
+
if (from < 0 || to < 0 || from >= arr.length || to >= arr.length) return;
|
|
6180
|
+
const [moved] = arr.splice(from, 1);
|
|
6181
|
+
arr.splice(to, 0, moved);
|
|
6182
|
+
const k = [...this.getKeys(name)];
|
|
6183
|
+
const [mk] = k.splice(from, 1);
|
|
6184
|
+
k.splice(to, 0, mk);
|
|
6185
|
+
this.keys[name] = k;
|
|
6186
|
+
this.clearBranch(name);
|
|
6187
|
+
this.setValue(name, arr, { validate: false });
|
|
6188
|
+
};
|
|
6189
|
+
/** Drop any errors/touched flags under `name.` — used when an array shifts. */
|
|
6190
|
+
clearBranch(name) {
|
|
6191
|
+
const prefix = name + ".";
|
|
6192
|
+
const errors = {};
|
|
6193
|
+
for (const k of Object.keys(this.errors)) if (!k.startsWith(prefix)) errors[k] = this.errors[k];
|
|
6194
|
+
const touched = {};
|
|
6195
|
+
for (const k of Object.keys(this.touched)) if (!k.startsWith(prefix)) touched[k] = this.touched[k];
|
|
6196
|
+
this.errors = errors;
|
|
6197
|
+
this.touched = touched;
|
|
6198
|
+
}
|
|
6199
|
+
};
|
|
6200
|
+
|
|
6201
|
+
// src/form/bindings.ts
|
|
6202
|
+
var getTarget = (arg) => {
|
|
6203
|
+
const t = arg?.target;
|
|
6204
|
+
return t && typeof t === "object" ? t : void 0;
|
|
6205
|
+
};
|
|
6206
|
+
var ADAPTERS = {
|
|
6207
|
+
value: { prop: "value", toValue: (v) => v, applyEmpty: false, empty: void 0 },
|
|
6208
|
+
native: { prop: "value", toValue: (e) => getTarget(e)?.value, applyEmpty: true, empty: "" },
|
|
6209
|
+
checked: { prop: "checked", toValue: (e) => getTarget(e)?.checked, applyEmpty: true, empty: false },
|
|
6210
|
+
target: { prop: "value", toValue: (e) => getTarget(e)?.value, applyEmpty: false, empty: void 0 }
|
|
6211
|
+
};
|
|
6212
|
+
function buildBindings(store, name, kind, snap) {
|
|
6213
|
+
const a = ADAPTERS[kind];
|
|
6214
|
+
const raw = snap.value;
|
|
6215
|
+
const value = a.applyEmpty ? raw ?? a.empty : raw;
|
|
6216
|
+
return {
|
|
6217
|
+
name,
|
|
6218
|
+
id: name,
|
|
6219
|
+
htmlFor: name,
|
|
6220
|
+
required: isRequired(store.getRule(name)) || void 0,
|
|
6221
|
+
errorMessage: snap.showError ? snap.error : void 0,
|
|
6222
|
+
[a.prop]: value,
|
|
6223
|
+
onChange: (arg) => store.setValue(name, a.toValue(arg), { touch: true }),
|
|
6224
|
+
onBlur: () => store.touch(name)
|
|
6225
|
+
};
|
|
6226
|
+
}
|
|
6227
|
+
|
|
6228
|
+
// src/form/useForm.ts
|
|
6229
|
+
function useForm(options = {}) {
|
|
6230
|
+
const ref = React8.useRef(null);
|
|
6231
|
+
if (ref.current === null) ref.current = new FormStore(options);
|
|
6232
|
+
const store = ref.current;
|
|
6233
|
+
React8.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
|
|
6234
|
+
const make = React8.useCallback(
|
|
6235
|
+
(kind) => (name, rules) => {
|
|
6236
|
+
if (rules !== void 0) store.setRule(name, rules);
|
|
6237
|
+
return buildBindings(store, name, kind, store.getFieldSnapshot(name));
|
|
6238
|
+
},
|
|
6239
|
+
[store]
|
|
6240
|
+
);
|
|
6241
|
+
return {
|
|
6242
|
+
store,
|
|
6243
|
+
values: store.values,
|
|
6244
|
+
errors: store.errors,
|
|
6245
|
+
touched: store.touched,
|
|
6246
|
+
submitted: store.submitted,
|
|
6247
|
+
isSubmitting: store.validating,
|
|
6248
|
+
isValid: store.isValid,
|
|
6249
|
+
getValue: store.getValue,
|
|
6250
|
+
getValues: store.getValues,
|
|
6251
|
+
setValue: (name, value) => store.setValue(name, value),
|
|
6252
|
+
setValues: (patch) => store.setValues(patch),
|
|
6253
|
+
setError: store.setError,
|
|
6254
|
+
validateField: (name) => store.validateField(name),
|
|
6255
|
+
validateAll: () => store.validateAll(),
|
|
6256
|
+
reset: store.reset,
|
|
6257
|
+
field: make("value"),
|
|
6258
|
+
fieldNative: make("native"),
|
|
6259
|
+
fieldChecked: make("checked"),
|
|
6260
|
+
fieldTarget: make("target")
|
|
6261
|
+
};
|
|
6262
|
+
}
|
|
6263
|
+
var FormContext = React8.createContext(null);
|
|
6264
|
+
function useFormStore() {
|
|
6265
|
+
const store = React8.useContext(FormContext);
|
|
6266
|
+
if (!store) {
|
|
6267
|
+
throw new Error("useFormStore must be used within a <Form>. Did you forget to wrap your fields?");
|
|
6268
|
+
}
|
|
6269
|
+
return store;
|
|
6270
|
+
}
|
|
6271
|
+
function Form({
|
|
6272
|
+
form,
|
|
6273
|
+
onFinish,
|
|
6274
|
+
onFinishFailed,
|
|
6275
|
+
action,
|
|
6276
|
+
children,
|
|
6277
|
+
...rest
|
|
6278
|
+
}) {
|
|
6279
|
+
const ref = React8.useRef(null);
|
|
6280
|
+
const bypass = React8.useRef(false);
|
|
6281
|
+
const handleSubmit = async (e) => {
|
|
6282
|
+
if (bypass.current) {
|
|
6283
|
+
bypass.current = false;
|
|
6284
|
+
return;
|
|
6285
|
+
}
|
|
6286
|
+
e.preventDefault();
|
|
6287
|
+
const store = form.store;
|
|
6288
|
+
store.setSubmitted(true);
|
|
6289
|
+
const errors = await store.validateAll();
|
|
6290
|
+
const hasError = Object.values(errors).some(Boolean);
|
|
6291
|
+
if (hasError) {
|
|
6292
|
+
onFinishFailed?.(errors, store.getValues());
|
|
6293
|
+
focusFirstError(ref.current, errors);
|
|
6294
|
+
return;
|
|
6295
|
+
}
|
|
6296
|
+
if (onFinish) {
|
|
6297
|
+
await onFinish(store.getValues());
|
|
6298
|
+
return;
|
|
6299
|
+
}
|
|
6300
|
+
if (typeof action === "function") {
|
|
6301
|
+
action(new FormData(ref.current));
|
|
6302
|
+
return;
|
|
6303
|
+
}
|
|
6304
|
+
if (typeof action === "string") {
|
|
6305
|
+
bypass.current = true;
|
|
6306
|
+
ref.current.requestSubmit();
|
|
6307
|
+
}
|
|
6308
|
+
};
|
|
6309
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FormContext.Provider, { value: form.store, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6310
|
+
"form",
|
|
6311
|
+
{
|
|
6312
|
+
ref,
|
|
6313
|
+
noValidate: true,
|
|
6314
|
+
action: typeof action === "string" ? action : void 0,
|
|
6315
|
+
onSubmit: handleSubmit,
|
|
6316
|
+
...rest,
|
|
6317
|
+
children
|
|
6318
|
+
}
|
|
6319
|
+
) });
|
|
6320
|
+
}
|
|
6321
|
+
function focusFirstError(formEl, errors) {
|
|
6322
|
+
if (!formEl) return;
|
|
6323
|
+
const firstName = Object.keys(errors).find((k) => errors[k]);
|
|
6324
|
+
if (!firstName) return;
|
|
6325
|
+
const el = formEl.querySelector(`[name="${CSS.escape(firstName)}"], #${CSS.escape(firstName)}`);
|
|
6326
|
+
el?.focus();
|
|
6327
|
+
}
|
|
6328
|
+
function useFormField(name, options = {}) {
|
|
6329
|
+
const store = useFormStore();
|
|
6330
|
+
const { kind = "value", rules } = options;
|
|
6331
|
+
if (rules !== void 0 && store.getRule(name) !== rules) store.setRule(name, rules);
|
|
6332
|
+
React8.useEffect(() => {
|
|
6333
|
+
return () => {
|
|
6334
|
+
if (rules !== void 0) store.removeRule(name);
|
|
6335
|
+
};
|
|
6336
|
+
}, [store, name]);
|
|
6337
|
+
const snap = React8.useSyncExternalStore(
|
|
6338
|
+
store.subscribe,
|
|
6339
|
+
() => store.getFieldSnapshot(name)
|
|
6340
|
+
);
|
|
6341
|
+
return buildBindings(store, name, kind, snap);
|
|
6342
|
+
}
|
|
6343
|
+
function FormField({ name, kind, rules, children }) {
|
|
6344
|
+
const field = useFormField(name, { kind, rules });
|
|
6345
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children(field) });
|
|
6346
|
+
}
|
|
6347
|
+
function useFieldArray(name) {
|
|
6348
|
+
const store = useFormStore();
|
|
6349
|
+
React8.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
|
|
6350
|
+
const arr = store.getValue(name) ?? [];
|
|
6351
|
+
const keys = store.getKeys(name);
|
|
6352
|
+
return {
|
|
6353
|
+
fields: arr.map((_, i) => ({ key: keys[i], name: `${name}.${i}`, index: i })),
|
|
6354
|
+
append: (item = {}) => store.arrayAppend(name, item),
|
|
6355
|
+
remove: (index) => store.arrayRemove(name, index),
|
|
6356
|
+
move: (from, to) => store.arrayMove(name, from, to),
|
|
6357
|
+
replace: (items) => store.setValue(name, items, { validate: false })
|
|
6358
|
+
};
|
|
6359
|
+
}
|
|
6360
|
+
|
|
5923
6361
|
Object.defineProperty(exports, "COLORS", {
|
|
5924
6362
|
enumerable: true,
|
|
5925
6363
|
get: function () { return chunk255PCZIW_cjs.colors_default; }
|
|
@@ -5952,8 +6390,14 @@ exports.Drawer = Drawer;
|
|
|
5952
6390
|
exports.Dropdown = Dropdown;
|
|
5953
6391
|
exports.FadingBase = FadingBase;
|
|
5954
6392
|
exports.Field = Field;
|
|
6393
|
+
exports.FieldHelpIcon = FieldHelpIcon;
|
|
6394
|
+
exports.FieldLabel = FieldLabel;
|
|
5955
6395
|
exports.FileInput = FileInput;
|
|
5956
6396
|
exports.Flex = Flex;
|
|
6397
|
+
exports.Form = Form;
|
|
6398
|
+
exports.FormContext = FormContext;
|
|
6399
|
+
exports.FormField = FormField;
|
|
6400
|
+
exports.FormStore = FormStore;
|
|
5957
6401
|
exports.Grid = Grid2;
|
|
5958
6402
|
exports.GridCard = GridCard;
|
|
5959
6403
|
exports.Icon = icons_default;
|
|
@@ -5996,6 +6440,13 @@ exports.TreeSelect = TreeSelect;
|
|
|
5996
6440
|
exports.Typography = Typography;
|
|
5997
6441
|
exports.Wizard = Wizard;
|
|
5998
6442
|
exports.fieldShell = fieldShell;
|
|
6443
|
+
exports.isRequired = isRequired;
|
|
6444
|
+
exports.patterns = patterns;
|
|
6445
|
+
exports.runFieldRules = runFieldRules;
|
|
6446
|
+
exports.useFieldArray = useFieldArray;
|
|
6447
|
+
exports.useForm = useForm;
|
|
6448
|
+
exports.useFormField = useFormField;
|
|
6449
|
+
exports.useFormStore = useFormStore;
|
|
5999
6450
|
exports.useNotification = useNotification;
|
|
6000
6451
|
//# sourceMappingURL=index.cjs.map
|
|
6001
6452
|
//# sourceMappingURL=index.cjs.map
|