@open-mercato/ui 0.5.1-develop.2663.2c29774b5b → 0.5.1-develop.2681.c559bb2bc3

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.
Files changed (53) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/backend/CrudForm.js +187 -39
  3. package/dist/backend/CrudForm.js.map +2 -2
  4. package/dist/backend/Page.js +12 -4
  5. package/dist/backend/Page.js.map +2 -2
  6. package/dist/backend/confirm-dialog/ConfirmDialog.js +7 -4
  7. package/dist/backend/confirm-dialog/ConfirmDialog.js.map +2 -2
  8. package/dist/backend/crud/CollapsibleGroup.js +88 -0
  9. package/dist/backend/crud/CollapsibleGroup.js.map +7 -0
  10. package/dist/backend/crud/CollapsibleZoneLayout.js +178 -0
  11. package/dist/backend/crud/CollapsibleZoneLayout.js.map +7 -0
  12. package/dist/backend/crud/useGroupCollapse.js +24 -0
  13. package/dist/backend/crud/useGroupCollapse.js.map +7 -0
  14. package/dist/backend/crud/useGroupOrder.js +61 -0
  15. package/dist/backend/crud/useGroupOrder.js.map +7 -0
  16. package/dist/backend/crud/usePersistedBooleanFlag.js +29 -0
  17. package/dist/backend/crud/usePersistedBooleanFlag.js.map +7 -0
  18. package/dist/backend/crud/useZoneCollapse.js +24 -0
  19. package/dist/backend/crud/useZoneCollapse.js.map +7 -0
  20. package/dist/backend/detail/AttachmentsSection.js +77 -33
  21. package/dist/backend/detail/AttachmentsSection.js.map +2 -2
  22. package/dist/backend/detail/NotesSection.js +82 -6
  23. package/dist/backend/detail/NotesSection.js.map +2 -2
  24. package/dist/backend/icons/lucideRegistry.generated.js +16 -2
  25. package/dist/backend/icons/lucideRegistry.generated.js.map +2 -2
  26. package/dist/backend/inputs/SwitchableMarkdownInput.js +3 -1
  27. package/dist/backend/inputs/SwitchableMarkdownInput.js.map +2 -2
  28. package/dist/primitives/avatar.js +59 -0
  29. package/dist/primitives/avatar.js.map +7 -0
  30. package/package.json +3 -3
  31. package/src/backend/CrudForm.tsx +230 -21
  32. package/src/backend/Page.tsx +20 -4
  33. package/src/backend/__tests__/AttachmentsSection.test.tsx +82 -0
  34. package/src/backend/__tests__/CollapsibleZoneLayout.test.tsx +171 -0
  35. package/src/backend/__tests__/CrudForm.validation.test.tsx +4 -4
  36. package/src/backend/__tests__/NotesSection.test.tsx +63 -0
  37. package/src/backend/confirm-dialog/ConfirmDialog.tsx +9 -4
  38. package/src/backend/crud/CollapsibleGroup.tsx +111 -0
  39. package/src/backend/crud/CollapsibleZoneLayout.tsx +234 -0
  40. package/src/backend/crud/__tests__/useGroupCollapse.test.ts +38 -0
  41. package/src/backend/crud/__tests__/useGroupOrder.test.ts +63 -0
  42. package/src/backend/crud/__tests__/usePersistedBooleanFlag.test.ts +49 -0
  43. package/src/backend/crud/__tests__/useZoneCollapse.test.ts +31 -0
  44. package/src/backend/crud/useGroupCollapse.ts +22 -0
  45. package/src/backend/crud/useGroupOrder.ts +74 -0
  46. package/src/backend/crud/usePersistedBooleanFlag.ts +35 -0
  47. package/src/backend/crud/useZoneCollapse.ts +22 -0
  48. package/src/backend/detail/AttachmentsSection.tsx +81 -38
  49. package/src/backend/detail/NotesSection.tsx +99 -6
  50. package/src/backend/icons/lucideRegistry.generated.tsx +16 -2
  51. package/src/backend/inputs/SwitchableMarkdownInput.tsx +3 -1
  52. package/src/primitives/__tests__/avatar.test.tsx +64 -0
  53. package/src/primitives/avatar.tsx +75 -0
