@open-mercato/ui 0.5.1-develop.2953.6647bb2c43 → 0.5.1-develop.2964.d5ac4a6ebb
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/AGENTS.md +8 -0
- package/dist/backend/CrudForm.js +57 -29
- package/dist/backend/CrudForm.js.map +2 -2
- package/dist/backend/DataTable.js +32 -14
- package/dist/backend/DataTable.js.map +2 -2
- package/dist/backend/FilterOverlay.js +23 -17
- package/dist/backend/FilterOverlay.js.map +2 -2
- package/dist/backend/JsonBuilder.js +32 -18
- package/dist/backend/JsonBuilder.js.map +2 -2
- package/dist/backend/columns/ColumnChooserPanel.js +12 -13
- package/dist/backend/columns/ColumnChooserPanel.js.map +2 -2
- package/dist/backend/custom-fields/FieldDefinitionsEditor.js +71 -62
- package/dist/backend/custom-fields/FieldDefinitionsEditor.js.map +2 -2
- package/dist/backend/date-range/DateRangeSelect.js +11 -10
- package/dist/backend/date-range/DateRangeSelect.js.map +2 -2
- package/dist/backend/date-range/InlineDateRangeSelect.js +10 -22
- package/dist/backend/date-range/InlineDateRangeSelect.js.map +2 -2
- package/dist/backend/detail/ActivitiesSection.js +20 -12
- package/dist/backend/detail/ActivitiesSection.js.map +2 -2
- package/dist/backend/detail/AddressEditor.js +24 -7
- package/dist/backend/detail/AddressEditor.js.map +2 -2
- package/dist/backend/detail/InlineEditors.js +12 -6
- package/dist/backend/detail/InlineEditors.js.map +2 -2
- package/dist/backend/detail/NotesSection.js +20 -14
- package/dist/backend/detail/NotesSection.js.map +2 -2
- package/dist/backend/filters/AdvancedFilterBuilder.js +52 -24
- package/dist/backend/filters/AdvancedFilterBuilder.js.map +2 -2
- package/dist/backend/injection/InjectedField.js +12 -7
- package/dist/backend/injection/InjectedField.js.map +2 -2
- package/dist/backend/inputs/ComboboxInput.js.map +2 -2
- package/dist/backend/inputs/EventSelect.js +22 -6
- package/dist/backend/inputs/EventSelect.js.map +2 -2
- package/dist/backend/inputs/PhoneNumberField.js +2 -2
- package/dist/backend/inputs/PhoneNumberField.js.map +2 -2
- package/dist/backend/inputs/TimeInput.js +9 -10
- package/dist/backend/inputs/TimeInput.js.map +2 -2
- package/dist/backend/messages/message-compose-form-groups.js +12 -7
- package/dist/backend/messages/message-compose-form-groups.js.map +2 -2
- package/dist/backend/messages/useMessageCompose.js +7 -1
- package/dist/backend/messages/useMessageCompose.js.map +2 -2
- package/dist/frontend/LanguageSwitcher.js +19 -14
- package/dist/frontend/LanguageSwitcher.js.map +2 -2
- package/dist/index.js +5 -0
- package/dist/index.js.map +2 -2
- package/dist/primitives/checkbox-field.js +17 -5
- package/dist/primitives/checkbox-field.js.map +2 -2
- package/dist/primitives/input.js +71 -14
- package/dist/primitives/input.js.map +2 -2
- package/dist/primitives/radio-field.js +74 -0
- package/dist/primitives/radio-field.js.map +7 -0
- package/dist/primitives/radio.js +37 -0
- package/dist/primitives/radio.js.map +7 -0
- package/dist/primitives/select.js +155 -0
- package/dist/primitives/select.js.map +7 -0
- package/dist/primitives/switch-field.js +76 -0
- package/dist/primitives/switch-field.js.map +7 -0
- package/dist/primitives/switch.js +17 -3
- package/dist/primitives/switch.js.map +2 -2
- package/dist/primitives/textarea.js +48 -12
- package/dist/primitives/textarea.js.map +2 -2
- package/dist/primitives/tooltip.js +44 -15
- package/dist/primitives/tooltip.js.map +2 -2
- package/package.json +5 -3
- package/src/backend/CrudForm.tsx +104 -37
- package/src/backend/DataTable.tsx +38 -20
- package/src/backend/FilterOverlay.tsx +35 -21
- package/src/backend/JsonBuilder.tsx +38 -20
- package/src/backend/__tests__/FieldDefinitionsEditor.test.tsx +23 -6
- package/src/backend/columns/ColumnChooserPanel.tsx +9 -10
- package/src/backend/custom-fields/FieldDefinitionsEditor.tsx +120 -87
- package/src/backend/date-range/DateRangeSelect.tsx +19 -12
- package/src/backend/date-range/InlineDateRangeSelect.tsx +16 -20
- package/src/backend/detail/ActivitiesSection.tsx +35 -23
- package/src/backend/detail/AddressEditor.tsx +30 -16
- package/src/backend/detail/InlineEditors.tsx +21 -11
- package/src/backend/detail/NotesSection.tsx +35 -25
- package/src/backend/filters/AdvancedFilterBuilder.tsx +60 -34
- package/src/backend/injection/InjectedField.tsx +21 -12
- package/src/backend/inputs/ComboboxInput.tsx +4 -0
- package/src/backend/inputs/EventSelect.tsx +30 -17
- package/src/backend/inputs/PhoneNumberField.tsx +2 -2
- package/src/backend/inputs/TimeInput.tsx +9 -10
- package/src/backend/messages/message-compose-form-groups.tsx +21 -12
- package/src/backend/messages/useMessageCompose.ts +20 -1
- package/src/frontend/LanguageSwitcher.tsx +20 -17
- package/src/index.ts +5 -0
- package/src/primitives/checkbox-field.tsx +10 -2
- package/src/primitives/input.tsx +73 -12
- package/src/primitives/radio-field.tsx +92 -0
- package/src/primitives/radio.tsx +42 -0
- package/src/primitives/select.tsx +200 -0
- package/src/primitives/switch-field.tsx +100 -0
- package/src/primitives/switch.tsx +17 -4
- package/src/primitives/textarea.tsx +67 -11
- package/src/primitives/tooltip.tsx +68 -24
package/.turbo/turbo-build.log
CHANGED
package/AGENTS.md
CHANGED
|
@@ -23,6 +23,14 @@ When you need… use this. Details (variants, sizes, props, MUST rules) live in
|
|
|
23
23
|
| Marketing CTA with brand gradient | `FancyButton` | `@open-mercato/ui/primitives/fancy-button` |
|
|
24
24
|
| Checkbox primitive (with indeterminate) | `Checkbox` | `@open-mercato/ui/primitives/checkbox` |
|
|
25
25
|
| Checkbox with label + description | `CheckboxField` | `@open-mercato/ui/primitives/checkbox-field` |
|
|
26
|
+
| Text input (text/email/password/number/etc.) | `Input` | `@open-mercato/ui/primitives/input` |
|
|
27
|
+
| Multi-line text input (with optional char counter) | `Textarea` | `@open-mercato/ui/primitives/textarea` |
|
|
28
|
+
| Dropdown / select | `Select` (with `SelectTrigger` / `SelectContent` / `SelectItem`) | `@open-mercato/ui/primitives/select` |
|
|
29
|
+
| Tooltip on hover (with arrow, dark/light) | `SimpleTooltip` (or `Tooltip`+`TooltipTrigger`+`TooltipContent`) | `@open-mercato/ui/primitives/tooltip` |
|
|
30
|
+
| Toggle switch (binary on/off preference) | `Switch` | `@open-mercato/ui/primitives/switch` |
|
|
31
|
+
| Switch with label + description (preference row) | `SwitchField` | `@open-mercato/ui/primitives/switch-field` |
|
|
32
|
+
| Radio button (single primitive) | `Radio` (inside `RadioGroup`) | `@open-mercato/ui/primitives/radio` |
|
|
33
|
+
| Radio with label + description (form row) | `RadioField` | `@open-mercato/ui/primitives/radio-field` |
|
|
26
34
|
| User / entity avatar | `Avatar`, `AvatarStack` | `@open-mercato/ui/primitives/avatar` |
|
|
27
35
|
| Keyboard shortcut keys | `Kbd`, `KbdShortcut` | `@open-mercato/ui/primitives/kbd` |
|
|
28
36
|
| Entity tag pill | `Tag` (with `TagMap`) | `@open-mercato/ui/primitives/tag` |
|
package/dist/backend/CrudForm.js
CHANGED
|
@@ -15,6 +15,15 @@ import { SortableContext, verticalListSortingStrategy, useSortable } from "@dnd-
|
|
|
15
15
|
import { CSS } from "@dnd-kit/utilities";
|
|
16
16
|
import { DataLoader } from "../primitives/DataLoader.js";
|
|
17
17
|
import { Checkbox } from "../primitives/checkbox.js";
|
|
18
|
+
import { Input } from "../primitives/input.js";
|
|
19
|
+
import { Textarea } from "../primitives/textarea.js";
|
|
20
|
+
import {
|
|
21
|
+
Select,
|
|
22
|
+
SelectContent,
|
|
23
|
+
SelectItem,
|
|
24
|
+
SelectTrigger,
|
|
25
|
+
SelectValue
|
|
26
|
+
} from "../primitives/select.js";
|
|
18
27
|
import { flash } from "./FlashMessages.js";
|
|
19
28
|
import dynamic from "next/dynamic";
|
|
20
29
|
import { FormHeader } from "./forms/FormHeader.js";
|
|
@@ -86,6 +95,7 @@ import { evaluateInjectedVisibility } from "./injection/visibility-utils.js";
|
|
|
86
95
|
import { ComponentReplacementHandles } from "@open-mercato/shared/modules/widgets/component-registry";
|
|
87
96
|
import { sanitizeHtmlRichText, sanitizeRichTextHref, sanitizeRichTextPasteContent } from "./utils/richTextSanitizer.js";
|
|
88
97
|
const EMPTY_OPTIONS = [];
|
|
98
|
+
const SELECT_CLEAR_SENTINEL = "__crudform_select_clear__";
|
|
89
99
|
const FOCUSABLE_SELECTOR = '[data-crud-focus-target], input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
90
100
|
const CRUDFORM_EXTENDED_EVENTS_ENABLED = parseBooleanWithDefault(
|
|
91
101
|
process.env.NEXT_PUBLIC_OM_CRUDFORM_EXTENDED_EVENTS_ENABLED,
|
|
@@ -1481,6 +1491,11 @@ function CrudForm({
|
|
|
1481
1491
|
if (!fieldId || lastErrorFieldRef.current === fieldId) return;
|
|
1482
1492
|
const form = document.getElementById(formId);
|
|
1483
1493
|
if (!form) return;
|
|
1494
|
+
const active = document.activeElement;
|
|
1495
|
+
if (active instanceof HTMLElement && form.contains(active)) {
|
|
1496
|
+
lastErrorFieldRef.current = fieldId;
|
|
1497
|
+
return;
|
|
1498
|
+
}
|
|
1484
1499
|
const container = form.querySelector(`[data-crud-field-id="${fieldId}"]`);
|
|
1485
1500
|
const target = container?.querySelector(FOCUSABLE_SELECTOR) ?? form.querySelector(`[name="${fieldId}"]`) ?? container ?? null;
|
|
1486
1501
|
if (target && typeof target.focus === "function") {
|
|
@@ -2127,17 +2142,16 @@ function CrudForm({
|
|
|
2127
2142
|
/* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card p-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 text-sm", children: [
|
|
2128
2143
|
/* @__PURE__ */ jsx("label", { className: "text-xs uppercase tracking-wide text-muted-foreground", children: fieldsetSelectorLabel }),
|
|
2129
2144
|
/* @__PURE__ */ jsxs(
|
|
2130
|
-
|
|
2145
|
+
Select,
|
|
2131
2146
|
{
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
onChange: (event) => handleFieldsetSelectionChange(
|
|
2147
|
+
value: entityLayout.activeFieldset || void 0,
|
|
2148
|
+
onValueChange: (value) => handleFieldsetSelectionChange(
|
|
2135
2149
|
entityLayout.entityId,
|
|
2136
|
-
|
|
2150
|
+
value || null
|
|
2137
2151
|
),
|
|
2138
2152
|
children: [
|
|
2139
|
-
/* @__PURE__ */ jsx(
|
|
2140
|
-
entityLayout.availableFieldsets.map((fs) => /* @__PURE__ */ jsx(
|
|
2153
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-auto min-w-[10rem]", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: defaultFieldsetLabel }) }),
|
|
2154
|
+
/* @__PURE__ */ jsx(SelectContent, { children: entityLayout.availableFieldsets.map((fs) => /* @__PURE__ */ jsx(SelectItem, { value: fs.code, children: fs.label }, fs.code)) })
|
|
2141
2155
|
]
|
|
2142
2156
|
}
|
|
2143
2157
|
),
|
|
@@ -2634,10 +2648,9 @@ function RelationSelect({
|
|
|
2634
2648
|
}, [query, options]);
|
|
2635
2649
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
2636
2650
|
/* @__PURE__ */ jsx(
|
|
2637
|
-
|
|
2651
|
+
Input,
|
|
2638
2652
|
{
|
|
2639
2653
|
ref: inputRef,
|
|
2640
|
-
className: "w-full h-9 rounded border px-2 text-sm",
|
|
2641
2654
|
placeholder: placeholder || t("ui.forms.listbox.searchPlaceholder", "Search..."),
|
|
2642
2655
|
value: query,
|
|
2643
2656
|
onChange: (e) => setQuery(e.target.value),
|
|
@@ -2718,10 +2731,9 @@ function TextInput({
|
|
|
2718
2731
|
}, [commitIfChanged]);
|
|
2719
2732
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2720
2733
|
/* @__PURE__ */ jsx(
|
|
2721
|
-
|
|
2734
|
+
Input,
|
|
2722
2735
|
{
|
|
2723
2736
|
type: inputType,
|
|
2724
|
-
className: "w-full h-9 rounded border px-2 text-sm",
|
|
2725
2737
|
placeholder,
|
|
2726
2738
|
value: local,
|
|
2727
2739
|
onChange: handleChange,
|
|
@@ -2779,10 +2791,9 @@ function NumberInput({
|
|
|
2779
2791
|
commitIfChanged();
|
|
2780
2792
|
}, [commitIfChanged]);
|
|
2781
2793
|
return /* @__PURE__ */ jsx(
|
|
2782
|
-
|
|
2794
|
+
Input,
|
|
2783
2795
|
{
|
|
2784
2796
|
type: "number",
|
|
2785
|
-
className: "w-full h-9 rounded border px-2 text-sm",
|
|
2786
2797
|
placeholder,
|
|
2787
2798
|
value: local,
|
|
2788
2799
|
onChange: handleChange,
|
|
@@ -2798,7 +2809,11 @@ function TextAreaInput({
|
|
|
2798
2809
|
value,
|
|
2799
2810
|
onChange,
|
|
2800
2811
|
placeholder,
|
|
2801
|
-
autoFocus
|
|
2812
|
+
autoFocus,
|
|
2813
|
+
maxLength,
|
|
2814
|
+
showCount,
|
|
2815
|
+
rows,
|
|
2816
|
+
disabled
|
|
2802
2817
|
}) {
|
|
2803
2818
|
const [local, setLocal] = React.useState(value);
|
|
2804
2819
|
const isFocusedRef = React.useRef(false);
|
|
@@ -2822,15 +2837,18 @@ function TextAreaInput({
|
|
|
2822
2837
|
commitIfChanged();
|
|
2823
2838
|
}, [commitIfChanged]);
|
|
2824
2839
|
return /* @__PURE__ */ jsx(
|
|
2825
|
-
|
|
2840
|
+
Textarea,
|
|
2826
2841
|
{
|
|
2827
|
-
className: "w-full rounded border px-2 py-2 min-h-[80px] sm:min-h-[120px] text-sm",
|
|
2828
2842
|
placeholder,
|
|
2829
2843
|
value: local,
|
|
2830
2844
|
onChange: handleChange,
|
|
2831
2845
|
onFocus: handleFocus,
|
|
2832
2846
|
onBlur: handleBlur,
|
|
2833
2847
|
autoFocus,
|
|
2848
|
+
maxLength,
|
|
2849
|
+
showCount,
|
|
2850
|
+
rows,
|
|
2851
|
+
disabled,
|
|
2834
2852
|
"data-crud-focus-target": ""
|
|
2835
2853
|
}
|
|
2836
2854
|
);
|
|
@@ -3106,9 +3124,10 @@ const ListboxMultiSelect = React.memo(function ListboxMultiSelect2({
|
|
|
3106
3124
|
);
|
|
3107
3125
|
return /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
|
|
3108
3126
|
/* @__PURE__ */ jsx(
|
|
3109
|
-
|
|
3127
|
+
Input,
|
|
3110
3128
|
{
|
|
3111
|
-
className: "mb-2
|
|
3129
|
+
className: "mb-2",
|
|
3130
|
+
size: "sm",
|
|
3112
3131
|
placeholder: searchPlaceholder,
|
|
3113
3132
|
value: query,
|
|
3114
3133
|
onChange: (e) => setQuery(e.target.value),
|
|
@@ -3226,10 +3245,9 @@ const FieldControl = React.memo(
|
|
|
3226
3245
|
}
|
|
3227
3246
|
),
|
|
3228
3247
|
field.type === "date" && /* @__PURE__ */ jsx(
|
|
3229
|
-
|
|
3248
|
+
Input,
|
|
3230
3249
|
{
|
|
3231
3250
|
type: "date",
|
|
3232
|
-
className: "w-full h-9 rounded border px-2 text-sm",
|
|
3233
3251
|
value: typeof value === "string" ? value : "",
|
|
3234
3252
|
onChange: (e) => setValue(field.id, e.target.value || void 0),
|
|
3235
3253
|
autoFocus: autoFocusField,
|
|
@@ -3238,10 +3256,9 @@ const FieldControl = React.memo(
|
|
|
3238
3256
|
}
|
|
3239
3257
|
),
|
|
3240
3258
|
field.type === "datetime-local" && /* @__PURE__ */ jsx(
|
|
3241
|
-
|
|
3259
|
+
Input,
|
|
3242
3260
|
{
|
|
3243
3261
|
type: "datetime-local",
|
|
3244
|
-
className: "w-full h-9 rounded border px-2 text-sm",
|
|
3245
3262
|
value: typeof value === "string" ? value : "",
|
|
3246
3263
|
onChange: (e) => setValue(field.id, e.target.value || void 0),
|
|
3247
3264
|
autoFocus: autoFocusField,
|
|
@@ -3296,7 +3313,11 @@ const FieldControl = React.memo(
|
|
|
3296
3313
|
value: value == null ? "" : String(value),
|
|
3297
3314
|
placeholder,
|
|
3298
3315
|
onChange: (next) => fieldSetValue(next),
|
|
3299
|
-
autoFocus: autoFocusField
|
|
3316
|
+
autoFocus: autoFocusField,
|
|
3317
|
+
maxLength: builtin?.maxLength,
|
|
3318
|
+
showCount: builtin?.showCount,
|
|
3319
|
+
rows: builtin?.rows,
|
|
3320
|
+
disabled
|
|
3300
3321
|
}
|
|
3301
3322
|
),
|
|
3302
3323
|
field.type === "richtext" && builtin?.editor === "simple" && /* @__PURE__ */ jsx(SimpleMarkdownEditor, { value: String(value ?? ""), onChange: fieldSetValue }),
|
|
@@ -3345,16 +3366,23 @@ const FieldControl = React.memo(
|
|
|
3345
3366
|
/* @__PURE__ */ jsx("span", { className: "text-sm", children: field.label })
|
|
3346
3367
|
] }),
|
|
3347
3368
|
field.type === "select" && !builtin?.multiple && /* @__PURE__ */ jsxs(
|
|
3348
|
-
|
|
3369
|
+
Select,
|
|
3349
3370
|
{
|
|
3350
|
-
className: "w-full h-9 rounded border pl-3 pr-8 text-sm",
|
|
3351
3371
|
value: Array.isArray(value) ? String(value[0] ?? "") : value == null ? "" : String(value),
|
|
3352
|
-
|
|
3353
|
-
|
|
3372
|
+
onValueChange: (next) => {
|
|
3373
|
+
if (!next || next === SELECT_CLEAR_SENTINEL) {
|
|
3374
|
+
setValue(field.id, void 0);
|
|
3375
|
+
return;
|
|
3376
|
+
}
|
|
3377
|
+
setValue(field.id, next);
|
|
3378
|
+
},
|
|
3354
3379
|
disabled,
|
|
3355
3380
|
children: [
|
|
3356
|
-
/* @__PURE__ */ jsx(
|
|
3357
|
-
|
|
3381
|
+
/* @__PURE__ */ jsx(SelectTrigger, { "data-crud-focus-target": "", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t("ui.forms.select.emptyOption", "\u2014") }) }),
|
|
3382
|
+
/* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
3383
|
+
!field.required && value != null && value !== "" && /* @__PURE__ */ jsx(SelectItem, { value: SELECT_CLEAR_SENTINEL, children: t("ui.forms.select.clearOption", "\u2014 Clear \u2014") }),
|
|
3384
|
+
options.filter((opt) => opt.value !== "").map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value))
|
|
3385
|
+
] })
|
|
3358
3386
|
]
|
|
3359
3387
|
}
|
|
3360
3388
|
),
|