@underverse-ui/underverse 1.0.118 → 1.0.120

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/index.d.cts CHANGED
@@ -1890,6 +1890,46 @@ interface CategoryTreeSelectBaseProps {
1890
1890
  minSearchLength?: number;
1891
1891
  /** Show a prompt instead of options while the query is shorter than `minSearchLength`. Default: `false`. */
1892
1892
  showSearchPromptWhenEmptyQuery?: boolean;
1893
+ /**
1894
+ * Render custom actions at the trailing edge of each tree row.
1895
+ *
1896
+ * @remarks
1897
+ * The returned node is placed inside the row flex container, after the label/content area.
1898
+ * Click events on the returned node are stopped from propagating to the row, so action buttons
1899
+ * do not accidentally trigger selection or expansion.
1900
+ *
1901
+ * @example
1902
+ * <CategoryTreeSelect
1903
+ * renderItemActions={(category) => (
1904
+ * <button onClick={() => handleEdit(category)}>Edit</button>
1905
+ * )}
1906
+ * />
1907
+ */
1908
+ renderItemActions?: (category: Category) => React__default.ReactNode;
1909
+ /**
1910
+ * Base left padding in rem applied to every node regardless of depth. Default: `0.75`.
1911
+ *
1912
+ * @remarks
1913
+ * Combined with `indentSize`, the final padding of a node at a given depth is:
1914
+ * `paddingLeft = level * indentSize + baseIndent` rem.
1915
+ *
1916
+ * @example
1917
+ * // Compact sidebar tree
1918
+ * <CategoryTreeSelect baseIndent={0.25} indentSize={0.75} />
1919
+ */
1920
+ baseIndent?: number;
1921
+ /**
1922
+ * Additional left padding in rem added per depth level. Default: `1`.
1923
+ *
1924
+ * @remarks
1925
+ * Set to a smaller value (e.g. `0.75`) to reduce the visual gap between
1926
+ * parent and child nodes without touching DOM styles.
1927
+ *
1928
+ * @example
1929
+ * // Compact sidebar tree
1930
+ * <CategoryTreeSelect baseIndent={0.25} indentSize={0.75} />
1931
+ */
1932
+ indentSize?: number;
1893
1933
  }
1894
1934
  /** Multi-select mode. This is the default when `singleSelect` is omitted. */