@@ -1,3 +1,3 @@
1
- Generated lucide registry with 127 icons -> /home/runner/work/open-mercato/open-mercato/packages/ui/src/backend/icons/lucideRegistry.generated.tsx
2
- Found 257 entry points
1
+ Generated lucide registry with 134 icons -> /home/runner/work/open-mercato/open-mercato/packages/ui/src/backend/icons/lucideRegistry.generated.tsx
2
+ Found 264 entry points
3
3
  ui built successfully
@@ -3,6 +3,9 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import Link from "next/link";
5
5
  import { useRouter } from "next/navigation";
6
+ import { DndContext, closestCenter, PointerSensor, KeyboardSensor, useSensor, useSensors } from "@dnd-kit/core";
7
+ import { SortableContext, verticalListSortingStrategy, useSortable } from "@dnd-kit/sortable";
8
+ import { CSS } from "@dnd-kit/utilities";
6
9
  import { DataLoader } from "../primitives/DataLoader.js";
7
10
  import { flash } from "./FlashMessages.js";
8
11
  import dynamic from "next/dynamic";
@@ -67,6 +70,8 @@ import { VersionHistoryAction } from "./version-history/VersionHistoryAction.js"
67
70
  import { parseBooleanWithDefault } from "@open-mercato/shared/lib/boolean";
68
71
  import { cn } from "@open-mercato/shared/lib/utils";
69
72
  import { useInjectionDataWidgets } from "./injection/useInjectionDataWidgets.js";
73
+ import { CollapsibleGroup } from "./crud/CollapsibleGroup.js";
74
+ import { useGroupOrder } from "./crud/useGroupOrder.js";
70
75
  import { InjectedField } from "./injection/InjectedField.js";
71
76
  import { evaluateInjectedVisibility } from "./injection/visibility-utils.js";
72
77
  import { ComponentReplacementHandles } from "@open-mercato/shared/modules/widgets/component-registry";
@@ -180,6 +185,16 @@ class FieldDefinitionsManagerErrorBoundary extends React.Component {
180
185
  return this.props.children;
181
186
  }
182
187
  }
