@open-mercato/ui 0.6.1-develop.3256.1.fe3dec2464 → 0.6.1-develop.3276.1.1fcd145078

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 (137) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/backend/CrudForm.js +46 -129
  3. package/dist/backend/CrudForm.js.map +3 -3
  4. package/dist/backend/DataTable.js +10 -3
  5. package/dist/backend/DataTable.js.map +2 -2
  6. package/dist/backend/EmptyState.js +1 -47
  7. package/dist/backend/EmptyState.js.map +2 -2
  8. package/dist/backend/FilterOverlay.js +31 -26
  9. package/dist/backend/FilterOverlay.js.map +2 -2
  10. package/dist/backend/FlashMessages.js +23 -25
  11. package/dist/backend/FlashMessages.js.map +2 -2
  12. package/dist/backend/JsonBuilder.js +4 -2
  13. package/dist/backend/JsonBuilder.js.map +2 -2
  14. package/dist/backend/LogList.js +49 -0
  15. package/dist/backend/LogList.js.map +7 -0
  16. package/dist/backend/crud/CollapsibleGroup.js +13 -3
  17. package/dist/backend/crud/CollapsibleGroup.js.map +2 -2
  18. package/dist/backend/detail/InlineEditors.js +80 -32
  19. package/dist/backend/detail/InlineEditors.js.map +2 -2
  20. package/dist/backend/inputs/ComboboxInput.js +60 -6
  21. package/dist/backend/inputs/ComboboxInput.js.map +2 -2
  22. package/dist/backend/inputs/DatePicker.js +6 -142
  23. package/dist/backend/inputs/DatePicker.js.map +2 -2
  24. package/dist/backend/inputs/DateTimePicker.js +6 -182
  25. package/dist/backend/inputs/DateTimePicker.js.map +2 -2
  26. package/dist/backend/inputs/TagsInput.js +16 -19
  27. package/dist/backend/inputs/TagsInput.js.map +2 -2
  28. package/dist/backend/inputs/TimeInput.js +1 -1
  29. package/dist/backend/inputs/TimeInput.js.map +2 -2
  30. package/dist/backend/inputs/TimePicker.js +83 -72
  31. package/dist/backend/inputs/TimePicker.js.map +2 -2
  32. package/dist/backend/utils/customFieldForms.js +2 -2
  33. package/dist/backend/utils/customFieldForms.js.map +1 -1
  34. package/dist/portal/components/PortalEmptyState.js +13 -9
  35. package/dist/portal/components/PortalEmptyState.js.map +2 -2
  36. package/dist/primitives/accordion.js +137 -0
  37. package/dist/primitives/accordion.js.map +7 -0
  38. package/dist/primitives/alert.js +180 -12
  39. package/dist/primitives/alert.js.map +2 -2
  40. package/dist/primitives/calendar.js +122 -32
  41. package/dist/primitives/calendar.js.map +2 -2
  42. package/dist/primitives/compact-select.js +47 -0
  43. package/dist/primitives/compact-select.js.map +7 -0
  44. package/dist/primitives/counter-input.js +174 -0
  45. package/dist/primitives/counter-input.js.map +7 -0
  46. package/dist/primitives/date-picker-helpers.js +79 -0
  47. package/dist/primitives/date-picker-helpers.js.map +7 -0
  48. package/dist/primitives/date-picker.js +216 -0
  49. package/dist/primitives/date-picker.js.map +7 -0
  50. package/dist/primitives/date-range-picker.js +239 -0
  51. package/dist/primitives/date-range-picker.js.map +7 -0
  52. package/dist/primitives/digit-input.js +157 -0
  53. package/dist/primitives/digit-input.js.map +7 -0
  54. package/dist/primitives/empty-state.js +93 -0
  55. package/dist/primitives/empty-state.js.map +7 -0
  56. package/dist/primitives/inline-input.js +29 -0
  57. package/dist/primitives/inline-input.js.map +7 -0
  58. package/dist/primitives/inline-select.js +41 -0
  59. package/dist/primitives/inline-select.js.map +7 -0
  60. package/dist/primitives/notification-stack.js +116 -0
  61. package/dist/primitives/notification-stack.js.map +7 -0
  62. package/dist/primitives/notification.js +62 -0
  63. package/dist/primitives/notification.js.map +7 -0
  64. package/dist/primitives/rich-editor.js +1230 -0
  65. package/dist/primitives/rich-editor.js.map +7 -0
  66. package/dist/primitives/select.js +1 -0
  67. package/dist/primitives/select.js.map +2 -2
  68. package/dist/primitives/skeleton.js +55 -0
  69. package/dist/primitives/skeleton.js.map +7 -0
  70. package/dist/primitives/tag-input.js +186 -0
  71. package/dist/primitives/tag-input.js.map +7 -0
  72. package/dist/primitives/tag.js +66 -13
  73. package/dist/primitives/tag.js.map +2 -2
  74. package/dist/primitives/time-picker.js +793 -0
  75. package/dist/primitives/time-picker.js.map +7 -0
  76. package/package.json +4 -3
  77. package/src/backend/CrudForm.tsx +61 -113
  78. package/src/backend/DataTable.tsx +17 -5
  79. package/src/backend/EmptyState.tsx +13 -63
  80. package/src/backend/FilterOverlay.tsx +38 -22
  81. package/src/backend/FlashMessages.tsx +23 -24
  82. package/src/backend/JsonBuilder.tsx +4 -2
  83. package/src/backend/LogList.tsx +109 -0
  84. package/src/backend/__tests__/CrudForm.datetime.test.tsx +12 -7
  85. package/src/backend/__tests__/FilterOverlay.dateRange.test.tsx +89 -0
  86. package/src/backend/__tests__/LogList.test.tsx +163 -0
  87. package/src/backend/crud/CollapsibleGroup.tsx +17 -3
  88. package/src/backend/detail/InlineEditors.tsx +78 -25
  89. package/src/backend/detail/__tests__/InlineEditors.test.tsx +81 -1
  90. package/src/backend/inputs/ComboboxInput.tsx +81 -9
  91. package/src/backend/inputs/DatePicker.tsx +28 -155
  92. package/src/backend/inputs/DateTimePicker.tsx +25 -193
  93. package/src/backend/inputs/TagsInput.tsx +10 -13
  94. package/src/backend/inputs/TimeInput.tsx +2 -1
  95. package/src/backend/inputs/TimePicker.tsx +99 -70
  96. package/src/backend/inputs/__tests__/ComboboxInput.test.tsx +133 -0
  97. package/src/backend/inputs/__tests__/TimePicker.test.tsx +2 -2
  98. package/src/backend/utils/__tests__/richTextSanitizer.test.ts +5 -2
  99. package/src/backend/utils/customFieldForms.ts +2 -2
  100. package/src/portal/components/PortalEmptyState.tsx +27 -22
  101. package/src/primitives/__tests__/accordion.test.tsx +197 -0
  102. package/src/primitives/__tests__/alert.test.tsx +204 -0
  103. package/src/primitives/__tests__/compact-select.test.tsx +98 -0
  104. package/src/primitives/__tests__/counter-input.test.tsx +165 -0
  105. package/src/primitives/__tests__/date-picker.test.tsx +221 -0
  106. package/src/primitives/__tests__/date-range-picker.test.tsx +173 -0
  107. package/src/primitives/__tests__/digit-input.test.tsx +168 -0
  108. package/src/primitives/__tests__/empty-state.test.tsx +154 -0
  109. package/src/primitives/__tests__/inline-input.test.tsx +100 -0
  110. package/src/primitives/__tests__/inline-select.test.tsx +103 -0
  111. package/src/primitives/__tests__/notification-stack.test.tsx +174 -0
  112. package/src/primitives/__tests__/notification.test.tsx +119 -0
  113. package/src/primitives/__tests__/rich-editor.test.tsx +411 -0
  114. package/src/primitives/__tests__/skeleton.test.tsx +76 -0
  115. package/src/primitives/__tests__/tag-input.test.tsx +198 -0
  116. package/src/primitives/__tests__/tag.test.tsx +123 -0
  117. package/src/primitives/__tests__/time-picker.test.tsx +392 -0
  118. package/src/primitives/accordion.tsx +225 -0
  119. package/src/primitives/alert.tsx +234 -24
  120. package/src/primitives/calendar.tsx +146 -38
  121. package/src/primitives/compact-select.tsx +59 -0
  122. package/src/primitives/counter-input.tsx +211 -0
  123. package/src/primitives/date-picker-helpers.ts +96 -0
  124. package/src/primitives/date-picker.tsx +290 -0
  125. package/src/primitives/date-range-picker.tsx +281 -0
  126. package/src/primitives/digit-input.tsx +208 -0
  127. package/src/primitives/empty-state.tsx +140 -0
  128. package/src/primitives/inline-input.tsx +55 -0
  129. package/src/primitives/inline-select.tsx +74 -0
  130. package/src/primitives/notification-stack.tsx +185 -0
  131. package/src/primitives/notification.tsx +136 -0
  132. package/src/primitives/rich-editor.tsx +1578 -0
  133. package/src/primitives/select.tsx +1 -0
  134. package/src/primitives/skeleton.tsx +70 -0
  135. package/src/primitives/tag-input.tsx +223 -0
  136. package/src/primitives/tag.tsx +69 -10
  137. package/src/primitives/time-picker.tsx +1059 -0
