@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.
@@ -1,3 +1,3 @@
1
- Generated lucide registry with 152 icons -> /home/runner/work/open-mercato/open-mercato/packages/ui/src/backend/icons/lucideRegistry.generated.tsx
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
@@ -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) setDynamicOptions((prev) => ({ ...prev, [f.id]: opts }));
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
- if (query === void 0 && !loaderChanged && Array.isArray(dynamicOptions[field.id])) {
2388
- return dynamicOptions[field.id];
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
- setDynamicOptions((prev) => ({
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 dynamicOptions[field.id] || builtin.options || EMPTY_OPTIONS;
2404
- }, [dynamicOptions]);
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: typeof builtin?.loadOptions === "function" ? async (query) => {
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: typeof builtin?.loadOptions === "function" ? async (query) => {
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