188
+ function SortableGroupItem({ id, children, disabled }) {
189
+ const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id, disabled });
190
+ const style = {
191
+ transform: CSS.Transform.toString(transform),
192
+ transition,
193
+ opacity: isDragging ? 0.5 : 1,
194
+ position: "relative"
195
+ };
196
+ return /* @__PURE__ */ jsx("div", { ref: setNodeRef, style, ...attributes, ...listeners, children });
197
+ }
183
198
  function CrudForm({
184
199
  schema,
185
200
  fields,
@@ -205,6 +220,8 @@ function CrudForm({
205
220
  customEntity = false,
206
221
  embedded = false,
207
222
  hideFooterActions = false,
223
+ trackDirtyWhenEmbedded = false,
224
+ onDirtyChange,
208
225
  extraActions,
209
226
  versionHistory,
210
227
  contentHeader,
@@ -213,6 +230,8 @@ function CrudForm({
213
230
  customFieldsetBindings,
214
231
  injectionSpotId,
215
232
  replacementHandle,
233
+ collapsibleGroups,
234
+ sortableGroups,
216
235
  shouldBypassUnsavedChangesGuard
217
236
  }) {
218
237
  React.useEffect(() => {
@@ -262,6 +281,12 @@ function CrudForm({
262
281
  const [fieldsetEditorTarget, setFieldsetEditorTarget] = React.useState(null);
263
282
  const [isInDialog, setIsInDialog] = React.useState(false);
264
283
  const rootRef = React.useRef(null);
284
+ const collapsibleGroupsEnabled = Boolean(collapsibleGroups);
285
+ const collapsiblePageType = typeof collapsibleGroups === "object" ? collapsibleGroups.pageType : formId;
286
+ const collapsibleChevronPosition = typeof collapsibleGroups === "object" ? collapsibleGroups.chevronPosition : void 0;
287
+ const groupCollapseRefs = React.useRef(/* @__PURE__ */ new Map());
288
+ const sortableGroupsEnabled = Boolean(sortableGroups);
289
+ const sortablePageType = typeof sortableGroups === "object" ? sortableGroups.pageType : formId;
265
290
  const fieldsetManagerRef = React.useRef(null);
266
291
  const resolvedEntityIdsKey = React.useMemo(() => buildResolvedEntityIdsKey(entityId, entityIds), [entityId, entityIds]);
267
292
  const resolvedEntityIds = React.useMemo(
@@ -320,7 +345,7 @@ function CrudForm({
320
345
  shouldBypassUnsavedChangesGuardRef.current = shouldBypassUnsavedChangesGuard;
321
346
  }, [shouldBypassUnsavedChangesGuard]);
322
347
  React.useEffect(() => {
323
- if (embedded) {
348
+ if (embedded && !trackDirtyWhenEmbedded) {
324
349
  isDirtyRef.current = false;
325
350
  setHasUnsavedChanges(false);
326
351
  return;
@@ -335,7 +360,10 @@ function CrudForm({
335
360
  const dirty = currentSnapshot !== snapshot;
336
361
  isDirtyRef.current = dirty;
337
362
  setHasUnsavedChanges(dirty);
338
- }, [embedded, values]);
363
+ }, [embedded, trackDirtyWhenEmbedded, values]);
364
+ React.useEffect(() => {
365
+ onDirtyChange?.(hasUnsavedChanges);
366
+ }, [hasUnsavedChanges, onDirtyChange]);
339
367
  const allowNextNavigation = React.useCallback(() => {
340
368
  navigationPromptBypassRef.current = true;
341
369
  if (typeof window !== "undefined") {
@@ -389,7 +417,7 @@ function CrudForm({
389
417
  }
390
418
  }, [allowNextNavigation, confirm, t]);
391
419
  React.useEffect(() => {
392
- if (embedded || !hasUnsavedChanges) return;
420
+ if (embedded && !trackDirtyWhenEmbedded || !hasUnsavedChanges) return;
393
421
  const beforeUnloadHandler = (event) => {
394
422
  if (!isDirtyRef.current) return;
395
423
  event.preventDefault();
@@ -463,7 +491,7 @@ function CrudForm({
463
491
  window.history.pushState = originalPushState;
464
492
  window.history.replaceState = originalReplaceState;
465
493
  };
466
- }, [allowNextNavigation, clearDirtyState, confirmUnsavedChanges, embedded, hasUnsavedChanges, router]);
494
+ }, [allowNextNavigation, clearDirtyState, confirmUnsavedChanges, embedded, hasUnsavedChanges, router, trackDirtyWhenEmbedded]);
467
495
  const { widgets: injectionWidgets } = useInjectionWidgets(resolvedInjectionSpotId, {
468
496
  context: injectionContext,
469
497
  triggerOnLoad: true
@@ -1241,6 +1269,33 @@ function CrudForm({
1241
1269
  return [...baseGroups.length ? baseGroups : autoGroup, ...injectionGroupCards];
1242
1270
  }, [allFields, groupsWithInjectedFields, injectionGroupCards, shouldAutoGroup]);
1243
1271
  const useGroupedLayout = resolvedGroupsForLayout.length > 0;
1272
+ const defaultGroupIds = React.useMemo(() => resolvedGroupsForLayout.map((g) => g.id), [resolvedGroupsForLayout]);
1273
+ const { orderedIds: sortedGroupIds, reorder: reorderGroups } = useGroupOrder(
1274
+ sortablePageType,
1275
+ defaultGroupIds
1276
+ );
1277
+ const sortableSensors = useSensors(
1278
+ useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
1279
+ useSensor(KeyboardSensor)
1280
+ );
1281
+ const handleGroupDragEnd = React.useCallback((event) => {
1282
+ const { active, over } = event;
1283
+ if (!over || active.id === over.id) return;
1284
+ const oldIndex = sortedGroupIds.indexOf(String(active.id));
1285
+ const newIndex = sortedGroupIds.indexOf(String(over.id));
1286
+ if (oldIndex !== -1 && newIndex !== -1) reorderGroups(oldIndex, newIndex);
1287
+ }, [sortedGroupIds, reorderGroups]);
1288
+ React.useEffect(() => {
1289
+ if (!collapsibleGroupsEnabled || Object.keys(errors).length === 0) return;
1290
+ const errorFieldIds = new Set(Object.keys(errors));
1291
+ for (const g of resolvedGroupsForLayout) {
1292
+ const groupFieldIds = (g.fields ?? []).map((f) => typeof f === "string" ? f : f.id);
1293
+ const hasError = groupFieldIds.some((id) => errorFieldIds.has(id));
1294
+ if (hasError) {
1295
+ groupCollapseRefs.current.get(g.id)?.expand();
1296
+ }
1297
+ }
1298
+ }, [errors, collapsibleGroupsEnabled, resolvedGroupsForLayout]);
1244
1299
  const stackedInjectionWidgets = React.useMemo(
1245
1300
  () => (injectionWidgets ?? []).filter((widget) => (widget.placement?.kind ?? "stack") === "stack"),
1246
1301
  [injectionWidgets]
@@ -2149,39 +2204,104 @@ function CrudForm({
2149
2204
  );
2150
2205
  }, [formReadOnly, handleReadOnlyFocusCapture, handleReadOnlyKeyDownCapture, readOnlyOverlay]);
2151
2206
  if (useGroupedLayout) {
2207
+ const sortedGroups = sortableGroupsEnabled ? [...resolvedGroupsForLayout].sort((a, b) => {
2208
+ const ai = sortedGroupIds.indexOf(a.id);
2209
+ const bi = sortedGroupIds.indexOf(b.id);
2210
+ return (ai === -1 ? 999 : ai) - (bi === -1 ? 999 : bi);
2211
+ }) : resolvedGroupsForLayout;
2152
2212
  const col1 = [];
2153
2213
  const col2 = [];
2154
- for (const g of resolvedGroupsForLayout) {
2214
+ for (const g of sortedGroups) {
2155
2215
  if ((g.column ?? 1) === 2) col2.push(g);
2156
2216
  else col1.push(g);
2157
2217
  }
2218
+ const col1Ids = col1.map((g) => g.id);
2158
2219
  const renderGroupedCards = (items) => {
2159
2220
  const nodes = [];
2160
2221
  for (const g of items) {
2161
2222
  const isCustomFieldsGroup = g.kind === "customFields";
2162
2223
  if (isCustomFieldsGroup) {
2163
2224
  if (isLoadingCustomFields) {
2164
- nodes.push(
2165
- /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card p-4", children: /* @__PURE__ */ jsx(
2166
- DataLoader,
2167
- {
2168
- isLoading: true,
2169
- loadingMessage: resolvedCustomFieldsLoadingMessage,
2170
- spinnerSize: "md",
2171
- className: "min-h-[1px]",
2172
- children: /* @__PURE__ */ jsx("div", {})
2173
- }
2174
- ) }, `${g.id}-loading`)
2175
- );
2225
+ const loadingContent = /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card p-4", children: /* @__PURE__ */ jsx(
2226
+ DataLoader,
2227
+ {
2228
+ isLoading: true,
2229
+ loadingMessage: resolvedCustomFieldsLoadingMessage,
2230
+ spinnerSize: "md",
2231
+ className: "min-h-[1px]",
2232
+ children: /* @__PURE__ */ jsx("div", {})
2233
+ }
2234
+ ) }, `${g.id}-loading`);
2235
+ if (collapsibleGroupsEnabled && g.title) {
2236
+ nodes.push(
2237
+ /* @__PURE__ */ jsx(
2238
+ CollapsibleGroup,
2239
+ {
2240
+ groupId: g.id,
2241
+ title: t(g.title, g.title),
2242
+ pageType: collapsiblePageType,
2243
+ chevronPosition: collapsibleChevronPosition,
2244
+ children: loadingContent
2245
+ },
2246
+ `${g.id}-loading-collapsible`
2247
+ )
2248
+ );
2249
+ } else {
2250
+ nodes.push(loadingContent);
2251
+ }
2176
2252
  continue;
2177
2253
  }
2254
+ const customFieldsInnerNodes = [];
2178
2255
  if (g.component) {
2179
- nodes.push(
2256
+ customFieldsInnerNodes.push(
2180
2257
  /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card px-4 py-3", children: g.component({ values, setValue, errors }) }, `${g.id}-component`)
2181
2258
  );
2182
2259
  }
2183
2260
  const renderedSections = renderCustomFieldsContent();
2184
- if (renderedSections.length) nodes.push(...renderedSections);
2261
+ if (renderedSections.length) customFieldsInnerNodes.push(...renderedSections);
2262
+ if (collapsibleGroupsEnabled && g.title) {
2263
+ const customFieldCount = customFieldLayout.reduce(
2264
+ (sum, entity) => sum + entity.sections.reduce(
2265
+ (sSum, section) => sSum + section.groups.reduce(
2266
+ (gSum, group) => gSum + group.fields.length,
2267
+ 0
2268
+ ),
2269
+ 0
2270
+ ),
2271
+ 0
2272
+ );
2273
+ const customFieldErrors = customFieldLayout.reduce(
2274
+ (sum, entity) => sum + entity.sections.reduce(
2275
+ (sSum, section) => sSum + section.groups.reduce(
2276
+ (gSum, group) => gSum + group.fields.filter((f) => errors[f.id]).length,
2277
+ 0
2278
+ ),
2279
+ 0
2280
+ ),
2281
+ 0
2282
+ );
2283
+ nodes.push(
2284
+ /* @__PURE__ */ jsx(
2285
+ CollapsibleGroup,
2286
+ {
2287
+ ref: (handle) => {
2288
+ if (handle) groupCollapseRefs.current.set(g.id, handle);
2289
+ else groupCollapseRefs.current.delete(g.id);
2290
+ },
2291
+ groupId: g.id,
2292
+ title: t(g.title, g.title),
2293
+ pageType: collapsiblePageType,
2294
+ errorCount: customFieldErrors,
2295
+ fieldCount: customFieldCount,
2296
+ chevronPosition: collapsibleChevronPosition,
2297
+ children: /* @__PURE__ */ jsx("div", { className: "space-y-3", children: customFieldsInnerNodes })
2298
+ },
2299
+ g.id
2300
+ )
2301
+ );
2302
+ } else {
2303
+ nodes.push(...customFieldsInnerNodes);
2304
+ }
2185
2305
  continue;
2186
2306
  }
2187
2307
  const componentNode = g.component ? g.component({ values, setValue, errors }) : null;
@@ -2192,28 +2312,56 @@ function CrudForm({
2192
2312
  continue;
2193
2313
  }
2194
2314
  const groupFields = resolveGroupFields(g);
2195
- nodes.push(
2196
- /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card px-4 py-3 space-y-3", children: [
2197
- g.title ? /* @__PURE__ */ jsx("div", { className: "text-sm font-medium", children: t(g.title, g.title) }) : null,
2198
- g.description ? /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: t(g.description, g.description) }) : null,
2199
- componentNode ? /* @__PURE__ */ jsx("div", { children: componentNode }) : null,
2315
+ const groupFieldIds = (g.fields ?? []).map((f) => typeof f === "string" ? f : f.id);
2316
+ const groupErrorCount = groupFieldIds.filter((id) => errors[id]).length;
2317
+ const groupContent = /* @__PURE__ */ jsxs(Fragment, { children: [
2318
+ g.description ? /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: t(g.description, g.description) }) : null,
2319
+ componentNode ? /* @__PURE__ */ jsx("div", { children: componentNode }) : null,
2320
+ /* @__PURE__ */ jsx(
2321
+ DataLoader,
2322
+ {
2323
+ isLoading: false,
2324
+ loadingMessage: resolvedLoadingMessage,
2325
+ spinnerSize: "md",
2326
+ className: "min-h-[1px]",
2327
+ children: groupFields.length > 0 ? renderFields(groupFields) : /* @__PURE__ */ jsx("div", { className: "min-h-[1px]" })
2328
+ }
2329
+ )
2330
+ ] });
2331
+ if (collapsibleGroupsEnabled && g.title) {
2332
+ nodes.push(
2200
2333
  /* @__PURE__ */ jsx(
2201
- DataLoader,
2334
+ CollapsibleGroup,
2202
2335
  {
2203
- isLoading: false,
2204
- loadingMessage: resolvedLoadingMessage,
2205
- spinnerSize: "md",
2206
- className: "min-h-[1px]",
2207
- children: groupFields.length > 0 ? renderFields(groupFields) : /* @__PURE__ */ jsx("div", { className: "min-h-[1px]" })
2208
- }
2336
+ ref: (handle) => {
2337
+ if (handle) groupCollapseRefs.current.set(g.id, handle);
2338
+ else groupCollapseRefs.current.delete(g.id);
2339
+ },
2340
+ groupId: g.id,
2341
+ title: t(g.title, g.title),
2342
+ pageType: collapsiblePageType,
2343
+ errorCount: groupErrorCount,
2344
+ fieldCount: groupFields.length,
2345
+ chevronPosition: collapsibleChevronPosition,
2346
+ children: /* @__PURE__ */ jsx("div", { className: "space-y-3", children: groupContent })
2347
+ },
2348
+ g.id
2209
2349
  )
2210
- ] }, g.id)
2211
- );
2350
+ );
2351
+ } else {
2352
+ nodes.push(
2353
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card px-4 py-3 space-y-3", children: [
2354
+ g.title ? /* @__PURE__ */ jsx("div", { className: "text-sm font-medium", children: t(g.title, g.title) }) : null,
2355
+ groupContent
2356
+ ] }, g.id)
2357
+ );
2358
+ }
2212
2359
  }
2213
2360
  return nodes;
2214
2361
  };
2215
- const col1Content = renderGroupedCards(col1);
2362
+ const col1Nodes = renderGroupedCards(col1);
2216
2363
  const col2Content = renderGroupedCards(col2);
2364
+ const col1Content = sortableGroupsEnabled ? col1Nodes.map((node, i) => /* @__PURE__ */ jsx(SortableGroupItem, { id: col1[i]?.id ?? String(i), children: node }, col1[i]?.id ?? i)) : col1Nodes;
2217
2365
  const hasSecondaryColumn = col2Content.length > 0;
2218
2366
  return /* @__PURE__ */ jsxs("div", { className: "space-y-4", ref: rootRef, "data-component-handle": resolvedReplacementHandle, children: [
2219
2367
  !embedded ? /* @__PURE__ */ jsx(
@@ -2261,12 +2409,12 @@ function CrudForm({
2261
2409
  {
2262
2410
  className: hasSecondaryColumn ? "grid grid-cols-1 lg:grid-cols-[7fr_3fr] gap-4" : "grid grid-cols-1 gap-4",
2263
2411
  children: [
2264
- /* @__PURE__ */ jsx("div", { className: "space-y-3", children: col1Content }),
2412
+ sortableGroupsEnabled ? /* @__PURE__ */ jsx(DndContext, { sensors: sortableSensors, collisionDetection: closestCenter, onDragEnd: handleGroupDragEnd, children: /* @__PURE__ */ jsx(SortableContext, { items: col1Ids, strategy: verticalListSortingStrategy, children: /* @__PURE__ */ jsx("div", { className: "space-y-3", children: col1Content }) }) }) : /* @__PURE__ */ jsx("div", { className: "space-y-3", children: col1Content }),
2265
2413
  hasSecondaryColumn ? /* @__PURE__ */ jsx("div", { className: "space-y-3", children: col2Content }) : null
2266
2414
  ]
2267
2415
  }
2268
2416
  ),
2269
- formError && !Object.keys(errors).length ? /* @__PURE__ */ jsx("div", { className: "text-sm text-red-600", children: formError }) : null,
2417
+ formError && !Object.keys(errors).length ? /* @__PURE__ */ jsx("div", { className: "text-sm text-status-error-text", children: formError }) : null,
2270
2418
  hideFooterActions || formReadOnly ? null : /* @__PURE__ */ jsx(
2271
2419
  FormFooter,
2272
2420
  {
@@ -2362,7 +2510,7 @@ function CrudForm({
2362
2510
  f.id
2363
2511
  );
2364
2512
  }) }),
2365
- formError && !Object.keys(errors).length ? /* @__PURE__ */ jsx("div", { className: "text-sm text-red-600", children: formError }) : null,
2513
+ formError && !Object.keys(errors).length ? /* @__PURE__ */ jsx("div", { className: "text-sm text-status-error-text", children: formError }) : null,
2366
2514
  hideFooterActions || formReadOnly ? null : /* @__PURE__ */ jsx(
2367
2515
  FormFooter,
2368
2516
  {
@@ -2962,7 +3110,7 @@ const FieldControl = React.memo(
2962
3110
  children: [
2963
3111
  field.type !== "checkbox" && field.label.trim().length > 0 ? /* @__PURE__ */ jsxs("label", { className: "block text-sm font-medium", children: [
2964
3112
  field.label,
2965
- field.required ? /* @__PURE__ */ jsx("span", { className: "text-red-600", children: " *" }) : null
3113
+ field.required ? /* @__PURE__ */ jsx("span", { className: "text-status-error-text", children: " *" }) : null
2966
3114
  ] }) : null,
2967
3115
  field.type === "text" && /* @__PURE__ */ jsx(
2968
3116
  TextInput,
@@ -3194,7 +3342,7 @@ const FieldControl = React.memo(
3194
3342
  /* @__PURE__ */ jsx(Info, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }),
3195
3343
  /* @__PURE__ */ jsx("div", { children: field.description })
3196
3344
  ] }) : null,
3197
- error ? /* @__PURE__ */ jsx("div", { className: "text-xs text-red-600", children: error }) : null
3345
+ error ? /* @__PURE__ */ jsx("div", { className: "text-xs text-status-error-text", children: error }) : null
3198
3346
  ]
3199
3347
  }
3200
3348
  );