@open-mercato/ui 0.6.6-develop.6241.1.47c01ad4ed → 0.6.6-develop.6246.1.85fd30c705
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/backend/custom-fields/FieldDefinitionsEditor.js +336 -385
- package/dist/backend/custom-fields/FieldDefinitionsEditor.js.map +2 -2
- package/package.json +3 -3
- package/src/backend/__tests__/FieldDefinitionsEditor.test.tsx +17 -0
- package/src/backend/custom-fields/FieldDefinitionsEditor.tsx +172 -181
|
@@ -3,7 +3,10 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Cog, GripVertical, Languages, Pencil, Plus, Trash2 } from "lucide-react";
|
|
5
5
|
import { Button } from "../../primitives/button.js";
|
|
6
|
+
import { CheckboxField } from "../../primitives/checkbox-field.js";
|
|
7
|
+
import { FormField } from "../../primitives/form-field.js";
|
|
6
8
|
import { IconButton } from "../../primitives/icon-button.js";
|
|
9
|
+
import { Input } from "../../primitives/input.js";
|
|
7
10
|
import {
|
|
8
11
|
Select,
|
|
9
12
|
SelectContent,
|
|
@@ -30,6 +33,15 @@ const DEFAULT_KIND_OPTIONS = CUSTOM_FIELD_KINDS.map((k) => ({
|
|
|
30
33
|
value: k,
|
|
31
34
|
label: k.charAt(0).toUpperCase() + k.slice(1)
|
|
32
35
|
}));
|
|
36
|
+
const DEFAULT_VALUE_NONE = "__open_mercato_no_default__";
|
|
37
|
+
function getDefaultValueNoneOptionValue(options) {
|
|
38
|
+
const optionValues = new Set(options.map((option) => String(option.value)));
|
|
39
|
+
let candidate = DEFAULT_VALUE_NONE;
|
|
40
|
+
while (optionValues.has(candidate)) {
|
|
41
|
+
candidate = `${candidate}_`;
|
|
42
|
+
}
|
|
43
|
+
return candidate;
|
|
44
|
+
}
|
|
33
45
|
const FIELDSET_ICON_OPTIONS = [
|
|
34
46
|
{ value: "layers", label: "Layers" },
|
|
35
47
|
{ value: "tag", label: "Tag" },
|
|
@@ -271,70 +283,59 @@ function FieldDefinitionsEditor({
|
|
|
271
283
|
)
|
|
272
284
|
] }),
|
|
273
285
|
resolvedActiveFieldset && activeFieldsetConfig ? /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-4 gap-3", children: [
|
|
274
|
-
/* @__PURE__ */
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
"
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
313
|
-
/* @__PURE__ */ jsx("label", { className: "text-xs", children: "Description" }),
|
|
314
|
-
/* @__PURE__ */ jsx(
|
|
315
|
-
"input",
|
|
316
|
-
{
|
|
317
|
-
className: "border rounded w-full px-2 py-1 text-sm",
|
|
318
|
-
value: activeFieldsetConfig.description ?? "",
|
|
319
|
-
onChange: (event) => handleFieldsetPatch(activeFieldsetConfig.code, { description: event.target.value })
|
|
320
|
-
}
|
|
321
|
-
)
|
|
322
|
-
] })
|
|
286
|
+
/* @__PURE__ */ jsx(FormField, { label: "Code", children: /* @__PURE__ */ jsx(
|
|
287
|
+
Input,
|
|
288
|
+
{
|
|
289
|
+
size: "sm",
|
|
290
|
+
inputClassName: "font-mono",
|
|
291
|
+
value: activeFieldsetConfig.code,
|
|
292
|
+
onChange: (event) => handleFieldsetCodeInput(activeFieldsetConfig.code, event.target.value)
|
|
293
|
+
}
|
|
294
|
+
) }),
|
|
295
|
+
/* @__PURE__ */ jsx(FormField, { label: "Label", children: /* @__PURE__ */ jsx(
|
|
296
|
+
Input,
|
|
297
|
+
{
|
|
298
|
+
size: "sm",
|
|
299
|
+
value: activeFieldsetConfig.label,
|
|
300
|
+
onChange: (event) => handleFieldsetPatch(activeFieldsetConfig.code, { label: event.target.value })
|
|
301
|
+
}
|
|
302
|
+
) }),
|
|
303
|
+
/* @__PURE__ */ jsx(FormField, { label: "Icon", children: /* @__PURE__ */ jsxs(
|
|
304
|
+
Select,
|
|
305
|
+
{
|
|
306
|
+
value: activeFieldsetConfig.icon || void 0,
|
|
307
|
+
onValueChange: (value) => handleFieldsetPatch(activeFieldsetConfig.code, {
|
|
308
|
+
icon: value || void 0
|
|
309
|
+
}),
|
|
310
|
+
children: [
|
|
311
|
+
/* @__PURE__ */ jsx(SelectTrigger, { size: "sm", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Default" }) }),
|
|
312
|
+
/* @__PURE__ */ jsx(SelectContent, { children: FIELDSET_ICON_OPTIONS.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
313
|
+
]
|
|
314
|
+
}
|
|
315
|
+
) }),
|
|
316
|
+
/* @__PURE__ */ jsx(FormField, { label: "Description", children: /* @__PURE__ */ jsx(
|
|
317
|
+
Input,
|
|
318
|
+
{
|
|
319
|
+
size: "sm",
|
|
320
|
+
value: activeFieldsetConfig.description ?? "",
|
|
321
|
+
onChange: (event) => handleFieldsetPatch(activeFieldsetConfig.code, { description: event.target.value })
|
|
322
|
+
}
|
|
323
|
+
) })
|
|
323
324
|
] }) : null,
|
|
324
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2
|
|
325
|
-
/* @__PURE__ */
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
!canToggleSingleFieldset ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "(add at least two fieldsets to toggle)" }) : null
|
|
325
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
326
|
+
/* @__PURE__ */ jsx(
|
|
327
|
+
CheckboxField,
|
|
328
|
+
{
|
|
329
|
+
size: "sm",
|
|
330
|
+
disabled: !canToggleSingleFieldset,
|
|
331
|
+
checked: singleFieldsetChecked,
|
|
332
|
+
onCheckedChange: (checked) => onSingleFieldsetPerRecordChange?.(checked === true),
|
|
333
|
+
label: "Single fieldset per entity",
|
|
334
|
+
containerClassName: "text-xs",
|
|
335
|
+
contentClassName: "gap-1 [&_label]:text-xs [&_label]:font-normal"
|
|
336
|
+
}
|
|
337
|
+
),
|
|
338
|
+
!canToggleSingleFieldset ? /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "(add at least two fieldsets to toggle)" }) : null
|
|
338
339
|
] })
|
|
339
340
|
] }) : /* @__PURE__ */ jsxs("div", { className: "rounded border border-dashed bg-muted/30 p-4 text-sm text-muted-foreground flex flex-col gap-3", children: [
|
|
340
341
|
/* @__PURE__ */ jsx("div", { children: "No fieldsets defined yet. Fieldsets let you group custom fields for different variants of the same entity (e.g., Fashion vs. Sport products)." }),
|
|
@@ -351,7 +352,7 @@ function FieldDefinitionsEditor({
|
|
|
351
352
|
}
|
|
352
353
|
) })
|
|
353
354
|
] }),
|
|
354
|
-
orderNotice?.dirty && /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-sticky -mt-1 -mb-1", children: /* @__PURE__ */ jsx("div", { className: "inline-flex items-center gap-2 text-xs px-2 py-1 rounded border bg-
|
|
355
|
+
orderNotice?.dirty && /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-sticky -mt-1 -mb-1", children: /* @__PURE__ */ jsx("div", { className: "inline-flex items-center gap-2 text-xs px-2 py-1 rounded border border-status-warning-border bg-status-warning-bg text-status-warning-text shadow-sm", children: orderNotice?.saving ? "Saving order\u2026" : orderNotice?.message ?? "Reordered \u2014 saving soon" }) }),
|
|
355
356
|
filteredDefinitions.map(({ definition, index }) => {
|
|
356
357
|
const assignedFieldset = typeof definition.configJson?.fieldset === "string" ? definition.configJson.fieldset : null;
|
|
357
358
|
const groupOptions = assignedFieldset ? fieldsets.find((fs) => fs.code === assignedFieldset)?.groups ?? [] : availableGroups;
|
|
@@ -432,7 +433,7 @@ function FieldDefinitionsEditor({
|
|
|
432
433
|
Button,
|
|
433
434
|
{
|
|
434
435
|
variant: "link",
|
|
435
|
-
className: "h-auto p-0
|
|
436
|
+
className: "h-auto p-0",
|
|
436
437
|
onClick: () => onRestoreField(key),
|
|
437
438
|
children: key
|
|
438
439
|
}
|
|
@@ -655,49 +656,48 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
|
|
|
655
656
|
"Drag to reorder"
|
|
656
657
|
] }),
|
|
657
658
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
658
|
-
/* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2 text-sm", children: [
|
|
659
|
-
/* @__PURE__ */ jsx("input", { type: "checkbox", checked: local.isActive !== false, onChange: (event) => {
|
|
660
|
-
apply({ isActive: event.target.checked }, true);
|
|
661
|
-
} }),
|
|
662
|
-
" Active"
|
|
663
|
-
] }),
|
|
664
|
-
onTranslate && /* @__PURE__ */ jsx(IconButton, { variant: "outline", size: "sm", onClick: onTranslate, "aria-label": "Translate field", children: /* @__PURE__ */ jsx(Languages, { className: "h-4 w-4" }) }),
|
|
665
|
-
/* @__PURE__ */ jsx(IconButton, { variant: "outline", size: "sm", onClick: onRemove, "aria-label": "Remove field", children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" }) })
|
|
666
|
-
] })
|
|
667
|
-
] }),
|
|
668
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-3 grid grid-cols-1 md:grid-cols-12 gap-3 items-center", children: [
|
|
669
|
-
/* @__PURE__ */ jsxs("div", { className: "md:col-span-6", children: [
|
|
670
|
-
/* @__PURE__ */ jsx("label", { className: "text-xs", children: "Key" }),
|
|
671
659
|
/* @__PURE__ */ jsx(
|
|
672
|
-
|
|
673
|
-
{
|
|
674
|
-
className: `rounded w-full px-2 py-1 text-sm font-mono ${error?.key ? "border-red-500 border" : "border"}`,
|
|
675
|
-
placeholder: "snake_case",
|
|
676
|
-
value: local.key,
|
|
677
|
-
onChange: (event) => apply({ key: event.target.value }),
|
|
678
|
-
onBlur: commit
|
|
679
|
-
}
|
|
680
|
-
),
|
|
681
|
-
error?.key ? /* @__PURE__ */ jsx("div", { className: "text-xs text-red-600 mt-1", children: error.key }) : null
|
|
682
|
-
] }),
|
|
683
|
-
/* @__PURE__ */ jsxs("div", { className: "md:col-span-6", children: [
|
|
684
|
-
/* @__PURE__ */ jsx("label", { className: "text-xs", children: "Kind" }),
|
|
685
|
-
/* @__PURE__ */ jsxs(
|
|
686
|
-
Select,
|
|
660
|
+
CheckboxField,
|
|
687
661
|
{
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
662
|
+
size: "sm",
|
|
663
|
+
checked: local.isActive !== false,
|
|
664
|
+
onCheckedChange: (checked) => {
|
|
665
|
+
apply({ isActive: checked === true }, true);
|
|
691
666
|
},
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
]
|
|
667
|
+
label: "Active",
|
|
668
|
+
containerClassName: "text-sm",
|
|
669
|
+
contentClassName: "gap-1 [&_label]:text-sm [&_label]:font-normal"
|
|
696
670
|
}
|
|
697
671
|
),
|
|
698
|
-
|
|
672
|
+
onTranslate && /* @__PURE__ */ jsx(IconButton, { variant: "outline", size: "sm", onClick: onTranslate, "aria-label": "Translate field", children: /* @__PURE__ */ jsx(Languages, { className: "h-4 w-4" }) }),
|
|
673
|
+
/* @__PURE__ */ jsx(IconButton, { variant: "outline", size: "sm", onClick: onRemove, "aria-label": "Remove field", children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" }) })
|
|
699
674
|
] })
|
|
700
675
|
] }),
|
|
676
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-3 grid grid-cols-1 md:grid-cols-12 gap-3 items-center", children: [
|
|
677
|
+
/* @__PURE__ */ jsx(FormField, { label: "Key", error: error?.key, className: "md:col-span-6", children: /* @__PURE__ */ jsx(
|
|
678
|
+
Input,
|
|
679
|
+
{
|
|
680
|
+
inputClassName: "font-mono",
|
|
681
|
+
placeholder: "snake_case",
|
|
682
|
+
value: local.key,
|
|
683
|
+
onChange: (event) => apply({ key: event.target.value }),
|
|
684
|
+
onBlur: commit
|
|
685
|
+
}
|
|
686
|
+
) }),
|
|
687
|
+
/* @__PURE__ */ jsx(FormField, { label: "Kind", error: error?.kind, className: "md:col-span-6", children: /* @__PURE__ */ jsxs(
|
|
688
|
+
Select,
|
|
689
|
+
{
|
|
690
|
+
value: local.kind || void 0,
|
|
691
|
+
onValueChange: (value) => {
|
|
692
|
+
apply({ kind: value ?? "" }, true);
|
|
693
|
+
},
|
|
694
|
+
children: [
|
|
695
|
+
/* @__PURE__ */ jsx(SelectTrigger, { "aria-invalid": !!error?.kind, children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
696
|
+
/* @__PURE__ */ jsx(SelectContent, { children: kindOptions.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
697
|
+
]
|
|
698
|
+
}
|
|
699
|
+
) })
|
|
700
|
+
] }),
|
|
701
701
|
allowFieldsetSelection ? /* @__PURE__ */ jsxs("div", { className: "mt-3 grid grid-cols-1 md:grid-cols-2 gap-3", children: [
|
|
702
702
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
703
703
|
/* @__PURE__ */ jsx("label", { className: "text-xs", children: "Assign to fieldset" }),
|
|
@@ -751,30 +751,22 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
|
|
|
751
751
|
] }) : null
|
|
752
752
|
] }) : null,
|
|
753
753
|
/* @__PURE__ */ jsxs("div", { className: "mt-3 grid grid-cols-1 md:grid-cols-2 gap-3", children: [
|
|
754
|
-
/* @__PURE__ */
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
"
|
|
758
|
-
{
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
{
|
|
771
|
-
className: "border rounded w-full px-2 py-1 text-sm",
|
|
772
|
-
value: typeof local.configJson?.description === "string" ? local.configJson.description : "",
|
|
773
|
-
onChange: (event) => apply({ configJson: { ...local.configJson || {}, description: event.target.value } }),
|
|
774
|
-
onBlur: commit
|
|
775
|
-
}
|
|
776
|
-
)
|
|
777
|
-
] }),
|
|
754
|
+
/* @__PURE__ */ jsx(FormField, { label: "Label", children: /* @__PURE__ */ jsx(
|
|
755
|
+
Input,
|
|
756
|
+
{
|
|
757
|
+
value: typeof local.configJson?.label === "string" ? local.configJson.label : "",
|
|
758
|
+
onChange: (event) => apply({ configJson: { ...local.configJson || {}, label: event.target.value } }),
|
|
759
|
+
onBlur: commit
|
|
760
|
+
}
|
|
761
|
+
) }),
|
|
762
|
+
/* @__PURE__ */ jsx(FormField, { label: "Description", children: /* @__PURE__ */ jsx(
|
|
763
|
+
Input,
|
|
764
|
+
{
|
|
765
|
+
value: typeof local.configJson?.description === "string" ? local.configJson.description : "",
|
|
766
|
+
onChange: (event) => apply({ configJson: { ...local.configJson || {}, description: event.target.value } }),
|
|
767
|
+
onBlur: commit
|
|
768
|
+
}
|
|
769
|
+
) }),
|
|
778
770
|
(local.kind === "text" || local.kind === "multiline") && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
779
771
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
780
772
|
/* @__PURE__ */ jsx("label", { className: "text-xs", children: "Editor" }),
|
|
@@ -797,12 +789,19 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
|
|
|
797
789
|
)
|
|
798
790
|
] }),
|
|
799
791
|
local.kind === "text" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
800
|
-
/* @__PURE__ */ jsx(
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
792
|
+
/* @__PURE__ */ jsx(
|
|
793
|
+
CheckboxField,
|
|
794
|
+
{
|
|
795
|
+
size: "sm",
|
|
796
|
+
checked: !!local.configJson?.multi,
|
|
797
|
+
onCheckedChange: (checked) => {
|
|
798
|
+
apply({ configJson: { ...local.configJson || {}, multi: checked === true } }, true);
|
|
799
|
+
},
|
|
800
|
+
label: "Multiple",
|
|
801
|
+
containerClassName: "md:col-span-2",
|
|
802
|
+
contentClassName: "gap-1 [&_label]:text-xs [&_label]:font-normal"
|
|
803
|
+
}
|
|
804
|
+
),
|
|
806
805
|
!!local.configJson?.multi && /* @__PURE__ */ jsxs("div", { className: "md:col-span-2", children: [
|
|
807
806
|
/* @__PURE__ */ jsx("label", { className: "text-xs", children: "Multi-select input style" }),
|
|
808
807
|
/* @__PURE__ */ jsxs(
|
|
@@ -843,7 +842,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
|
|
|
843
842
|
{
|
|
844
843
|
variant: "ghost",
|
|
845
844
|
size: "xs",
|
|
846
|
-
className: "text-
|
|
845
|
+
className: "text-destructive hover:text-destructive/80",
|
|
847
846
|
onClick: () => handleRemoveOption(idx),
|
|
848
847
|
"aria-label": "Remove option",
|
|
849
848
|
children: /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" })
|
|
@@ -868,60 +867,49 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
|
|
|
868
867
|
) })
|
|
869
868
|
] }),
|
|
870
869
|
(local.kind === "select" || local.kind === "relation") && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
871
|
-
/* @__PURE__ */
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
"
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
}
|
|
901
|
-
});
|
|
902
|
-
},
|
|
903
|
-
onBlur: commit
|
|
904
|
-
}
|
|
905
|
-
)
|
|
906
|
-
] })
|
|
870
|
+
/* @__PURE__ */ jsx(FormField, { label: "Options URL", children: /* @__PURE__ */ jsx(
|
|
871
|
+
Input,
|
|
872
|
+
{
|
|
873
|
+
placeholder: "/api/...",
|
|
874
|
+
value: typeof local.configJson?.optionsUrl === "string" ? local.configJson.optionsUrl : "",
|
|
875
|
+
onChange: (event) => apply({ configJson: { ...local.configJson || {}, optionsUrl: event.target.value } }),
|
|
876
|
+
onBlur: commit
|
|
877
|
+
}
|
|
878
|
+
) }),
|
|
879
|
+
local.kind === "relation" && /* @__PURE__ */ jsx(FormField, { label: "Related Entity ID", children: /* @__PURE__ */ jsx(
|
|
880
|
+
Input,
|
|
881
|
+
{
|
|
882
|
+
inputClassName: "font-mono",
|
|
883
|
+
placeholder: "module:entity",
|
|
884
|
+
value: typeof local.configJson?.relatedEntityId === "string" ? local.configJson.relatedEntityId : "",
|
|
885
|
+
onChange: (event) => {
|
|
886
|
+
const relatedEntityId = event.target.value;
|
|
887
|
+
const defOptionsUrl = relatedEntityId ? `/api/entities/relations/options?entityId=${encodeURIComponent(relatedEntityId)}` : "";
|
|
888
|
+
apply({
|
|
889
|
+
configJson: {
|
|
890
|
+
...local.configJson || {},
|
|
891
|
+
relatedEntityId,
|
|
892
|
+
optionsUrl: local.configJson?.optionsUrl || defOptionsUrl
|
|
893
|
+
}
|
|
894
|
+
});
|
|
895
|
+
},
|
|
896
|
+
onBlur: commit
|
|
897
|
+
}
|
|
898
|
+
) })
|
|
907
899
|
] }),
|
|
908
900
|
local.kind === "currency" && /* @__PURE__ */ jsxs("div", { className: "md:col-span-2", children: [
|
|
909
901
|
/* @__PURE__ */ jsx("label", { className: "text-xs", children: "Options source" }),
|
|
910
902
|
/* @__PURE__ */ jsx("div", { className: "rounded border bg-muted px-2 py-1 text-xs text-muted-foreground", children: "/api/currencies/options" })
|
|
911
903
|
] }),
|
|
912
|
-
(local.kind === "integer" || local.kind === "float") && /* @__PURE__ */
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
"
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
onBlur: commit
|
|
922
|
-
}
|
|
923
|
-
)
|
|
924
|
-
] })
|
|
904
|
+
(local.kind === "integer" || local.kind === "float") && /* @__PURE__ */ jsx(FormField, { label: "Units (optional)", className: "md:col-span-2", children: /* @__PURE__ */ jsx(
|
|
905
|
+
Input,
|
|
906
|
+
{
|
|
907
|
+
placeholder: "kg, cm, etc.",
|
|
908
|
+
value: typeof local.configJson?.unit === "string" ? local.configJson.unit : "",
|
|
909
|
+
onChange: (event) => apply({ configJson: { ...local.configJson || {}, unit: event.target.value } }),
|
|
910
|
+
onBlur: commit
|
|
911
|
+
}
|
|
912
|
+
) })
|
|
925
913
|
] }),
|
|
926
914
|
/* @__PURE__ */ jsxs("div", { className: "mt-3 pt-3 border-t", children: [
|
|
927
915
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
@@ -980,9 +968,8 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
|
|
|
980
968
|
}
|
|
981
969
|
) }),
|
|
982
970
|
/* @__PURE__ */ jsx("div", { className: "md:col-span-4", children: /* @__PURE__ */ jsx(
|
|
983
|
-
|
|
971
|
+
Input,
|
|
984
972
|
{
|
|
985
|
-
className: "border rounded w-full px-2 py-1 text-sm",
|
|
986
973
|
placeholder: rule?.rule === "regex" ? "Pattern (e.g. ^[a-z]+$)" : ["lt", "lte", "gt", "gte"].includes(rule?.rule) ? "Number" : "\u2014",
|
|
987
974
|
value: rule?.param ?? "",
|
|
988
975
|
onChange: (event) => {
|
|
@@ -999,9 +986,8 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
|
|
|
999
986
|
}
|
|
1000
987
|
) }),
|
|
1001
988
|
/* @__PURE__ */ jsx("div", { className: "md:col-span-4", children: /* @__PURE__ */ jsx(
|
|
1002
|
-
|
|
989
|
+
Input,
|
|
1003
990
|
{
|
|
1004
|
-
className: "border rounded w-full px-2 py-1 text-sm",
|
|
1005
991
|
placeholder: "Error message",
|
|
1006
992
|
value: rule?.message || "",
|
|
1007
993
|
onChange: (event) => {
|
|
@@ -1053,152 +1039,137 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
|
|
|
1053
1039
|
const currentDefault = local.configJson?.defaultValue;
|
|
1054
1040
|
if (local.kind === "boolean") {
|
|
1055
1041
|
const boolDefault = currentDefault === true ? "true" : currentDefault === false ? "false" : "";
|
|
1056
|
-
return /* @__PURE__ */
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1042
|
+
return /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.fields.defaultValue", "Default value"), className: "mt-3", children: /* @__PURE__ */ jsxs(
|
|
1043
|
+
Select,
|
|
1044
|
+
{
|
|
1045
|
+
value: boolDefault || DEFAULT_VALUE_NONE,
|
|
1046
|
+
onValueChange: (raw) => {
|
|
1047
|
+
const value = raw === "true" ? true : raw === "false" ? false : void 0;
|
|
1048
|
+
apply({ configJson: { ...local.configJson || {}, defaultValue: value } }, true);
|
|
1049
|
+
},
|
|
1050
|
+
children: [
|
|
1051
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
1052
|
+
/* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
1053
|
+
/* @__PURE__ */ jsx(SelectItem, { value: DEFAULT_VALUE_NONE, children: t("entities.customFields.fields.defaultValueNone", "No default") }),
|
|
1054
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "true", children: t("entities.customFields.fields.defaultValueTrue", "Checked (true)") }),
|
|
1055
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "false", children: t("entities.customFields.fields.defaultValueFalse", "Unchecked (false)") })
|
|
1056
|
+
] })
|
|
1057
|
+
]
|
|
1058
|
+
}
|
|
1059
|
+
) });
|
|
1060
|
+
}
|
|
1061
|
+
if (local.kind === "select" && !local.configJson?.multi) {
|
|
1062
|
+
const opts = normalizeCustomFieldOptions(local.configJson?.options || []);
|
|
1063
|
+
if (opts.length > 0) {
|
|
1064
|
+
const noneValue = getDefaultValueNoneOptionValue(opts);
|
|
1065
|
+
return /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.fields.defaultValue", "Default value"), className: "mt-3", children: /* @__PURE__ */ jsxs(
|
|
1066
|
+
Select,
|
|
1060
1067
|
{
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1068
|
+
value: typeof currentDefault === "string" || typeof currentDefault === "number" ? String(currentDefault) : "",
|
|
1069
|
+
onValueChange: (raw) => {
|
|
1070
|
+
if (raw === noneValue) {
|
|
1071
|
+
apply({ configJson: { ...local.configJson || {}, defaultValue: void 0 } }, true);
|
|
1072
|
+
return;
|
|
1073
|
+
}
|
|
1074
|
+
const matched = opts.find((o) => String(o.value) === raw);
|
|
1075
|
+
const typed = matched ? matched.value : raw;
|
|
1076
|
+
apply({ configJson: { ...local.configJson || {}, defaultValue: typed } }, true);
|
|
1067
1077
|
},
|
|
1068
1078
|
children: [
|
|
1069
|
-
/* @__PURE__ */ jsx(
|
|
1070
|
-
/* @__PURE__ */
|
|
1071
|
-
|
|
1079
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t("entities.customFields.fields.defaultValueNone", "No default") }) }),
|
|
1080
|
+
/* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
1081
|
+
/* @__PURE__ */ jsx(SelectItem, { value: noneValue, children: t("entities.customFields.fields.defaultValueNone", "No default") }),
|
|
1082
|
+
opts.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: String(option.value), children: option.label }, String(option.value)))
|
|
1083
|
+
] })
|
|
1072
1084
|
]
|
|
1073
1085
|
}
|
|
1074
|
-
)
|
|
1075
|
-
] });
|
|
1076
|
-
}
|
|
1077
|
-
if (local.kind === "select" && !local.configJson?.multi) {
|
|
1078
|
-
const opts = normalizeCustomFieldOptions(local.configJson?.options || []);
|
|
1079
|
-
if (opts.length > 0) {
|
|
1080
|
-
return /* @__PURE__ */ jsxs("div", { className: "mt-3", children: [
|
|
1081
|
-
/* @__PURE__ */ jsx("label", { className: "text-xs", children: t("entities.customFields.fields.defaultValue", "Default value") }),
|
|
1082
|
-
/* @__PURE__ */ jsxs(
|
|
1083
|
-
"select",
|
|
1084
|
-
{
|
|
1085
|
-
className: "border rounded w-full px-2 py-1 text-sm",
|
|
1086
|
-
value: typeof currentDefault === "string" || typeof currentDefault === "number" ? String(currentDefault) : "",
|
|
1087
|
-
onChange: (event) => {
|
|
1088
|
-
const raw = event.target.value;
|
|
1089
|
-
if (!raw) {
|
|
1090
|
-
apply({ configJson: { ...local.configJson || {}, defaultValue: void 0 } }, true);
|
|
1091
|
-
return;
|
|
1092
|
-
}
|
|
1093
|
-
const matched = opts.find((o) => String(o.value) === raw);
|
|
1094
|
-
const typed = matched ? matched.value : raw;
|
|
1095
|
-
apply({ configJson: { ...local.configJson || {}, defaultValue: typed } }, true);
|
|
1096
|
-
},
|
|
1097
|
-
children: [
|
|
1098
|
-
/* @__PURE__ */ jsx("option", { value: "", children: t("entities.customFields.fields.defaultValueNone", "No default") }),
|
|
1099
|
-
opts.map((option) => /* @__PURE__ */ jsx("option", { value: String(option.value), children: option.label }, String(option.value)))
|
|
1100
|
-
]
|
|
1101
|
-
}
|
|
1102
|
-
)
|
|
1103
|
-
] });
|
|
1086
|
+
) });
|
|
1104
1087
|
}
|
|
1105
1088
|
}
|
|
1106
1089
|
if (local.kind === "integer" || local.kind === "float") {
|
|
1107
|
-
return /* @__PURE__ */
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
"
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
placeholder: t("entities.customFields.fields.defaultValuePlaceholder", "No default")
|
|
1124
|
-
}
|
|
1125
|
-
)
|
|
1126
|
-
] });
|
|
1090
|
+
return /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.fields.defaultValue", "Default value"), className: "mt-3", children: /* @__PURE__ */ jsx(
|
|
1091
|
+
Input,
|
|
1092
|
+
{
|
|
1093
|
+
type: "number",
|
|
1094
|
+
step: local.kind === "integer" ? "1" : "any",
|
|
1095
|
+
value: typeof currentDefault === "number" ? String(currentDefault) : "",
|
|
1096
|
+
onChange: (event) => {
|
|
1097
|
+
const raw = event.target.value;
|
|
1098
|
+
const parsed = raw === "" ? void 0 : local.kind === "integer" ? parseInt(raw, 10) : parseFloat(raw);
|
|
1099
|
+
const value = parsed !== void 0 && !isNaN(parsed) ? parsed : void 0;
|
|
1100
|
+
apply({ configJson: { ...local.configJson || {}, defaultValue: value } });
|
|
1101
|
+
},
|
|
1102
|
+
onBlur: commit,
|
|
1103
|
+
placeholder: t("entities.customFields.fields.defaultValuePlaceholder", "No default")
|
|
1104
|
+
}
|
|
1105
|
+
) });
|
|
1127
1106
|
}
|
|
1128
1107
|
if (["text", "multiline", "date", "datetime", "currency"].includes(local.kind)) {
|
|
1129
|
-
return /* @__PURE__ */
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
"
|
|
1133
|
-
{
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
placeholder: t("entities.customFields.fields.defaultValuePlaceholder", "No default")
|
|
1142
|
-
}
|
|
1143
|
-
)
|
|
1144
|
-
] });
|
|
1108
|
+
return /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.fields.defaultValue", "Default value"), className: "mt-3", children: /* @__PURE__ */ jsx(
|
|
1109
|
+
Input,
|
|
1110
|
+
{
|
|
1111
|
+
value: typeof currentDefault === "string" ? currentDefault : "",
|
|
1112
|
+
onChange: (event) => {
|
|
1113
|
+
const value = event.target.value;
|
|
1114
|
+
apply({ configJson: { ...local.configJson || {}, defaultValue: value || void 0 } });
|
|
1115
|
+
},
|
|
1116
|
+
onBlur: commit,
|
|
1117
|
+
placeholder: t("entities.customFields.fields.defaultValuePlaceholder", "No default")
|
|
1118
|
+
}
|
|
1119
|
+
) });
|
|
1145
1120
|
}
|
|
1146
1121
|
return null;
|
|
1147
1122
|
})(),
|
|
1148
1123
|
/* @__PURE__ */ jsxs("div", { className: "mt-3 pt-2 border-t flex flex-wrap items-center gap-4", children: [
|
|
1149
1124
|
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: t("entities.customFields.fields.visibility", "Visibility:") }),
|
|
1150
|
-
/* @__PURE__ */
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
"
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
{
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
}
|
|
1199
|
-
),
|
|
1200
|
-
t("entities.customFields.fields.encrypted", "Encrypted")
|
|
1201
|
-
] })
|
|
1125
|
+
/* @__PURE__ */ jsx(
|
|
1126
|
+
CheckboxField,
|
|
1127
|
+
{
|
|
1128
|
+
size: "sm",
|
|
1129
|
+
checked: local.configJson?.listVisible !== false,
|
|
1130
|
+
onCheckedChange: (checked) => {
|
|
1131
|
+
apply({ configJson: { ...local.configJson || {}, listVisible: checked === true } }, true);
|
|
1132
|
+
},
|
|
1133
|
+
label: t("entities.customFields.fields.listVisible", "List"),
|
|
1134
|
+
contentClassName: "gap-1 [&_label]:text-xs [&_label]:font-normal"
|
|
1135
|
+
}
|
|
1136
|
+
),
|
|
1137
|
+
/* @__PURE__ */ jsx(
|
|
1138
|
+
CheckboxField,
|
|
1139
|
+
{
|
|
1140
|
+
size: "sm",
|
|
1141
|
+
checked: !!local.configJson?.filterable,
|
|
1142
|
+
onCheckedChange: (checked) => {
|
|
1143
|
+
apply({ configJson: { ...local.configJson || {}, filterable: checked === true } }, true);
|
|
1144
|
+
},
|
|
1145
|
+
label: t("entities.customFields.fields.filterable", "Filter"),
|
|
1146
|
+
contentClassName: "gap-1 [&_label]:text-xs [&_label]:font-normal"
|
|
1147
|
+
}
|
|
1148
|
+
),
|
|
1149
|
+
/* @__PURE__ */ jsx(
|
|
1150
|
+
CheckboxField,
|
|
1151
|
+
{
|
|
1152
|
+
size: "sm",
|
|
1153
|
+
checked: local.configJson?.formEditable !== false,
|
|
1154
|
+
onCheckedChange: (checked) => {
|
|
1155
|
+
apply({ configJson: { ...local.configJson || {}, formEditable: checked === true } }, true);
|
|
1156
|
+
},
|
|
1157
|
+
label: t("entities.customFields.fields.formEditable", "Form"),
|
|
1158
|
+
contentClassName: "gap-1 [&_label]:text-xs [&_label]:font-normal"
|
|
1159
|
+
}
|
|
1160
|
+
),
|
|
1161
|
+
/* @__PURE__ */ jsx(
|
|
1162
|
+
CheckboxField,
|
|
1163
|
+
{
|
|
1164
|
+
size: "sm",
|
|
1165
|
+
checked: !!local.configJson?.encrypted,
|
|
1166
|
+
onCheckedChange: (checked) => {
|
|
1167
|
+
apply({ configJson: { ...local.configJson || {}, encrypted: checked === true } }, true);
|
|
1168
|
+
},
|
|
1169
|
+
label: t("entities.customFields.fields.encrypted", "Encrypted"),
|
|
1170
|
+
contentClassName: "gap-1 [&_label]:text-xs [&_label]:font-normal"
|
|
1171
|
+
}
|
|
1172
|
+
)
|
|
1202
1173
|
] })
|
|
1203
1174
|
] }),
|
|
1204
1175
|
/* @__PURE__ */ jsx(
|
|
@@ -1215,34 +1186,26 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
|
|
|
1215
1186
|
/* @__PURE__ */ jsx(DialogDescription, { children: "Provide the stored value and optional label shown to users." })
|
|
1216
1187
|
] }),
|
|
1217
1188
|
/* @__PURE__ */ jsxs("div", { className: "space-y-4 py-2", children: [
|
|
1218
|
-
/* @__PURE__ */
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
"
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
setOptionFormError(null);
|
|
1228
|
-
setOptionValueDraft(event.target.value);
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
),
|
|
1232
|
-
optionFormError ? /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-red-600", children: optionFormError }) : null
|
|
1233
|
-
] }),
|
|
1234
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1235
|
-
/* @__PURE__ */ jsx("label", { className: "text-xs", children: "Label" }),
|
|
1236
|
-
/* @__PURE__ */ jsx(
|
|
1237
|
-
"input",
|
|
1238
|
-
{
|
|
1239
|
-
className: "mt-1 w-full rounded border px-2 py-1 text-sm",
|
|
1240
|
-
placeholder: "Label shown to users (optional)",
|
|
1241
|
-
value: optionLabelDraft,
|
|
1242
|
-
onChange: (event) => setOptionLabelDraft(event.target.value)
|
|
1189
|
+
/* @__PURE__ */ jsx(FormField, { label: "Value", error: optionFormError ?? void 0, children: /* @__PURE__ */ jsx(
|
|
1190
|
+
Input,
|
|
1191
|
+
{
|
|
1192
|
+
inputClassName: "font-mono",
|
|
1193
|
+
placeholder: "unique_value",
|
|
1194
|
+
value: optionValueDraft,
|
|
1195
|
+
onChange: (event) => {
|
|
1196
|
+
setOptionFormError(null);
|
|
1197
|
+
setOptionValueDraft(event.target.value);
|
|
1243
1198
|
}
|
|
1244
|
-
|
|
1245
|
-
|
|
1199
|
+
}
|
|
1200
|
+
) }),
|
|
1201
|
+
/* @__PURE__ */ jsx(FormField, { label: "Label", children: /* @__PURE__ */ jsx(
|
|
1202
|
+
Input,
|
|
1203
|
+
{
|
|
1204
|
+
placeholder: "Label shown to users (optional)",
|
|
1205
|
+
value: optionLabelDraft,
|
|
1206
|
+
onChange: (event) => setOptionLabelDraft(event.target.value)
|
|
1207
|
+
}
|
|
1208
|
+
) })
|
|
1246
1209
|
] }),
|
|
1247
1210
|
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
1248
1211
|
/* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: handleCloseOptionDialog, children: "Cancel" }),
|
|
@@ -1269,47 +1232,35 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
|
|
|
1269
1232
|
/* @__PURE__ */ jsx(DialogDescription, { children: editingGroupCode ? "Update the selected group for this fieldset." : "Add a reusable group for this fieldset." })
|
|
1270
1233
|
] }),
|
|
1271
1234
|
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
1272
|
-
/* @__PURE__ */
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
"
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1302
|
-
/* @__PURE__ */ jsx("label", { className: "text-xs font-medium", children: "Hint" }),
|
|
1303
|
-
/* @__PURE__ */ jsx(
|
|
1304
|
-
"input",
|
|
1305
|
-
{
|
|
1306
|
-
className: "mt-1 w-full rounded border px-2 py-1 text-sm",
|
|
1307
|
-
value: groupDraft.hint,
|
|
1308
|
-
onChange: (event) => setGroupDraft((prev) => ({ ...prev, hint: event.target.value })),
|
|
1309
|
-
placeholder: "Visible to merchandisers"
|
|
1310
|
-
}
|
|
1311
|
-
)
|
|
1312
|
-
] }),
|
|
1235
|
+
/* @__PURE__ */ jsx(FormField, { label: "Group code", error: groupError ?? void 0, disabled: !!editingGroupCode, children: /* @__PURE__ */ jsx(
|
|
1236
|
+
Input,
|
|
1237
|
+
{
|
|
1238
|
+
inputClassName: "font-mono",
|
|
1239
|
+
value: groupDraft.code,
|
|
1240
|
+
onChange: (event) => {
|
|
1241
|
+
setGroupDraft((prev) => ({ ...prev, code: event.target.value }));
|
|
1242
|
+
if (groupError) setGroupError(null);
|
|
1243
|
+
},
|
|
1244
|
+
disabled: !!editingGroupCode,
|
|
1245
|
+
placeholder: "e.g. buying_committee"
|
|
1246
|
+
}
|
|
1247
|
+
) }),
|
|
1248
|
+
/* @__PURE__ */ jsx(FormField, { label: "Label", children: /* @__PURE__ */ jsx(
|
|
1249
|
+
Input,
|
|
1250
|
+
{
|
|
1251
|
+
value: groupDraft.title,
|
|
1252
|
+
onChange: (event) => setGroupDraft((prev) => ({ ...prev, title: event.target.value })),
|
|
1253
|
+
placeholder: "Buying committee"
|
|
1254
|
+
}
|
|
1255
|
+
) }),
|
|
1256
|
+
/* @__PURE__ */ jsx(FormField, { label: "Hint", children: /* @__PURE__ */ jsx(
|
|
1257
|
+
Input,
|
|
1258
|
+
{
|
|
1259
|
+
value: groupDraft.hint,
|
|
1260
|
+
onChange: (event) => setGroupDraft((prev) => ({ ...prev, hint: event.target.value })),
|
|
1261
|
+
placeholder: "Visible to merchandisers"
|
|
1262
|
+
}
|
|
1263
|
+
) }),
|
|
1313
1264
|
currentFieldsetValue && groupOptions.length > 0 ? /* @__PURE__ */ jsxs("div", { children: [
|
|
1314
1265
|
/* @__PURE__ */ jsx("div", { className: "text-xs font-medium mb-1", children: "Existing groups" }),
|
|
1315
1266
|
/* @__PURE__ */ jsx("div", { className: "space-y-2 max-h-40 overflow-y-auto", children: groupOptions.map((group) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between rounded border px-3 py-2 text-sm", children: [
|
|
@@ -1335,7 +1286,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
|
|
|
1335
1286
|
{
|
|
1336
1287
|
variant: "ghost",
|
|
1337
1288
|
size: "xs",
|
|
1338
|
-
className: "text-
|
|
1289
|
+
className: "text-destructive hover:text-destructive/80",
|
|
1339
1290
|
onClick: () => handleRemoveGroupEntry(group.code),
|
|
1340
1291
|
"aria-label": `Delete ${group.code}`,
|
|
1341
1292
|
children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" })
|