@@ -1,3 +1,3 @@
1
1
  Generated lucide registry with 134 icons -> /home/runner/work/open-mercato/open-mercato/packages/ui/src/backend/icons/lucideRegistry.generated.tsx
2
- [build:ui] found 312 entry points
2
+ [build:ui] found 329 entry points
3
3
  [build:ui] built successfully
@@ -93,7 +93,7 @@ import { useGroupOrder } from "./crud/useGroupOrder.js";
93
93
  import { InjectedField } from "./injection/InjectedField.js";
94
94
  import { evaluateInjectedVisibility } from "./injection/visibility-utils.js";
95
95
  import { ComponentReplacementHandles } from "@open-mercato/shared/modules/widgets/component-registry";
96
- import { sanitizeHtmlRichText, sanitizeRichTextHref, sanitizeRichTextPasteContent } from "./utils/richTextSanitizer.js";
96
+ import { RichEditor } from "../primitives/rich-editor.js";
97
97
  const EMPTY_OPTIONS = [];
98
98
  const SELECT_CLEAR_SENTINEL = "__crudform_select_clear__";
99
99
  const FOCUSABLE_SELECTOR = '[data-crud-focus-target], input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
@@ -2913,120 +2913,27 @@ const MarkdownEditor = React.memo(function MarkdownEditor2({ value = "", onChang
2913
2913
  }
2914
2914
  ) });