1895
1935
  interface CategoryTreeSelectMultiProps extends CategoryTreeSelectBaseProps {
package/dist/index.d.ts CHANGED
@@ -1890,6 +1890,46 @@ interface CategoryTreeSelectBaseProps {
1890
1890
  minSearchLength?: number;
1891
1891
  /** Show a prompt instead of options while the query is shorter than `minSearchLength`. Default: `false`. */
1892
1892
  showSearchPromptWhenEmptyQuery?: boolean;
1893
+ /**
1894
+ * Render custom actions at the trailing edge of each tree row.
1895
+ *
1896
+ * @remarks
1897
+ * The returned node is placed inside the row flex container, after the label/content area.
1898
+ * Click events on the returned node are stopped from propagating to the row, so action buttons
1899
+ * do not accidentally trigger selection or expansion.
1900
+ *
1901
+ * @example
1902
+ * <CategoryTreeSelect
1903
+ * renderItemActions={(category) => (
1904
+ * <button onClick={() => handleEdit(category)}>Edit</button>
1905
+ * )}
1906
+ * />
1907
+ */
1908
+ renderItemActions?: (category: Category) => React__default.ReactNode;
1909
+ /**
1910
+ * Base left padding in rem applied to every node regardless of depth. Default: `0.75`.
1911
+ *
1912
+ * @remarks
1913
+ * Combined with `indentSize`, the final padding of a node at a given depth is:
1914
+ * `paddingLeft = level * indentSize + baseIndent` rem.
1915
+ *
1916
+ * @example
1917
+ * // Compact sidebar tree
1918
+ * <CategoryTreeSelect baseIndent={0.25} indentSize={0.75} />
1919
+ */
1920
+ baseIndent?: number;
1921
+ /**
1922
+ * Additional left padding in rem added per depth level. Default: `1`.
1923
+ *
1924
+ * @remarks
1925
+ * Set to a smaller value (e.g. `0.75`) to reduce the visual gap between
1926
+ * parent and child nodes without touching DOM styles.
1927
+ *
1928
+ * @example
1929
+ * // Compact sidebar tree
1930
+ * <CategoryTreeSelect baseIndent={0.25} indentSize={0.75} />
1931
+ */
1932
+ indentSize?: number;
1893
1933
  }
1894
1934
  /** Multi-select mode. This is the default when `singleSelect` is omitted. */
1895
1935
  interface CategoryTreeSelectMultiProps extends CategoryTreeSelectBaseProps {
package/dist/index.js CHANGED
@@ -2915,6 +2915,10 @@ var Tooltip = React10.forwardRef(({
2915
2915
  setIsOpen(false);
2916
2916
  }, delayClose);
2917
2917
  };
2918
+ const closeNow = React10.useCallback(() => {
2919
+ clearTimeout(timeoutRef.current);
2920
+ setIsOpen(false);
2921
+ }, []);
2918
2922
  const handleFocus = () => {
2919
2923
  if (disabled) return;
2920
2924
  setIsOpen(true);
@@ -2925,6 +2929,10 @@ var Tooltip = React10.forwardRef(({
2925
2929
  React10.useEffect(() => {
2926
2930
  return () => clearTimeout(timeoutRef.current);
2927
2931
  }, []);
2932
+ React10.useEffect(() => {
2933
+ if (isOpen) return;
2934
+ clearTimeout(timeoutRef.current);
2935
+ }, [isOpen]);
2928
2936
  React10.useLayoutEffect(() => {
2929
2937
  if (!isOpen) {
2930
2938
  lastAppliedRef.current = null;
@@ -2968,6 +2976,18 @@ var Tooltip = React10.forwardRef(({
2968
2976
  if (panelRef.current) ro.observe(panelRef.current);
2969
2977
  return () => ro.disconnect();
2970
2978
  }, [isOpen, updatePosition]);
2979
+ React10.useEffect(() => {
2980
+ if (!isOpen) return;
2981
+ const handleDocumentKeyDown = (event) => {
2982
+ if (event.key === "Escape") closeNow();
2983
+ };
2984
+ document.addEventListener("pointerdown", closeNow, true);
2985
+ document.addEventListener("keydown", handleDocumentKeyDown);
2986
+ return () => {
2987
+ document.removeEventListener("pointerdown", closeNow, true);
2988
+ document.removeEventListener("keydown", handleDocumentKeyDown);
2989
+ };
2990
+ }, [closeNow, isOpen]);
2971
2991
  const childProps = children.props;
2972
2992
  const childRef = childProps.ref;
2973
2993
  const passthroughRef = mergeRefs(forwardedRef, childRef, (node) => {
@@ -3000,6 +3020,22 @@ var Tooltip = React10.forwardRef(({
3000
3020
  handleMouseLeave();
3001
3021
  }
3002
3022
  ),
3023
+ onPointerDown: chainEventHandlers(
3024
+ triggerPassthroughProps.onPointerDown,
3025
+ childProps.onPointerDown,
3026
+ (e) => {
3027
+ triggerRef.current = e.currentTarget;
3028
+ closeNow();
3029
+ }
3030
+ ),
3031
+ onClick: chainEventHandlers(
3032
+ triggerPassthroughProps.onClick,
3033
+ childProps.onClick,
3034
+ (e) => {
3035
+ triggerRef.current = e.currentTarget;
3036
+ closeNow();
3037
+ }
3038
+ ),
3003
3039
  onFocus: chainEventHandlers(
3004
3040
  triggerPassthroughProps.onFocus,
3005
3041
  childProps.onFocus,
@@ -17466,6 +17502,9 @@ function CategoryTreeSelect(props) {
17466
17502
  searchDebounceMs = 0,
17467
17503
  minSearchLength = 0,
17468
17504
  showSearchPromptWhenEmptyQuery = false,
17505
+ baseIndent = TREE_NODE_BASE_PADDING_REM,
17506
+ indentSize = TREE_NODE_INDENT_REM,
17507
+ renderItemActions,
17469
17508
  singleSelect = false
17470
17509
  } = props;
17471
17510
  const [isOpen, setIsOpen] = useState31(false);
@@ -17769,7 +17808,7 @@ function CategoryTreeSelect(props) {
17769
17808
  // Selected state - đồng bộ cho tất cả
17770
17809
  !viewOnly && isSelected && "bg-accent/40"
17771
17810
  ),
17772
- style: { paddingLeft: `${level * TREE_NODE_INDENT_REM + TREE_NODE_BASE_PADDING_REM}rem` },
17811
+ style: { paddingLeft: `${level * indentSize + baseIndent}rem` },
17773
17812
  children: [
17774
17813
  hasChildren ? /* @__PURE__ */ jsx50(
17775
17814
  "button",
@@ -17814,7 +17853,8 @@ function CategoryTreeSelect(props) {
17814
17853
  ),
17815
17854
  hasChildren && !isSelected && /* @__PURE__ */ jsx50("span", { className: "ml-auto shrink-0 text-[10px] font-medium text-muted-foreground/50 bg-muted/50 px-1.5 py-0.5 rounded-md", children: children.length })
17816
17855
  ] })
17817
- )
17856
+ ),
17857
+ renderItemActions && /* @__PURE__ */ jsx50("div", { className: "shrink-0 ml-auto", onClick: (e) => e.stopPropagation(), children: renderItemActions(category) })
17818
17858
  ]
17819
17859
  }
17820
17860
  ),