@open-mercato/ui 0.6.8-develop.6998.1.d2bc46c56c → 0.6.8-develop.7003.1.24fef49d48
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/.turbo/turbo-build.log +1 -1
- package/dist/backend/CrudForm.js +30 -19
- package/dist/backend/CrudForm.js.map +2 -2
- package/dist/backend/icons/lucideRegistry.generated.js +16 -2
- package/dist/backend/icons/lucideRegistry.generated.js.map +2 -2
- package/dist/backend/inputs/ComboboxInput.js +34 -27
- package/dist/backend/inputs/ComboboxInput.js.map +2 -2
- package/package.json +3 -3
- package/src/backend/CrudForm.tsx +41 -31
- package/src/backend/icons/lucideRegistry.generated.tsx +14 -0
- package/src/backend/inputs/ComboboxInput.tsx +11 -4
- package/src/backend/inputs/__tests__/ComboboxInput.test.tsx +21 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
Generated lucide registry with
|
|
1
|
+
Generated lucide registry with 159 icons -> /home/runner/work/open-mercato/open-mercato/packages/ui/src/backend/icons/lucideRegistry.generated.tsx
|
|
2
2
|
[build:ui] found 400 entry points
|
|
3
3
|
[build:ui] built successfully
|
package/dist/backend/CrudForm.js
CHANGED
|
@@ -105,6 +105,11 @@ import { RichEditor } from "../primitives/rich-editor.js";
|
|
|
105
105
|
import MarkdownField from "./inputs/MarkdownField.js";
|
|
106
106
|
const logger = createLogger("ui").child({ component: "CrudForm" });
|
|
107
107
|
const EMPTY_OPTIONS = [];
|
|
108
|
+
function areOptionListsEqual(a, b) {
|
|
109
|
+
if (a === b) return true;
|
|
110
|
+
if (a.length !== b.length) return false;
|
|
111
|
+
return a.every((option, index) => option.value === b[index].value && option.label === b[index].label);
|
|
112
|
+
}
|
|
108
113
|
const SELECT_CLEAR_SENTINEL = "__crudform_select_clear__";
|
|
109
114
|
const FOCUSABLE_SELECTOR = '[data-crud-focus-target], input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
110
115
|
const CRUDFORM_EXTENDED_EVENTS_ENABLED = parseBooleanWithDefault(
|
|
@@ -2338,7 +2343,7 @@ function CrudForm({
|
|
|
2338
2343
|
if (!displayMessage) {
|
|
2339
2344
|
displayMessage = hasFieldErrors ? highlightedMessage : saveErrorMessage;
|
|
2340
2345
|
}
|
|
2341
|
-
displayMessage = parseServerMessage(displayMessage);
|
|
2346
|
+
displayMessage = translateValidationMessage(parseServerMessage(displayMessage));
|
|
2342
2347
|
if (optimisticLockConflict) {
|
|
2343
2348
|
try {
|
|
2344
2349
|
surfaceRecordConflict(err, t);
|
|
@@ -2356,6 +2361,13 @@ function CrudForm({
|
|
|
2356
2361
|
}
|
|
2357
2362
|
};
|
|
2358
2363
|
const dynamicOptionLoadersRef = React.useRef(/* @__PURE__ */ new Map());
|
|
2364
|
+
const dynamicOptionsRef = React.useRef({});
|
|
2365
|
+
const storeDynamicOptions = React.useCallback((fieldId, fetched) => {
|
|
2366
|
+
const current = dynamicOptionsRef.current[fieldId];
|
|
2367
|
+
if (current && areOptionListsEqual(current, fetched)) return;
|
|
2368
|
+
dynamicOptionsRef.current = { ...dynamicOptionsRef.current, [fieldId]: fetched };
|
|
2369
|
+
setDynamicOptions(dynamicOptionsRef.current);
|
|
2370
|
+
}, []);
|
|
2359
2371
|
React.useEffect(() => {
|
|
2360
2372
|
let cancelled = false;
|
|
2361
2373
|
const loadAll = async () => {
|
|
@@ -2365,7 +2377,7 @@ function CrudForm({
|
|
|
2365
2377
|
try {
|
|
2366
2378
|
dynamicOptionLoadersRef.current.set(f.id, f.loadOptions);
|
|
2367
2379
|
const opts = await f.loadOptions();
|
|
2368
|
-
if (!cancelled)
|
|
2380
|
+
if (!cancelled) storeDynamicOptions(f.id, opts);
|
|
2369
2381
|
} catch {
|
|
2370
2382
|
}
|
|
2371
2383
|
});
|
|
@@ -2375,7 +2387,7 @@ function CrudForm({
|
|
|
2375
2387
|
return () => {
|
|
2376
2388
|
cancelled = true;
|
|
2377
2389
|
};
|
|
2378
|
-
}, [dynamicOptionLoaderKey]);
|
|
2390
|
+
}, [dynamicOptionLoaderKey, storeDynamicOptions]);
|
|
2379
2391
|
const loadFieldOptions = React.useCallback(async (field, query) => {
|
|
2380
2392
|
if (!("type" in field) || field.type === "custom") return EMPTY_OPTIONS;
|
|
2381
2393
|
const builtin = field;
|
|
@@ -2384,24 +2396,22 @@ function CrudForm({
|
|
|
2384
2396
|
const previousLoader = dynamicOptionLoadersRef.current.get(field.id);
|
|
2385
2397
|
const loaderChanged = previousLoader !== loader;
|
|
2386
2398
|
dynamicOptionLoadersRef.current.set(field.id, loader);
|
|
2387
|
-
|
|
2388
|
-
|
|
2399
|
+
const cached = dynamicOptionsRef.current[field.id];
|
|
2400
|
+
if (query === void 0 && !loaderChanged && Array.isArray(cached)) {
|
|
2401
|
+
return cached;
|
|
2389
2402
|
}
|
|
2390
2403
|
try {
|
|
2391
2404
|
const fetched = await loader(query);
|
|
2392
2405
|
if (query === void 0) {
|
|
2393
|
-
|
|
2394
|
-
...prev,
|
|
2395
|
-
[field.id]: fetched
|
|
2396
|
-
}));
|
|
2406
|
+
storeDynamicOptions(field.id, fetched);
|
|
2397
2407
|
}
|
|
2398
2408
|
return fetched;
|
|
2399
2409
|
} catch {
|
|
2400
2410
|
return builtin.options ?? EMPTY_OPTIONS;
|
|
2401
2411
|
}
|
|
2402
2412
|
}
|
|
2403
|
-
return
|
|
2404
|
-
}, [
|
|
2413
|
+
return dynamicOptionsRef.current[field.id] || builtin.options || EMPTY_OPTIONS;
|
|
2414
|
+
}, [storeDynamicOptions]);
|
|
2405
2415
|
const fieldOptionsById = React.useMemo(() => {
|
|
2406
2416
|
const map = new globalThis.Map();
|
|
2407
2417
|
for (const f of allFields) {
|
|
@@ -3447,6 +3457,13 @@ const FieldControl = React.memo(
|
|
|
3447
3457
|
loadFieldOptions(field).catch(() => {
|
|
3448
3458
|
});
|
|
3449
3459
|
}, [field, hasLoader, loadFieldOptions]);
|
|
3460
|
+
const loadFieldSuggestions = React.useMemo(() => {
|
|
3461
|
+
if (!hasLoader) return void 0;
|
|
3462
|
+
return async (query) => {
|
|
3463
|
+
const opts = await loadFieldOptions(field, query);
|
|
3464
|
+
return opts.map((opt) => ({ value: opt.value, label: opt.label }));
|
|
3465
|
+
};
|
|
3466
|
+
}, [field, hasLoader, loadFieldOptions]);
|
|
3450
3467
|
const placeholder = builtin?.placeholder;
|
|
3451
3468
|
const rootClassName = wrapperClassName ? `space-y-1 ${wrapperClassName}` : "space-y-1";
|
|
3452
3469
|
const validateOnWrapperBlur = supportsWrapperBlurValidation(field);
|
|
@@ -3604,10 +3621,7 @@ const FieldControl = React.memo(
|
|
|
3604
3621
|
autoFocus: autoFocusField,
|
|
3605
3622
|
suppressInitialSuggestionsOnFocus: autoFocusField,
|
|
3606
3623
|
suggestions: options.map((opt) => ({ value: opt.value, label: opt.label })),
|
|
3607
|
-
loadSuggestions:
|
|
3608
|
-
const opts = await loadFieldOptions(field, query);
|
|
3609
|
-
return opts.map((opt) => ({ value: opt.value, label: opt.label }));
|
|
3610
|
-
} : void 0
|
|
3624
|
+
loadSuggestions: loadFieldSuggestions
|
|
3611
3625
|
}
|
|
3612
3626
|
),
|
|
3613
3627
|
field.type === "combobox" && /* @__PURE__ */ jsx(
|
|
@@ -3620,10 +3634,7 @@ const FieldControl = React.memo(
|
|
|
3620
3634
|
suggestions: builtin?.suggestions ? builtin.suggestions : options.map((opt) => ({ value: opt.value, label: opt.label })),
|
|
3621
3635
|
seedOptions: builtin?.seedOptions ? builtin.seedOptions.map((opt) => ({ value: opt.value, label: opt.label })) : void 0,
|
|
3622
3636
|
resolveLabel: builtin?.resolveLabel,
|
|
3623
|
-
loadSuggestions:
|
|
3624
|
-
const opts = await loadFieldOptions(field, query);
|
|
3625
|
-
return opts.map((opt) => ({ value: opt.value, label: opt.label }));
|
|
3626
|
-
} : void 0,
|
|
3637
|
+
loadSuggestions: loadFieldSuggestions,
|
|
3627
3638
|
allowCustomValues: builtin?.allowCustomValues ?? true,
|
|
3628
3639
|
clearable: !field.required,
|
|
3629
3640
|
disabled
|