@underverse-ui/underverse 1.0.211 → 2.0.1

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 (30) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +21 -0
  3. package/README.md +243 -706
  4. package/api-reference.json +1 -1
  5. package/dist/{EmojiPicker-FEJJDAWZ.js → EmojiPicker-34YATB7Z.js} +4 -4
  6. package/dist/{chunk-F6A7HJE4.js → chunk-A7XL4RDV.js} +3 -3
  7. package/dist/{chunk-CYCBSKWI.js → chunk-KGNYK5YF.js} +2 -2
  8. package/dist/{chunk-BRDGIALS.js → chunk-PLHJWXCW.js} +24 -30
  9. package/dist/{chunk-BRDGIALS.js.map → chunk-PLHJWXCW.js.map} +1 -1
  10. package/dist/{chunk-GKY5DHGR.js → chunk-UNDGI6ZI.js} +3 -3
  11. package/dist/{chunk-4E43DRP2.js → chunk-Y7SQKJ7X.js} +95 -31
  12. package/dist/chunk-Y7SQKJ7X.js.map +1 -0
  13. package/dist/{chunk-AMAILXHP.js → chunk-Z6WE65J2.js} +44 -18
  14. package/dist/chunk-Z6WE65J2.js.map +1 -0
  15. package/dist/index.cjs +280 -159
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.js +140 -103
  18. package/dist/index.js.map +1 -1
  19. package/dist/{menu-bar-6GS5LLTD.js → menu-bar-AAD3LQTN.js} +4 -4
  20. package/dist/ueditor.cjs +132 -42
  21. package/dist/ueditor.cjs.map +1 -1
  22. package/dist/ueditor.js +4 -4
  23. package/package.json +3 -1
  24. package/dist/chunk-4E43DRP2.js.map +0 -1
  25. package/dist/chunk-AMAILXHP.js.map +0 -1
  26. /package/dist/{EmojiPicker-FEJJDAWZ.js.map → EmojiPicker-34YATB7Z.js.map} +0 -0
  27. /package/dist/{chunk-F6A7HJE4.js.map → chunk-A7XL4RDV.js.map} +0 -0
  28. /package/dist/{chunk-CYCBSKWI.js.map → chunk-KGNYK5YF.js.map} +0 -0
  29. /package/dist/{chunk-GKY5DHGR.js.map → chunk-UNDGI6ZI.js.map} +0 -0
  30. /package/dist/{menu-bar-6GS5LLTD.js.map → menu-bar-AAD3LQTN.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -2077,35 +2077,29 @@ function NextIntlAdapterProvider({
2077
2077
  messages
2078
2078
  }) {
2079
2079
  const normalizedLocale = normalizeLocale(locale, "en");
2080
- const translatorCache = React7.useMemo(
2081
- () => /* @__PURE__ */ new Map(),
2082
- [normalizedLocale, messages]
2083
- );
2084
- const translate = React7.useCallback((namespace, key, values) => {
2085
- let translator = translatorCache.get(namespace);
2086
- if (!translator) {
2087
- const runtimeTranslator = (0, import_next_intl.createTranslator)({
2088
- locale: normalizedLocale,
2089
- messages,
2090
- namespace,
2091
- onError: () => {
2092
- }
2093
- });
2094
- translator = (translationKey, translationValues) => runtimeTranslator(translationKey, translationValues);
2095
- translatorCache.set(namespace, translator);
2096
- }
2097
- try {
2098
- return {
2099
- locale: normalizedLocale,
2100
- translated: translator(key, values)
2101
- };
2102
- } catch {
2103
- return {
2104
- locale: normalizedLocale,
2105
- translated: null
2106
- };
2080
+ const runtimeTranslator = React7.useMemo(() => (0, import_next_intl.createTranslator)({
2081
+ locale: normalizedLocale,
2082
+ messages,
2083
+ onError: () => {
2107
2084
  }
2108
- }, [messages, normalizedLocale, translatorCache]);
2085
+ }), [messages, normalizedLocale]);
2086
+ const translate = React7.useCallback(
2087
+ (namespace, key, values) => {
2088
+ const namespacedKey = namespace ? `${namespace}.${key}` : key;
2089
+ try {
2090
+ return {
2091
+ locale: normalizedLocale,
2092
+ translated: runtimeTranslator(namespacedKey, values)
2093
+ };
2094
+ } catch {
2095
+ return {
2096
+ locale: normalizedLocale,
2097
+ translated: null
2098
+ };
2099
+ }
2100
+ },
2101
+ [normalizedLocale, runtimeTranslator]
2102
+ );
2109
2103
  const value = React7.useMemo(() => ({
2110
2104
  locale: normalizedLocale,
2111
2105
  translate
@@ -2670,7 +2664,7 @@ var init_Tooltip = __esm({
2670
2664
  onBlur: chainEventHandlers(
2671
2665
  triggerPassthroughProps.onBlur,
2672
2666
  childProps.onBlur,
2673
- (e) => {
2667
+ () => {
2674
2668
  handleBlur();
2675
2669
  }
2676
2670
  )
@@ -4934,6 +4928,9 @@ function getClipboardData(dataTransfer, type) {
4934
4928
  return "";
4935
4929
  }
4936
4930
  }
4931
+ function hasClipboardHtmlTable(dataTransfer) {
4932
+ return /<table(?:\s|>)/i.test(getClipboardData(dataTransfer, "text/html"));
4933
+ }
4937
4934
  function extractClipboardHtmlFragment(html) {
4938
4935
  const startMarker = "<!--StartFragment-->";
4939
4936
  const endMarker = "<!--EndFragment-->";
@@ -4944,6 +4941,13 @@ function extractClipboardHtmlFragment(html) {
4944
4941
  }
4945
4942
  return html;
4946
4943
  }
4944
+ function hasMeaningfulContentOutsideTable(container) {
4945
+ const clone = container.cloneNode(true);
4946
+ clone.querySelectorAll("table, style, script, meta, link").forEach((element) => element.remove());
4947
+ const remainingText = (clone.textContent ?? "").replace(/\u00a0/g, " ").replace(/\u200b/g, "").trim();
4948
+ if (remainingText) return true;
4949
+ return !!clone.querySelector("img, video, audio, iframe, object, embed, svg, canvas, hr, input, textarea, select, button");
4950
+ }
4947
4951
  function normalizeClipboardCellText(value) {
4948
4952
  return value.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\u00a0/g, " ").replace(/[ \t]+\n/g, "\n").replace(/\n[ \t]+/g, "\n").replace(/\n+$/g, "").replace(/^\n+/g, "").trim();
4949
4953
  }
@@ -5554,7 +5558,10 @@ function getClipboardTableContent(dataTransfer) {
5554
5558
  const fragment = extractClipboardHtmlFragment(html);
5555
5559
  const fragmentDoc = new DOMParser().parseFromString(fragment, "text/html");
5556
5560
  const styleMap = parseClipboardCssClassStyles(doc);
5557
- const table = fragmentDoc.querySelector("table") ?? doc.querySelector("table");
5561
+ const sourceBody = fragmentDoc.querySelector("table") ? fragmentDoc.body : doc.body;
5562
+ const tables = sourceBody.querySelectorAll("table");
5563
+ if (tables.length !== 1 || hasMeaningfulContentOutsideTable(sourceBody)) return null;
5564
+ const table = tables[0];
5558
5565
  if (!(table instanceof HTMLTableElement)) return null;
5559
5566
  return createTableContent(getHtmlTableRows(table, styleMap), 1, {
5560
5567
  backgroundColor: DEFAULT_HTML_TABLE_CELL_BACKGROUND_COLOR
@@ -5733,6 +5740,7 @@ var init_clipboard_images = __esm({
5733
5740
  editor.chain().focus().insertContent(tableContent).run();
5734
5741
  return true;
5735
5742
  }
5743
+ if (hasClipboardHtmlTable(event.clipboardData)) return false;
5736
5744
  const tsvTableContent = getClipboardTsvTableContent(event.clipboardData);
5737
5745
  if (tsvTableContent) {
5738
5746
  event.preventDefault();
@@ -6422,7 +6430,7 @@ var init_colors = __esm({
6422
6430
  "src/components/UEditor/colors.tsx"() {
6423
6431
  "use strict";
6424
6432
  "use client";
6425
- import_react71 = require("react");
6433
+ import_react71 = __toESM(require("react"), 1);
6426
6434
  init_useSmartTranslations();
6427
6435
  import_lucide_react50 = require("lucide-react");
6428
6436
  init_cn();
@@ -6590,12 +6598,25 @@ var init_colors = __esm({
6590
6598
  colors,
6591
6599
  currentColor,
6592
6600
  onSelect,
6601
+ onCustomColorSelect,
6593
6602
  label
6594
6603
  }) => {
6595
6604
  const t = useSmartTranslations("UEditor");
6596
6605
  const colorInputRef = (0, import_react71.useRef)(null);
6597
6606
  const automaticColor = colors[0]?.color ?? "";
6598
6607
  const paletteColors = colors.slice(1);
6608
+ const customColorSelect = onCustomColorSelect ?? onSelect;
6609
+ import_react71.default.useEffect(() => {
6610
+ const input = colorInputRef.current;
6611
+ if (!input) return;
6612
+ const commitColor = () => customColorSelect(input.value);
6613
+ input.addEventListener("change", commitColor);
6614
+ return () => input.removeEventListener("change", commitColor);
6615
+ }, [customColorSelect]);
6616
+ import_react71.default.useEffect(() => {
6617
+ const input = colorInputRef.current;
6618
+ if (input) input.value = currentColor.startsWith("#") ? currentColor : "#000000";
6619
+ }, [currentColor]);
6599
6620
  return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "w-56 p-2", children: [
6600
6621
  /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "px-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: label }),
6601
6622
  /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
@@ -6649,20 +6670,19 @@ var init_colors = __esm({
6649
6670
  }
6650
6671
  ),
6651
6672
  /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "flex-1 text-center", children: t("colors.moreColors") }),
6652
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_lucide_react50.Palette, { className: "h-4 w-4 text-muted-foreground" }),
6653
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
6654
- "input",
6655
- {
6656
- ref: colorInputRef,
6657
- type: "color",
6658
- value: currentColor.startsWith("#") ? currentColor : "#000000",
6659
- onChange: (event) => onSelect(event.target.value),
6660
- className: "sr-only",
6661
- tabIndex: -1
6662
- }
6663
- )
6673
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_lucide_react50.Palette, { className: "h-4 w-4 text-muted-foreground" })
6664
6674
  ]
6665
6675
  }
6676
+ ),
6677
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
6678
+ "input",
6679
+ {
6680
+ ref: colorInputRef,
6681
+ type: "color",
6682
+ defaultValue: currentColor.startsWith("#") ? currentColor : "#000000",
6683
+ className: "sr-only",
6684
+ tabIndex: -1
6685
+ }
6666
6686
  )
6667
6687
  ] });
6668
6688
  };
@@ -8242,7 +8262,7 @@ var init_editor_styles = __esm({
8242
8262
  "[&_td]:px-2",
8243
8263
  "[&_td]:py-0",
8244
8264
  "[&_td]:whitespace-normal",
8245
- "[&_td]:[overflow-wrap:anywhere]",
8265
+ "[&_td]:wrap-anywhere",
8246
8266
  "[&_td]:[word-break:normal]",
8247
8267
  "[&_td[data-text-wrap='nowrap']]:whitespace-nowrap",
8248
8268
  "[&_td[data-text-wrap='nowrap']]:[overflow-wrap:normal]",
@@ -8254,7 +8274,7 @@ var init_editor_styles = __esm({
8254
8274
  "[&_th]:px-2",
8255
8275
  "[&_th]:py-0",
8256
8276
  "[&_th]:whitespace-normal",
8257
- "[&_th]:[overflow-wrap:anywhere]",
8277
+ "[&_th]:wrap-anywhere",
8258
8278
  "[&_th]:[word-break:normal]",
8259
8279
  "[&_th[data-text-wrap='nowrap']]:whitespace-nowrap",
8260
8280
  "[&_th[data-text-wrap='nowrap']]:[overflow-wrap:normal]",
@@ -10284,19 +10304,7 @@ function useOverlayScrollbarTarget(targetRef, options = {}) {
10284
10304
  return () => {
10285
10305
  controller.destroy();
10286
10306
  };
10287
- }, [
10288
- targetRef,
10289
- resolved.enabled,
10290
- resolved.theme,
10291
- resolved.visibility,
10292
- resolved.autoHide,
10293
- resolved.autoHideDelay,
10294
- resolved.dragScroll,
10295
- resolved.clickScroll,
10296
- resolved.overflowX,
10297
- resolved.overflowY,
10298
- resolved.exclude
10299
- ]);
10307
+ }, [resolved, targetRef]);
10300
10308
  }
10301
10309
  var OverlayScrollbarProvider_default = OverlayScrollbarProvider;
10302
10310
 
@@ -13702,19 +13710,19 @@ var variantStyles5 = {
13702
13710
  },
13703
13711
  underline: {
13704
13712
  container: "relative border-b border-border/60",
13705
- tab: "relative transition-colors duration-200 pb-3 border-b-2 border-transparent hover:border-primary/30",
13713
+ tab: "relative transition-colors duration-200 border-b-2 border-transparent hover:border-primary/30",
13706
13714
  activeTab: "text-primary border-primary font-semibold",
13707
13715
  inactiveTab: "text-muted-foreground hover:text-foreground"
13708
13716
  },
13709
13717
  card: {
13710
- container: "space-y-1.5 bg-muted/20 p-2 rounded-2xl border border-border/30",
13718
+ container: "bg-muted/20 p-1.5 rounded-2xl border border-border/30",
13711
13719
  tab: "rounded-xl border border-transparent transition-all duration-200",
13712
13720
  activeTab: "bg-primary text-primary-foreground border-primary shadow-md",
13713
13721
  inactiveTab: "text-muted-foreground hover:text-foreground hover:bg-accent/50 hover:border-border/50"
13714
13722
  },
13715
13723
  "underline-card": {
13716
13724
  container: "border-b border-border/60 bg-card/80 backdrop-blur-sm rounded-t-2xl p-1",
13717
- tab: "relative transition-all duration-200 pb-3 px-4 rounded-t-xl border-b-2 border-transparent hover:border-primary/30 hover:bg-accent/30",
13725
+ tab: "relative transition-all duration-200 rounded-t-xl border-b-2 border-transparent hover:border-primary/30 hover:bg-accent/30",
13718
13726
  activeTab: "text-primary border-primary font-semibold bg-accent/30",
13719
13727
  inactiveTab: "text-muted-foreground hover:text-foreground"
13720
13728
  }
@@ -13824,7 +13832,7 @@ var Tabs = ({
13824
13832
  }, [baseId, tabs]);
13825
13833
  const containerClasses = cn(
13826
13834
  "relative",
13827
- orientation === "horizontal" ? "w-full flex space-x-1 overflow-x-auto" : "flex flex-col space-y-1 shrink-0",
13835
+ orientation === "horizontal" ? "w-full flex items-center space-x-1 overflow-x-auto" : "flex flex-col space-y-1 shrink-0",
13828
13836
  variantStyles5[variant].container,
13829
13837
  className
13830
13838
  );
@@ -13859,10 +13867,7 @@ var Tabs = ({
13859
13867
  tab.href && tab.disabled && "pointer-events-none cursor-not-allowed opacity-50"
13860
13868
  );
13861
13869
  const sharedStyle = {
13862
- boxShadow: "none",
13863
- transform: "none",
13864
- outline: "none",
13865
- border: "none"
13870
+ outline: "none"
13866
13871
  };
13867
13872
  const sharedProps = {
13868
13873
  ref: (el) => {
@@ -15307,6 +15312,10 @@ init_radius();
15307
15312
  init_UnderverseConfigContext();
15308
15313
  init_form_control_size();
15309
15314
  var import_jsx_runtime38 = require("react/jsx-runtime");
15315
+ function normalizeToLocalDate(date) {
15316
+ if (!date) return null;
15317
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
15318
+ }
15310
15319
  var DatePicker = ({
15311
15320
  id,
15312
15321
  value,
@@ -15340,16 +15349,15 @@ var DatePicker = ({
15340
15349
  const [isFocused, setIsFocused] = React34.useState(false);
15341
15350
  const [inputValue, setInputValue] = React34.useState("");
15342
15351
  React34.useEffect(() => {
15343
- if (value) {
15344
- const parsed = parseDateString(inputValue, locale);
15345
- const isSame = parsed && parsed.getTime() === value.getTime();
15346
- if (!isSame) {
15347
- setInputValue(formatDateShort(value, locale));
15352
+ setInputValue((currentInput) => {
15353
+ if (value) {
15354
+ const parsed = parseDateString(currentInput, locale);
15355
+ const isSame = parsed && parsed.getTime() === value.getTime();
15356
+ return isSame ? currentInput : formatDateShort(value, locale);
15348
15357
  }
15349
- } else if (!isFocused) {
15350
- setInputValue("");
15351
- }
15352
- }, [value, locale, isFocused]);
15358
+ return isFocused ? currentInput : "";
15359
+ });
15360
+ }, [isFocused, locale, value]);
15353
15361
  const handleInputChange = (e) => {
15354
15362
  const text = e.target.value;
15355
15363
  setInputValue(text);
@@ -15368,7 +15376,7 @@ var DatePicker = ({
15368
15376
  if (required) {
15369
15377
  setLocalRequiredError(tv("required"));
15370
15378
  } else {
15371
- onChange(void 0);
15379
+ if (value) onChange(void 0);
15372
15380
  setLocalRequiredError(void 0);
15373
15381
  }
15374
15382
  } else {
@@ -15766,6 +15774,7 @@ var DatePicker = ({
15766
15774
  const autoId = (0, import_react22.useId)();
15767
15775
  const resolvedId = id ? String(id) : `datepicker-${autoId}`;
15768
15776
  const labelId = label ? `${resolvedId}-label` : void 0;
15777
+ const panelId = `${resolvedId}-panel`;
15769
15778
  const labelSize = sizeStyles8[size].label;
15770
15779
  const radiusClass = size === "sm" ? "rounded-md" : "rounded-lg";
15771
15780
  const verticalGap = size === "sm" ? "space-y-1.5" : size === "lg" ? "space-y-2.5" : "space-y-2";
@@ -15814,6 +15823,7 @@ var DatePicker = ({
15814
15823
  {
15815
15824
  open: isOpen,
15816
15825
  onOpenChange: setIsOpen,
15826
+ contentProps: { id: panelId },
15817
15827
  placement: "bottom-start",
15818
15828
  disabled,
15819
15829
  contentWidth: sizeStyles8[size].contentWidth,
@@ -15830,12 +15840,6 @@ var DatePicker = ({
15830
15840
  "div",
15831
15841
  {
15832
15842
  ref: triggerRef,
15833
- id: resolvedId,
15834
- role: "button",
15835
- "aria-label": value ? formatDateDisplay(value) : placeholder || t("placeholder"),
15836
- "aria-labelledby": labelId,
15837
- "aria-required": required,
15838
- "aria-invalid": !!effectiveError,
15839
15843
  className: cn(
15840
15844
  "group flex w-full items-center justify-between border bg-background/80 backdrop-blur-sm",
15841
15845
  formControlFixedClass,
@@ -15867,8 +15871,16 @@ var DatePicker = ({
15867
15871
  "input",
15868
15872
  {
15869
15873
  ref: inputRef,
15874
+ id: resolvedId,
15870
15875
  type: "text",
15876
+ role: "combobox",
15871
15877
  "aria-label": value ? formatDateDisplay(value) : placeholder || t("placeholder"),
15878
+ "aria-labelledby": labelId,
15879
+ "aria-haspopup": "dialog",
15880
+ "aria-expanded": isOpen,
15881
+ "aria-controls": panelId,
15882
+ "aria-required": required,
15883
+ "aria-invalid": !!effectiveError,
15872
15884
  disabled,
15873
15885
  placeholder: placeholder || t("placeholder"),
15874
15886
  value: isFocused ? inputValue : value ? formatDateDisplay(value) : "",
@@ -15975,19 +15987,18 @@ var DateRangePicker = ({
15975
15987
  return `${startStr} - ${formatDateShort(e, locale)}`;
15976
15988
  }, [locale]);
15977
15989
  React34.useEffect(() => {
15978
- if (startDate) {
15979
- const parts = inputValue.split(/\s*-\s*/);
15980
- const inputStart = parts[0] ? parseDateString(parts[0], locale) : null;
15981
- const inputEnd = parts[1] ? parseDateString(parts[1], locale) : null;
15982
- const startSame = inputStart && startDate && inputStart.getTime() === startDate.getTime();
15983
- const endSame = !endDate && !inputEnd || endDate && inputEnd && endDate.getTime() === inputEnd.getTime();
15984
- if (!(startSame && endSame)) {
15985
- setInputValue(getRangeString(startDate, endDate));
15986
- }
15987
- } else if (!isFocused) {
15988
- setInputValue("");
15989
- }
15990
- }, [startDate, endDate, locale, isFocused, getRangeString]);
15990
+ setInputValue((currentInput) => {
15991
+ if (startDate) {
15992
+ const parts = currentInput.split(/\s*-\s*/);
15993
+ const inputStart = parts[0] ? parseDateString(parts[0], locale) : null;
15994
+ const inputEnd = parts[1] ? parseDateString(parts[1], locale) : null;
15995
+ const startSame = inputStart && inputStart.getTime() === startDate.getTime();
15996
+ const endSame = !endDate && !inputEnd || endDate && inputEnd && endDate.getTime() === inputEnd.getTime();
15997
+ return startSame && endSame ? currentInput : getRangeString(startDate, endDate);
15998
+ }
15999
+ return isFocused ? currentInput : "";
16000
+ });
16001
+ }, [endDate, getRangeString, isFocused, locale, startDate]);
15991
16002
  const handleInputChange = (e) => {
15992
16003
  const text = e.target.value;
15993
16004
  setInputValue(text);
@@ -16036,7 +16047,7 @@ var DateRangePicker = ({
16036
16047
  } else {
16037
16048
  setTempStart(null);
16038
16049
  setTempEnd(null);
16039
- onChange(void 0, void 0);
16050
+ if (startDate || endDate) onChange(void 0, void 0);
16040
16051
  setLocalRequiredError(void 0);
16041
16052
  }
16042
16053
  } else {
@@ -16067,8 +16078,8 @@ var DateRangePicker = ({
16067
16078
  }
16068
16079
  }
16069
16080
  if (startDate) {
16070
- setTempStart(normalizeToLocal(startDate));
16071
- setTempEnd(normalizeToLocal(endDate));
16081
+ setTempStart(normalizeToLocalDate(startDate));
16082
+ setTempEnd(normalizeToLocalDate(endDate));
16072
16083
  setInputValue(getRangeString(startDate, endDate));
16073
16084
  setLocalRequiredError(void 0);
16074
16085
  } else {
@@ -16172,21 +16183,17 @@ var DateRangePicker = ({
16172
16183
  footerMargin: "mt-5 pt-4 gap-2.5"
16173
16184
  }
16174
16185
  };
16175
- const normalizeToLocal = (date) => {
16176
- if (!date) return null;
16177
- return new Date(date.getFullYear(), date.getMonth(), date.getDate());
16178
- };
16179
- const minDay = React34.useMemo(() => normalizeToLocal(minDate), [minDate]);
16180
- const maxDay = React34.useMemo(() => normalizeToLocal(maxDate), [maxDate]);
16186
+ const minDay = normalizeToLocalDate(minDate);
16187
+ const maxDay = normalizeToLocalDate(maxDate);
16181
16188
  const [viewDate, setViewDate] = React34.useState(startDate || /* @__PURE__ */ new Date());
16182
- const [tempStart, setTempStart] = React34.useState(normalizeToLocal(startDate));
16183
- const [tempEnd, setTempEnd] = React34.useState(normalizeToLocal(endDate));
16189
+ const [tempStart, setTempStart] = React34.useState(normalizeToLocalDate(startDate));
16190
+ const [tempEnd, setTempEnd] = React34.useState(normalizeToLocalDate(endDate));
16184
16191
  const [hoveredDate, setHoveredDate] = React34.useState(null);
16185
16192
  React34.useEffect(() => {
16186
- setTempStart(normalizeToLocal(startDate));
16193
+ setTempStart(normalizeToLocalDate(startDate));
16187
16194
  }, [startDate]);
16188
16195
  React34.useEffect(() => {
16189
- setTempEnd(normalizeToLocal(endDate));
16196
+ setTempEnd(normalizeToLocalDate(endDate));
16190
16197
  }, [endDate]);
16191
16198
  React34.useEffect(() => {
16192
16199
  if (!isOpen) {
@@ -16205,12 +16212,12 @@ var DateRangePicker = ({
16205
16212
  const inRange = (d, s, e) => d > s && d < e;
16206
16213
  const getDaysInMonth = (d) => new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
16207
16214
  const getFirstDayOfMonth = (d) => new Date(d.getFullYear(), d.getMonth(), 1).getDay();
16208
- const navigateMonth = React34.useCallback((direction) => {
16215
+ const navigateMonth = (direction) => {
16209
16216
  setViewDate((prev) => new Date(prev.getFullYear(), prev.getMonth() + (direction === "next" ? 1 : -1), 1));
16210
- }, []);
16211
- const navigateYearRange = React34.useCallback((direction) => {
16217
+ };
16218
+ const navigateYearRange = (direction) => {
16212
16219
  setViewDate((prev) => new Date(prev.getFullYear() + (direction === "next" ? 12 : -12), prev.getMonth(), 1));
16213
- }, []);
16220
+ };
16214
16221
  const isElementVerticallyScrollable = (el) => {
16215
16222
  const style = window.getComputedStyle(el);
16216
16223
  const overflowY = style.overflowY;
@@ -16239,11 +16246,13 @@ var DateRangePicker = ({
16239
16246
  const steps = Math.trunc(wheelDeltaRef.current / threshold);
16240
16247
  wheelDeltaRef.current -= steps * threshold;
16241
16248
  const direction = steps > 0 ? "next" : "prev";
16242
- for (let i = 0; i < Math.abs(steps); i++) navigateMonth(direction);
16249
+ for (let i = 0; i < Math.abs(steps); i++) {
16250
+ setViewDate((prev) => new Date(prev.getFullYear(), prev.getMonth() + (direction === "next" ? 1 : -1), 1));
16251
+ }
16243
16252
  };
16244
16253
  container.addEventListener("wheel", onWheel, { passive: false });
16245
16254
  return () => container.removeEventListener("wheel", onWheel);
16246
- }, [isOpen, navigateMonth]);
16255
+ }, [isOpen]);
16247
16256
  const handleSelect = (date) => {
16248
16257
  const localDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
16249
16258
  if (!tempStart || tempStart && tempEnd) {
@@ -16526,6 +16535,7 @@ var DateRangePicker = ({
16526
16535
  const autoId = (0, import_react22.useId)();
16527
16536
  const resolvedId = id ? String(id) : `daterangepicker-${autoId}`;
16528
16537
  const labelId = label ? `${resolvedId}-label` : void 0;
16538
+ const panelId = `${resolvedId}-panel`;
16529
16539
  const globalConfig = useUnderverseUIConfig();
16530
16540
  const resolvedBorderMode = borderMode ?? globalConfig.borderMode ?? "full";
16531
16541
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: cn("space-y-1.5", className), children: [
@@ -16570,6 +16580,7 @@ var DateRangePicker = ({
16570
16580
  {
16571
16581
  open: isOpen,
16572
16582
  onOpenChange: setIsOpen,
16583
+ contentProps: { id: panelId },
16573
16584
  placement: "bottom-start",
16574
16585
  disabled,
16575
16586
  contentWidth: sizeStyles8[size].contentWidth,
@@ -16585,12 +16596,6 @@ var DateRangePicker = ({
16585
16596
  "div",
16586
16597
  {
16587
16598
  ref: triggerRef,
16588
- id: resolvedId,
16589
- role: "button",
16590
- "aria-label": tempStart ? displayLabel : placeholder,
16591
- "aria-labelledby": labelId,
16592
- "aria-required": required,
16593
- "aria-invalid": !!effectiveError,
16594
16599
  className: cn(
16595
16600
  "group flex w-full items-center justify-between border bg-background/80 backdrop-blur-sm",
16596
16601
  formControlFixedClass,
@@ -16621,8 +16626,16 @@ var DateRangePicker = ({
16621
16626
  "input",
16622
16627
  {
16623
16628
  ref: inputRef,
16629
+ id: resolvedId,
16624
16630
  type: "text",
16631
+ role: "combobox",
16625
16632
  "aria-label": tempStart ? displayLabel : placeholder,
16633
+ "aria-labelledby": labelId,
16634
+ "aria-haspopup": "dialog",
16635
+ "aria-expanded": isOpen,
16636
+ "aria-controls": panelId,
16637
+ "aria-required": required,
16638
+ "aria-invalid": !!effectiveError,
16626
16639
  disabled,
16627
16640
  placeholder,
16628
16641
  value: isFocused ? inputValue : tempStart ? displayLabel : "",
@@ -17464,6 +17477,7 @@ var LunarDatePicker = ({
17464
17477
  const autoId = (0, import_react23.useId)();
17465
17478
  const resolvedId = id ? String(id) : `lunar-datepicker-${autoId}`;
17466
17479
  const labelId = label ? `${resolvedId}-label` : void 0;
17480
+ const panelId = `${resolvedId}-panel`;
17467
17481
  const labelSize = sizeStyles8[size].label;
17468
17482
  const verticalGap = size === "sm" ? "space-y-1.5" : size === "lg" ? "space-y-2.5" : "space-y-2";
17469
17483
  const effectiveError = localRequiredError;
@@ -17509,6 +17523,7 @@ var LunarDatePicker = ({
17509
17523
  {
17510
17524
  open: isOpen,
17511
17525
  onOpenChange: setIsOpen,
17526
+ contentProps: { id: panelId },
17512
17527
  placement: "bottom-start",
17513
17528
  borderMode: resolvedBorderMode,
17514
17529
  disabled,
@@ -17525,12 +17540,6 @@ var LunarDatePicker = ({
17525
17540
  "div",
17526
17541
  {
17527
17542
  ref: triggerRef,
17528
- id: resolvedId,
17529
- role: "button",
17530
- "aria-label": value ? formatDateDisplay(value) : placeholder || t("placeholder"),
17531
- "aria-labelledby": labelId,
17532
- "aria-required": required,
17533
- "aria-invalid": !!effectiveError,
17534
17543
  className: cn(
17535
17544
  "group flex w-full items-center justify-between border bg-background/80 backdrop-blur-sm",
17536
17545
  formControlFixedClass,
@@ -17562,8 +17571,16 @@ var LunarDatePicker = ({
17562
17571
  "input",
17563
17572
  {
17564
17573
  ref: inputRef,
17574
+ id: resolvedId,
17565
17575
  type: "text",
17576
+ role: "combobox",
17566
17577
  "aria-label": value ? formatDateDisplay(value) : placeholder || t("placeholder"),
17578
+ "aria-labelledby": labelId,
17579
+ "aria-haspopup": "dialog",
17580
+ "aria-expanded": isOpen,
17581
+ "aria-controls": panelId,
17582
+ "aria-required": required,
17583
+ "aria-invalid": !!effectiveError,
17567
17584
  disabled,
17568
17585
  placeholder: placeholder || t("placeholder"),
17569
17586
  value: isFocused ? inputValue : value ? formatDateDisplay(value) : "",
@@ -18090,6 +18107,7 @@ var LunarDateRangePicker = ({
18090
18107
  const autoId = (0, import_react23.useId)();
18091
18108
  const resolvedId = id ? String(id) : `lunardaterangepicker-${autoId}`;
18092
18109
  const labelId = label ? `${resolvedId}-label` : void 0;
18110
+ const panelId = `${resolvedId}-panel`;
18093
18111
  return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: cn("space-y-1.5", className), children: [
18094
18112
  label && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
18095
18113
  "label",
@@ -18132,6 +18150,7 @@ var LunarDateRangePicker = ({
18132
18150
  {
18133
18151
  open: isOpen,
18134
18152
  onOpenChange: setIsOpen,
18153
+ contentProps: { id: panelId },
18135
18154
  placement: "bottom-start",
18136
18155
  disabled,
18137
18156
  contentWidth: sizeStyles8[size].contentWidth,
@@ -18144,13 +18163,18 @@ var LunarDateRangePicker = ({
18144
18163
  "animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-300"
18145
18164
  ),
18146
18165
  trigger: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
18147
- "div",
18166
+ "button",
18148
18167
  {
18149
18168
  ref: triggerRef,
18150
18169
  id: resolvedId,
18151
- role: "button",
18170
+ type: "button",
18171
+ role: "combobox",
18172
+ disabled,
18152
18173
  "aria-label": tempStart ? displayLabel : placeholder,
18153
18174
  "aria-labelledby": labelId,
18175
+ "aria-haspopup": "dialog",
18176
+ "aria-expanded": isOpen,
18177
+ "aria-controls": panelId,
18154
18178
  "aria-required": required,
18155
18179
  "aria-invalid": !!effectiveError,
18156
18180
  className: cn(
@@ -18692,6 +18716,9 @@ function MonthYearPicker({
18692
18716
  const resolvedBorderMode = borderMode ?? globalConfig.input?.borderMode ?? globalConfig.borderMode ?? "full";
18693
18717
  const gi18n = useGlobalI18n();
18694
18718
  const tv = useSmartTranslations("ValidationInput");
18719
+ const autoId = React36.useId();
18720
+ const triggerId = `month-year-picker-trigger-${autoId}`;
18721
+ const panelId = `${triggerId}-panel`;
18695
18722
  const now = /* @__PURE__ */ new Date();
18696
18723
  const currentYear = now.getFullYear();
18697
18724
  const resolvedMinYear = minYear ?? minDate?.getFullYear() ?? currentYear - 50;
@@ -18839,11 +18866,14 @@ function MonthYearPicker({
18839
18866
  const trigger = variant === "inline" ? null : /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
18840
18867
  "button",
18841
18868
  {
18869
+ id: triggerId,
18842
18870
  type: "button",
18871
+ role: "combobox",
18843
18872
  disabled,
18844
18873
  "aria-label": gi18n.selectMonthYear ?? "Select month and year",
18845
18874
  "aria-haspopup": "dialog",
18846
18875
  "aria-expanded": open,
18876
+ "aria-controls": panelId,
18847
18877
  "aria-required": required,
18848
18878
  "aria-invalid": !!effectiveError,
18849
18879
  className: cn(
@@ -19067,6 +19097,7 @@ function MonthYearPicker({
19067
19097
  trigger,
19068
19098
  open,
19069
19099
  onOpenChange: handleOpenChange,
19100
+ contentProps: { id: panelId },
19070
19101
  placement: "bottom",
19071
19102
  contentWidth,
19072
19103
  matchTriggerWidth,
@@ -20246,6 +20277,7 @@ function TimePicker({
20246
20277
  const directEditInputRef = React38.useRef(null);
20247
20278
  const triggerId = `time-picker-trigger-${autoId}`;
20248
20279
  const labelId = label ? `time-picker-label-${autoId}` : void 0;
20280
+ const panelId = `${triggerId}-panel`;
20249
20281
  React38.useEffect(() => {
20250
20282
  if (isControlled) {
20251
20283
  const parsed = parseTime(value, format, includeSeconds);
@@ -20556,11 +20588,13 @@ function TimePicker({
20556
20588
  {
20557
20589
  id: triggerId,
20558
20590
  type: "button",
20591
+ role: "combobox",
20559
20592
  disabled,
20560
20593
  "aria-label": gi18n.selectTime ?? "Select time",
20561
20594
  "aria-labelledby": labelId,
20562
20595
  "aria-haspopup": "dialog",
20563
20596
  "aria-expanded": open,
20597
+ "aria-controls": panelId,
20564
20598
  "aria-required": required,
20565
20599
  "aria-invalid": !!effectiveError,
20566
20600
  className: cn(
@@ -21000,6 +21034,7 @@ function TimePicker({
21000
21034
  trigger,
21001
21035
  open,
21002
21036
  onOpenChange: handleOpenChange,
21037
+ contentProps: { id: panelId },
21003
21038
  placement: "bottom-start",
21004
21039
  matchTriggerWidth: shouldMatchTriggerWidth,
21005
21040
  contentWidth: shouldMatchTriggerWidth ? void 0 : contentWidth,
@@ -21059,6 +21094,10 @@ var DateTimePicker = ({
21059
21094
  const t = useSmartTranslations("DateTimePicker");
21060
21095
  const tv = useSmartTranslations("ValidationInput");
21061
21096
  const locale = useSmartLocale();
21097
+ const autoId = React39.useId();
21098
+ const triggerId = `date-time-picker-trigger-${autoId}`;
21099
+ const panelId = `${triggerId}-panel`;
21100
+ const labelId = label ? `${triggerId}-label` : void 0;
21062
21101
  const [open, setOpen] = React39.useState(false);
21063
21102
  const [localRequiredError, setLocalRequiredError] = React39.useState();
21064
21103
  const sizeStyles8 = {
@@ -21199,11 +21238,19 @@ var DateTimePicker = ({
21199
21238
  const weekdays = getWeekdays(locale);
21200
21239
  const effectiveError = localRequiredError;
21201
21240
  return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: cn("space-y-1.5", className), children: [
21202
- label && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("label", { className: cn(sizeStyles8[size].label, "font-medium text-foreground flex items-center gap-1", effectiveError && "text-destructive", labelClassName), children: [
21203
- label,
21204
- " ",
21205
- required && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-destructive", children: "*" })
21206
- ] }),
21241
+ label && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
21242
+ "label",
21243
+ {
21244
+ id: labelId,
21245
+ htmlFor: triggerId,
21246
+ className: cn(sizeStyles8[size].label, "font-medium text-foreground flex items-center gap-1", effectiveError && "text-destructive", labelClassName),
21247
+ children: [
21248
+ label,
21249
+ " ",
21250
+ required && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-destructive", children: "*" })
21251
+ ]
21252
+ }
21253
+ ),
21207
21254
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
21208
21255
  "input",
21209
21256
  {
@@ -21226,11 +21273,19 @@ var DateTimePicker = ({
21226
21273
  {
21227
21274
  open,
21228
21275
  onOpenChange: setOpen,
21276
+ contentProps: { id: panelId },
21229
21277
  trigger: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
21230
21278
  "button",
21231
21279
  {
21280
+ id: triggerId,
21232
21281
  type: "button",
21282
+ role: "combobox",
21233
21283
  disabled,
21284
+ "aria-haspopup": "dialog",
21285
+ "aria-expanded": open,
21286
+ "aria-controls": panelId,
21287
+ "aria-label": labelId ? void 0 : displayValue || placeholder || "Select date & time",
21288
+ "aria-labelledby": labelId,
21234
21289
  "aria-required": required,
21235
21290
  "aria-invalid": !!effectiveError,
21236
21291
  className: cn(
@@ -24768,7 +24823,7 @@ var MultiCombobox = ({
24768
24823
  );
24769
24824
  }),
24770
24825
  hiddenCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: cn("inline-flex items-center bg-muted text-muted-foreground rounded-lg shrink-0", sizeStyles8[size].tag), children: gi18n.moreCount ? gi18n.moreCount(hiddenCount) : `+${hiddenCount} more` })
24771
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: cn(formControlValueClass, "font-medium"), children: gi18n.selectedCount ? gi18n.selectedCount(value.length) : `${value.length} item${value.length > 1 ? "s" : ""} selected` }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: cn(formControlValueClass, "text-muted-foreground"), children: placeholder }) }),
24826
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: cn(formControlValueClass, "font-medium"), children: gi18n.selectedCount ? gi18n.selectedCount(value.length) : `${value.length} item${value.length > 1 ? "s" : ""} selected` }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: cn(formControlValueClass, "text-left text-muted-foreground"), children: placeholder }) }),
24772
24827
  /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex items-center gap-1.5 shrink-0", children: [
24773
24828
  showClear && value.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
24774
24829
  "div",
@@ -31209,6 +31264,7 @@ function DataTableHeader({
31209
31264
  },
31210
31265
  [
31211
31266
  filters,
31267
+ gi18n,
31212
31268
  headerAlign,
31213
31269
  headerMinHeightClass,
31214
31270
  headerTitleClass,
@@ -31217,6 +31273,7 @@ function DataTableHeader({
31217
31273
  setFilters,
31218
31274
  setSort,
31219
31275
  sort,
31276
+ sortByLabel,
31220
31277
  sortIconClass,
31221
31278
  t
31222
31279
  ]
@@ -38567,15 +38624,18 @@ var FloatingMenuContent = ({ editor }) => {
38567
38624
  }
38568
38625
  );
38569
38626
  };
38570
- function applyTableCellBackground(editor, color) {
38627
+ function applyTableCellBackground(editor, color, options = {}) {
38628
+ const shouldFocus = options.focus ?? true;
38571
38629
  const value = color || null;
38572
38630
  const { state, view } = editor;
38573
38631
  const applied = (0, import_tables8.setCellAttr)("backgroundColor", value)(state, view.dispatch.bind(view));
38574
38632
  if (applied) {
38575
- view.focus();
38633
+ if (shouldFocus) view.focus();
38576
38634
  return;
38577
38635
  }
38578
- editor.chain().focus().setCellAttribute("backgroundColor", value).run();
38636
+ const chain = editor.chain();
38637
+ if (shouldFocus) chain.focus();
38638
+ chain.setCellAttribute("backgroundColor", value).run();
38579
38639
  }
38580
38640
  function applyTableCellAttribute2(editor, name, value, options = {}) {
38581
38641
  const shouldFocus = options.focus ?? true;
@@ -38633,6 +38693,30 @@ function BorderPositionPreviewIcon({ position }) {
38633
38693
  showVertical && /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("path", { d: "M10 2V18", strokeWidth: "2" })
38634
38694
  ] });
38635
38695
  }
38696
+ function getBubbleMenuPosition({
38697
+ start,
38698
+ end,
38699
+ menuSize,
38700
+ viewport,
38701
+ offset = 16,
38702
+ padding = 8
38703
+ }) {
38704
+ const selectionTop = Math.min(start.top, end.top);
38705
+ const selectionBottom = Math.max(start.bottom, end.bottom);
38706
+ const spaceAbove = selectionTop - offset - padding;
38707
+ const spaceBelow = viewport.height - padding - selectionBottom - offset;
38708
+ const placement = menuSize.height <= spaceAbove || spaceAbove >= spaceBelow ? "top" : "bottom";
38709
+ const halfWidth = menuSize.width / 2;
38710
+ const minLeft = padding + halfWidth;
38711
+ const maxLeft = viewport.width - padding - halfWidth;
38712
+ const selectionCenter = (start.left + end.left) / 2;
38713
+ const left = maxLeft >= minLeft ? Math.min(maxLeft, Math.max(minLeft, selectionCenter)) : viewport.width / 2;
38714
+ const requestedTop = placement === "top" ? selectionTop - offset : selectionBottom + offset;
38715
+ const minTop = placement === "top" ? padding + menuSize.height : padding;
38716
+ const maxTop = placement === "top" ? viewport.height - padding : viewport.height - padding - menuSize.height;
38717
+ const top = maxTop >= minTop ? Math.min(maxTop, Math.max(minTop, requestedTop)) : Math.max(padding, requestedTop);
38718
+ return { top, left, placement };
38719
+ }
38636
38720
  function getBubbleMenuContext(editor) {
38637
38721
  const { selection } = editor.state;
38638
38722
  if (editor.isActive("image")) return "image";
@@ -38798,24 +38882,34 @@ var BubbleMenuContent = ({
38798
38882
  setActiveColorPalette(null);
38799
38883
  onKeepOpenChange?.(false);
38800
38884
  }, [onKeepOpenChange]);
38801
- const applyInlineColorAndClose = (0, import_react75.useCallback)((color) => {
38885
+ const applyInlineColor = (0, import_react75.useCallback)((color, focus) => {
38802
38886
  if (activeColorPalette === "text") {
38887
+ const chain = editor.chain();
38888
+ if (focus) chain.focus();
38803
38889
  if (color === "inherit") {
38804
- editor.chain().focus().unsetColor().run();
38890
+ chain.unsetColor().run();
38805
38891
  } else {
38806
- editor.chain().focus().setColor(color).run();
38892
+ chain.setColor(color).run();
38807
38893
  }
38808
38894
  } else if (activeColorPalette === "highlight") {
38895
+ const chain = editor.chain();
38896
+ if (focus) chain.focus();
38809
38897
  if (color === "") {
38810
- editor.chain().focus().unsetHighlight().run();
38898
+ chain.unsetHighlight().run();
38811
38899
  } else {
38812
- editor.chain().focus().toggleHighlight({ color }).run();
38900
+ chain.toggleHighlight({ color }).run();
38813
38901
  }
38814
38902
  } else {
38815
- applyTableCellBackground(editor, color);
38903
+ applyTableCellBackground(editor, color, { focus });
38816
38904
  }
38905
+ }, [activeColorPalette, editor]);
38906
+ const applyInlineColorAndClose = (0, import_react75.useCallback)((color) => {
38907
+ applyInlineColor(color, true);
38817
38908
  closeColorPalette();
38818
- }, [activeColorPalette, closeColorPalette, editor]);
38909
+ }, [applyInlineColor, closeColorPalette]);
38910
+ const applyCustomColor = (0, import_react75.useCallback)((color) => {
38911
+ applyInlineColor(color, false);
38912
+ }, [applyInlineColor]);
38819
38913
  (0, import_react75.useEffect)(() => {
38820
38914
  if (!showLinkInput) return;
38821
38915
  const close2 = () => setShowLinkInput(false);
@@ -39010,6 +39104,7 @@ var BubbleMenuContent = ({
39010
39104
  colors: isTextPalette ? textColors : highlightColors,
39011
39105
  currentColor: isTextPalette ? currentTextColor : isHighlightPalette ? currentHighlightColor : currentCellBgColor,
39012
39106
  onSelect: applyInlineColorAndClose,
39107
+ onCustomColorSelect: applyCustomColor,
39013
39108
  label: isTextPalette ? t("colors.textColor") : isHighlightPalette ? t("colors.highlight") : t("tableMenu.cellBackground") || "Cell background"
39014
39109
  }
39015
39110
  ) });
@@ -39296,6 +39391,7 @@ var BubbleMenuContent = ({
39296
39391
  /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
39297
39392
  ToolbarButton,
39298
39393
  {
39394
+ onMouseDown: () => onKeepOpenChange?.(true),
39299
39395
  onClick: () => setActiveColorPalette("cell-bg"),
39300
39396
  active: Boolean(currentCellBgColor),
39301
39397
  title: t("tableMenu.cellBackground") || "Cell background",
@@ -39527,6 +39623,8 @@ var CustomBubbleMenu = ({
39527
39623
  placement: "top"
39528
39624
  });
39529
39625
  const menuRef = (0, import_react75.useRef)(null);
39626
+ const updatePositionRef = (0, import_react75.useRef)(() => {
39627
+ });
39530
39628
  const keepOpenRef = (0, import_react75.useRef)(false);
39531
39629
  const [keepOpen, setKeepOpenState] = (0, import_react75.useState)(false);
39532
39630
  const showTimeoutRef = (0, import_react75.useRef)(null);
@@ -39584,19 +39682,15 @@ var CustomBubbleMenu = ({
39584
39682
  setIsVisible(false);
39585
39683
  return;
39586
39684
  }
39587
- const viewportPadding = 8;
39588
39685
  const menuHeight = menuRef.current?.getBoundingClientRect().height || BUBBLE_MENU_ESTIMATED_HEIGHT;
39589
- const editorTop = view.dom.getBoundingClientRect().top;
39590
- const selectionTop = Math.min(start.top, end.top);
39591
- const selectionBottom = Math.max(start.bottom, end.bottom);
39592
- const hasRoomAboveEditor = selectionTop - BUBBLE_MENU_OFFSET - menuHeight >= editorTop + viewportPadding;
39593
- const placement = hasRoomAboveEditor ? "top" : "bottom";
39594
- const left = Math.min(
39595
- window.innerWidth - viewportPadding,
39596
- Math.max(viewportPadding, (start.left + end.left) / 2)
39597
- );
39598
- const top = placement === "top" ? Math.max(viewportPadding, selectionTop - BUBBLE_MENU_OFFSET) : Math.min(window.innerHeight - viewportPadding, selectionBottom + BUBBLE_MENU_OFFSET);
39599
- setPosition2({ top, left, placement });
39686
+ const menuWidth = menuRef.current?.getBoundingClientRect().width || 0;
39687
+ setPosition2(getBubbleMenuPosition({
39688
+ start,
39689
+ end,
39690
+ menuSize: { width: menuWidth, height: menuHeight },
39691
+ viewport: { width: window.innerWidth, height: window.innerHeight },
39692
+ offset: BUBBLE_MENU_OFFSET
39693
+ }));
39600
39694
  if (keepOpenRef.current) {
39601
39695
  clearShowTimeout();
39602
39696
  setIsVisible(true);
@@ -39625,8 +39719,11 @@ var CustomBubbleMenu = ({
39625
39719
  editor.on("transaction", schedulePositionUpdate);
39626
39720
  editor.on("focus", schedulePositionUpdate);
39627
39721
  editor.on("blur", handleBlur);
39722
+ updatePositionRef.current = updatePosition;
39628
39723
  schedulePositionUpdate();
39629
39724
  return () => {
39725
+ updatePositionRef.current = () => {
39726
+ };
39630
39727
  if (animationFrameId !== null) cancelAnimationFrame(animationFrameId);
39631
39728
  clearShowTimeout();
39632
39729
  editor.off("transaction", schedulePositionUpdate);
@@ -39634,6 +39731,24 @@ var CustomBubbleMenu = ({
39634
39731
  editor.off("blur", handleBlur);
39635
39732
  };
39636
39733
  }, [editor]);
39734
+ (0, import_react75.useEffect)(() => {
39735
+ if (!isVisible || typeof ResizeObserver === "undefined") return;
39736
+ const menu = menuRef.current;
39737
+ if (!menu) return;
39738
+ let animationFrameId = null;
39739
+ const observer = new ResizeObserver(() => {
39740
+ if (animationFrameId !== null) cancelAnimationFrame(animationFrameId);
39741
+ animationFrameId = requestAnimationFrame(() => {
39742
+ animationFrameId = null;
39743
+ updatePositionRef.current();
39744
+ });
39745
+ });
39746
+ observer.observe(menu);
39747
+ return () => {
39748
+ if (animationFrameId !== null) cancelAnimationFrame(animationFrameId);
39749
+ observer.disconnect();
39750
+ };
39751
+ }, [isVisible]);
39637
39752
  (0, import_react75.useEffect)(() => {
39638
39753
  if (!isVisible) return;
39639
39754
  const handlePointerDown = (event) => {
@@ -45190,7 +45305,7 @@ function TableResizeHandles({
45190
45305
  "data-resizing": active ? "true" : "false",
45191
45306
  className: cn(
45192
45307
  "pointer-events-none absolute z-[38] box-border border border-primary/55",
45193
- active && "border-primary bg-primary/[0.03]"
45308
+ active && "border-primary bg-primary/3"
45194
45309
  ),
45195
45310
  style: {
45196
45311
  left: layout.tableLeft,
@@ -47253,11 +47368,17 @@ function useUEditorOutput({
47253
47368
  onJsonChange,
47254
47369
  outputDebounceMs
47255
47370
  }) {
47256
- const callbacksRef = React91.useRef({});
47371
+ const callbacksRef = React91.useRef({
47372
+ onChange,
47373
+ onHtmlChange,
47374
+ onJsonChange
47375
+ });
47257
47376
  const pendingEditorRef = React91.useRef(null);
47258
47377
  const timeoutRef = React91.useRef(null);
47259
47378
  const debounceMs = normalizeDebounceMs(outputDebounceMs);
47260
- callbacksRef.current = { onChange, onHtmlChange, onJsonChange };
47379
+ React91.useLayoutEffect(() => {
47380
+ callbacksRef.current = { onChange, onHtmlChange, onJsonChange };
47381
+ }, [onChange, onHtmlChange, onJsonChange]);
47261
47382
  const flushOutputUpdates = React91.useCallback(() => {
47262
47383
  if (timeoutRef.current !== null) {
47263
47384
  clearTimeout(timeoutRef.current);