2915
2915
  }, (prev, next) => prev.value === next.value);
2916
- const HtmlRichTextEditor = React.memo(function HtmlRichTextEditor2({ value = "", onChange }) {
2916
+ const HtmlRichEditorField = React.memo(function HtmlRichEditorField2({ value = "", onChange }) {
2917
2917
  const t = useT();
2918
- const boldLabel = t("ui.forms.richtext.bold");
2919
- const italicLabel = t("ui.forms.richtext.italic");
2920
- const underlineLabel = t("ui.forms.richtext.underline");
2921
- const listLabel = t("ui.forms.richtext.list");
2922
- const heading3Label = t("ui.forms.richtext.heading3");
2923
- const linkLabel = t("ui.forms.richtext.link");
2924
- const linkUrlPrompt = t("ui.forms.richtext.linkUrlPrompt");
2925
- const ref = React.useRef(null);
2926
- const applyingExternal = React.useRef(false);
2927
- const typingRef = React.useRef(false);
2928
- React.useEffect(() => {
2929
- const el = ref.current;
2930
- if (!el) return;
2931
- const current = el.innerHTML;
2932
- const sanitizedValue = sanitizeHtmlRichText(value);
2933
- if (!typingRef.current && current !== sanitizedValue) {
2934
- applyingExternal.current = true;
2935
- el.innerHTML = sanitizedValue;
2936
- requestAnimationFrame(() => {
2937
- applyingExternal.current = false;
2938
- });
2939
- }
2940
- }, [value]);
2941
- const exec = (cmd, arg) => {
2942
- const el = ref.current;
2943
- if (!el) return;
2944
- el.focus();
2945
- try {
2946
- document.execCommand(cmd, false, arg);
2947
- } catch {
2948
- }
2949
- };
2950
- const onKeyDown = (e) => {
2951
- const isMod = e.metaKey || e.ctrlKey;
2952
- if (!isMod) return;
2953
- const k = e.key.toLowerCase();
2954
- if (k === "b") {
2955
- e.preventDefault();
2956
- exec("bold");
2957
- }
2958
- if (k === "i") {
2959
- e.preventDefault();
2960
- exec("italic");
2961
- }
2962
- if (k === "u") {
2963
- e.preventDefault();
2964
- exec("underline");
2965
- }
2966
- };
2967
- const onPaste = (e) => {
2968
- const html = e.clipboardData.getData("text/html");
2969
- const text = e.clipboardData.getData("text/plain");
2970
- const sanitizedPaste = sanitizeRichTextPasteContent(html, text);
2971
- if (!sanitizedPaste) return;
2972
- e.preventDefault();
2973
- exec(sanitizedPaste.command, sanitizedPaste.value);
2974
- };
2975
- return /* @__PURE__ */ jsxs("div", { className: "w-full rounded border", children: [
2976
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 px-2 py-1 border-b", children: [
2977
- /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", className: "h-auto px-2 py-0.5 text-xs", onMouseDown: (e) => e.preventDefault(), onClick: () => exec("bold"), children: boldLabel }),
2978
- /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", className: "h-auto px-2 py-0.5 text-xs", onMouseDown: (e) => e.preventDefault(), onClick: () => exec("italic"), children: italicLabel }),
2979
- /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", className: "h-auto px-2 py-0.5 text-xs", onMouseDown: (e) => e.preventDefault(), onClick: () => exec("underline"), children: underlineLabel }),
2980
- /* @__PURE__ */ jsx("span", { className: "mx-2 text-muted-foreground", children: "|" }),
2981
- /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", className: "h-auto px-2 py-0.5 text-xs", onMouseDown: (e) => e.preventDefault(), onClick: () => exec("insertUnorderedList"), children: [
2982
- "\u2022 ",
2983
- listLabel
2984
- ] }),
2985
- /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", className: "h-auto px-2 py-0.5 text-xs", onMouseDown: (e) => e.preventDefault(), onClick: () => exec("formatBlock", "<h3>"), children: heading3Label }),
2986
- /* @__PURE__ */ jsx(
2987
- Button,
2988
- {
2989
- variant: "ghost",
2990
- size: "sm",
2991
- className: "h-auto px-2 py-0.5 text-xs",
2992
- onMouseDown: (e) => e.preventDefault(),
2993
- onClick: () => {
2994
- const url = sanitizeRichTextHref(window.prompt(linkUrlPrompt));
2995
- if (url) exec("createLink", url);
2996
- },
2997
- children: linkLabel
2998
- }
2999
- )
3000
- ] }),
3001
- /* @__PURE__ */ jsx(
3002
- "div",
3003
- {
3004
- ref,
3005
- className: "w-full px-2 py-2 min-h-[100px] sm:min-h-[160px] focus-visible:outline-none prose prose-sm max-w-none",
3006
- contentEditable: true,
3007
- suppressContentEditableWarning: true,
3008
- onKeyDown,
3009
- onPaste,
3010
- onInput: () => {
3011
- if (!applyingExternal.current) typingRef.current = true;
3012
- },
3013
- onBlur: () => {
3014
- const el = ref.current;
3015
- if (!el) return;
3016
- typingRef.current = false;
3017
- const sanitizedValue = sanitizeHtmlRichText(el.innerHTML);
3018
- if (el.innerHTML !== sanitizedValue) {
3019
- applyingExternal.current = true;
3020
- el.innerHTML = sanitizedValue;
3021
- requestAnimationFrame(() => {
3022
- applyingExternal.current = false;
3023
- });
3024
- }
3025
- onChange(sanitizedValue);
3026
- }
3027
- }
3028
- )
3029
- ] });
2918
+ const labels = React.useMemo(() => ({
2919
+ bold: t("ui.forms.richtext.bold"),
2920
+ italic: t("ui.forms.richtext.italic"),
2921
+ underline: t("ui.forms.richtext.underline"),
2922
+ unorderedList: t("ui.forms.richtext.list"),
2923
+ orderedList: t("ui.forms.richtext.orderedList", "Numbered list"),
2924
+ heading: t("ui.forms.richtext.heading", "Heading"),
2925
+ heading1: t("ui.forms.richtext.heading1", "Heading 1"),
2926
+ heading2: t("ui.forms.richtext.heading2", "Heading 2"),
2927
+ heading3: t("ui.forms.richtext.heading3"),
2928
+ paragraph: t("ui.forms.richtext.paragraph", "Paragraph"),
2929
+ link: t("ui.forms.richtext.link"),
2930
+ linkUrlPrompt: t("ui.forms.richtext.linkUrlPrompt"),
2931
+ placeholder: t("ui.forms.richtext.placeholder"),
2932
+ comment: t("ui.forms.richtext.comment", "Add comment"),
2933
+ mention: t("ui.forms.richtext.mention", "Mention"),
2934
+ more: t("ui.forms.richtext.more", "More")
2935
+ }), [t]);
2936
+ return /* @__PURE__ */ jsx(RichEditor, { value, onChange, variant: "full", labels });
3030
2937
  }, (prev, next) => prev.value === next.value);
3031
2938
  const SimpleMarkdownEditor = React.memo(function SimpleMarkdownEditor2({ value = "", onChange }) {
3032
2939
  const t = useT();
@@ -3252,25 +3159,33 @@ const FieldControl = React.memo(
3252
3159
  }
3253
3160
  ),
3254
3161
  field.type === "date" && /* @__PURE__ */ jsx(
3255
- Input,
3162
+ DatePicker,
3256
3163
  {
3257
- type: "date",
3258
- value: typeof value === "string" ? value : "",
3259
- onChange: (e) => setValue(field.id, e.target.value || void 0),
3260
- autoFocus: autoFocusField,
3261
- "data-crud-focus-target": "",
3262
- disabled
3164
+ value: typeof value === "string" && value ? parseISO(value) : value instanceof Date ? value : null,
3165
+ onChange: (date) => setValue(field.id, date ? format(date, "yyyy-MM-dd") : void 0),
3166
+ disabled,
3167
+ readOnly,
3168
+ placeholder,
3169
+ minDate: builtin?.minDate,
3170
+ maxDate: builtin?.maxDate,
3171
+ displayFormat: builtin?.displayFormat,
3172
+ closeOnSelect: builtin?.closeOnSelect,
3173
+ locale: builtin?.locale
3263
3174
  }
3264
3175
  ),
3265
3176
  field.type === "datetime-local" && /* @__PURE__ */ jsx(
3266
- Input,
3177
+ DateTimePicker,
3267
3178
  {
3268
- type: "datetime-local",
3269
- value: typeof value === "string" ? value : "",
3270
- onChange: (e) => setValue(field.id, e.target.value || void 0),
3271
- autoFocus: autoFocusField,
3272
- "data-crud-focus-target": "",
3273
- disabled
3179
+ value: typeof value === "string" && value ? new Date(value) : value instanceof Date ? value : null,
3180
+ onChange: (date) => setValue(field.id, date ? format(date, "yyyy-MM-dd'T'HH:mm") : void 0),
3181
+ disabled,
3182
+ readOnly,
3183
+ placeholder,
3184
+ minuteStep: builtin?.minuteStep,
3185
+ minDate: builtin?.minDate,
3186
+ maxDate: builtin?.maxDate,
3187
+ displayFormat: builtin?.displayFormat,
3188
+ locale: builtin?.locale
3274
3189
  }
3275
3190
  ),
3276
3191
  field.type === "datepicker" && /* @__PURE__ */ jsx(
@@ -3328,7 +3243,7 @@ const FieldControl = React.memo(
3328
3243
  }
3329
3244
  ),
3330
3245
  field.type === "richtext" && builtin?.editor === "simple" && /* @__PURE__ */ jsx(SimpleMarkdownEditor, { value: String(value ?? ""), onChange: fieldSetValue }),
3331
- field.type === "richtext" && builtin?.editor === "html" && /* @__PURE__ */ jsx(HtmlRichTextEditor, { value: String(value ?? ""), onChange: fieldSetValue }),
3246
+ field.type === "richtext" && builtin?.editor === "html" && /* @__PURE__ */ jsx(HtmlRichEditorField, { value: String(value ?? ""), onChange: fieldSetValue }),
3332
3247
  field.type === "richtext" && (!builtin?.editor || builtin.editor !== "simple" && builtin.editor !== "html") && /* @__PURE__ */ jsx(MarkdownEditor, { value: String(value ?? ""), onChange: fieldSetValue }),
3333
3248
  field.type === "tags" && /* @__PURE__ */ jsx(
3334
3249
  TagsInput,
@@ -3353,6 +3268,8 @@ const FieldControl = React.memo(
3353
3268
  placeholder,
3354
3269
  autoFocus: autoFocusField,
3355
3270
  suggestions: builtin?.suggestions ? builtin.suggestions : options.map((opt) => ({ value: opt.value, label: opt.label })),
3271
+ seedOptions: builtin?.seedOptions ? builtin.seedOptions.map((opt) => ({ value: opt.value, label: opt.label })) : void 0,
3272
+ resolveLabel: builtin?.resolveLabel,
3356
3273
  loadSuggestions: typeof builtin?.loadOptions === "function" ? async (query) => {
3357
3274
  const opts = await loadFieldOptions(field, query);
3358
3275
  return opts.map((opt) => ({ value: opt.value, label: opt.label }));