@monolith-forensics/monolith-ui 1.3.112 → 1.4.0

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.
@@ -0,0 +1,23 @@
1
+ import { useFloating, useInteractions } from "@floating-ui/react";
2
+ import { PopoverTransitionProps } from "./Popover.types";
3
+ export interface PopoverContextValue {
4
+ opened: boolean;
5
+ refs: ReturnType<typeof useFloating>["refs"];
6
+ context: ReturnType<typeof useFloating>["context"];
7
+ floatingStyles: ReturnType<typeof useFloating>["floatingStyles"];
8
+ getReferenceProps: ReturnType<typeof useInteractions>["getReferenceProps"];
9
+ getFloatingProps: ReturnType<typeof useInteractions>["getFloatingProps"];
10
+ withArrow: boolean;
11
+ arrowSize: number;
12
+ arrowRadius: number;
13
+ arrowRef: React.MutableRefObject<HTMLDivElement | null>;
14
+ withinPortal: boolean;
15
+ trapFocus: boolean;
16
+ returnFocus: boolean;
17
+ keepMounted: boolean;
18
+ zIndex: number;
19
+ dropdownId: string;
20
+ transitionProps: PopoverTransitionProps;
21
+ }
22
+ export declare const PopoverContext: import("react").Context<PopoverContextValue | null>;
23
+ export declare const usePopoverContext: () => PopoverContextValue;
@@ -0,0 +1,9 @@
1
+ import { createContext, useContext } from "react";
2
+ export const PopoverContext = createContext(null);
3
+ export const usePopoverContext = () => {
4
+ const context = useContext(PopoverContext);
5
+ if (!context) {
6
+ throw new Error("Popover components must be used within Popover");
7
+ }
8
+ return context;
9
+ };
@@ -0,0 +1,7 @@
1
+ import { PopoverDropdownProps, PopoverProps, PopoverTargetProps } from "./Popover.types";
2
+ type PopoverCompound = React.FC<PopoverProps> & {
3
+ Target: React.FC<PopoverTargetProps>;
4
+ Dropdown: React.FC<PopoverDropdownProps>;
5
+ };
6
+ export declare const Popover: PopoverCompound;
7
+ export {};
@@ -0,0 +1,124 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useUncontrolled } from "@mantine/hooks";
3
+ import { arrow, autoUpdate, flip, FloatingDelayGroup, offset, shift, size, useClick, useDismiss, useFloating, useFocus, useHover, useInteractions, useRole, } from "@floating-ui/react";
4
+ import { useId, useMemo, useRef } from "react";
5
+ import { PopoverContext } from "./Popover.context";
6
+ import { PopoverTarget } from "./PopoverTarget";
7
+ import { PopoverDropdown } from "./PopoverDropdown";
8
+ const PopoverRoot = ({ children, opened, defaultOpened = false, onChange, trigger = "click", disabled = false, position = "bottom", offset: offsetValue = 8, openDelay = 75, closeDelay = 100, closeOnClickOutside = true, closeOnEscape = true, withinPortal = true, trapFocus = false, returnFocus = true, keepMounted = false, withArrow = false, arrowSize = 8, arrowRadius = 2, zIndex = 1500, role = "dialog", width, matchTargetWidth = false, shiftPadding = 8, flipPadding = 8, withDelayGroup = false, delayGroupTimeoutMs = 250, transitionProps = {}, }) => {
9
+ const [_opened, setOpened] = useUncontrolled({
10
+ value: opened,
11
+ defaultValue: defaultOpened,
12
+ finalValue: false,
13
+ onChange,
14
+ });
15
+ const arrowRef = useRef(null);
16
+ const dropdownId = useId();
17
+ const resolvedArrowSize = Math.max(arrowSize, 6);
18
+ const { refs, floatingStyles, context } = useFloating({
19
+ open: _opened,
20
+ onOpenChange: (nextOpen) => {
21
+ if (!disabled) {
22
+ setOpened(nextOpen);
23
+ }
24
+ },
25
+ placement: position,
26
+ middleware: [
27
+ offset(offsetValue + (withArrow ? resolvedArrowSize / 2 : 0)),
28
+ flip({ padding: flipPadding }),
29
+ shift({ padding: shiftPadding }),
30
+ size({
31
+ apply({ rects, elements }) {
32
+ if (matchTargetWidth) {
33
+ elements.floating.style.width = `${rects.reference.width}px`;
34
+ }
35
+ if (width !== undefined) {
36
+ elements.floating.style.width =
37
+ typeof width === "number" ? `${width}px` : width;
38
+ }
39
+ },
40
+ }),
41
+ ...(withArrow
42
+ ? [
43
+ arrow({
44
+ element: arrowRef,
45
+ padding: 8,
46
+ }),
47
+ ]
48
+ : []),
49
+ ],
50
+ whileElementsMounted: autoUpdate,
51
+ });
52
+ const click = useClick(context, {
53
+ enabled: !disabled && trigger === "click",
54
+ event: "click",
55
+ toggle: true,
56
+ });
57
+ const hover = useHover(context, {
58
+ enabled: !disabled && trigger === "hover",
59
+ delay: { open: openDelay, close: closeDelay },
60
+ move: false,
61
+ });
62
+ const focus = useFocus(context, {
63
+ enabled: !disabled && trigger === "hover",
64
+ visibleOnly: true,
65
+ });
66
+ const dismiss = useDismiss(context, {
67
+ enabled: !disabled,
68
+ outsidePress: closeOnClickOutside,
69
+ escapeKey: closeOnEscape,
70
+ });
71
+ const roleInteraction = useRole(context, { role });
72
+ const { getReferenceProps, getFloatingProps } = useInteractions([
73
+ click,
74
+ hover,
75
+ focus,
76
+ dismiss,
77
+ roleInteraction,
78
+ ]);
79
+ const contextValue = useMemo(() => ({
80
+ opened: _opened,
81
+ refs,
82
+ context,
83
+ floatingStyles,
84
+ getReferenceProps,
85
+ getFloatingProps,
86
+ withArrow,
87
+ arrowSize,
88
+ arrowRadius,
89
+ arrowRef,
90
+ withinPortal,
91
+ trapFocus,
92
+ returnFocus,
93
+ keepMounted,
94
+ zIndex,
95
+ dropdownId,
96
+ transitionProps,
97
+ }), [
98
+ _opened,
99
+ refs,
100
+ context,
101
+ floatingStyles,
102
+ getReferenceProps,
103
+ getFloatingProps,
104
+ withArrow,
105
+ arrowSize,
106
+ arrowRadius,
107
+ withinPortal,
108
+ trapFocus,
109
+ returnFocus,
110
+ keepMounted,
111
+ zIndex,
112
+ dropdownId,
113
+ transitionProps,
114
+ ]);
115
+ const body = _jsx(PopoverContext.Provider, { value: contextValue, children: children });
116
+ if (!withDelayGroup) {
117
+ return body;
118
+ }
119
+ return (_jsx(FloatingDelayGroup, { delay: { open: openDelay, close: closeDelay }, timeoutMs: delayGroupTimeoutMs, children: body }));
120
+ };
121
+ export const Popover = Object.assign(PopoverRoot, {
122
+ Target: PopoverTarget,
123
+ Dropdown: PopoverDropdown,
124
+ });
@@ -0,0 +1,7 @@
1
+ export declare const StyledDropdown: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
2
+ export declare const ARROW_STYLES: Record<"top" | "right" | "bottom" | "left", {
3
+ clipPath: string;
4
+ borderTransparent: string[];
5
+ radiusCorner: string;
6
+ staticProp: string;
7
+ }>;
@@ -0,0 +1,40 @@
1
+ import styled from "styled-components";
2
+ export const StyledDropdown = styled.div `
3
+ position: relative;
4
+ min-width: 180px;
5
+ border-radius: 8px;
6
+ border: 1px solid ${({ theme }) => theme.palette.divider};
7
+ background-color: ${({ theme }) => theme.palette.background.default};
8
+ color: ${({ theme }) => theme.palette.text.primary};
9
+ box-shadow:
10
+ rgba(15, 23, 42, 0.1) 0px 10px 15px -3px,
11
+ rgba(15, 23, 42, 0.05) 0px 4px 6px -2px;
12
+ padding: 10px 12px;
13
+ outline: none;
14
+ `;
15
+ export const ARROW_STYLES = {
16
+ bottom: {
17
+ clipPath: "polygon(0 100%, 0 0, 100% 0)",
18
+ borderTransparent: ["borderBottomColor", "borderRightColor"],
19
+ radiusCorner: "borderTopLeftRadius",
20
+ staticProp: "top",
21
+ },
22
+ top: {
23
+ clipPath: "polygon(0 100%, 100% 100%, 100% 0)",
24
+ borderTransparent: ["borderTopColor", "borderLeftColor"],
25
+ radiusCorner: "borderBottomRightRadius",
26
+ staticProp: "bottom",
27
+ },
28
+ left: {
29
+ clipPath: "polygon(100% 0, 0 0, 100% 100%)",
30
+ borderTransparent: ["borderLeftColor", "borderBottomColor"],
31
+ radiusCorner: "borderTopRightRadius",
32
+ staticProp: "right",
33
+ },
34
+ right: {
35
+ clipPath: "polygon(0 100%, 0 0, 100% 100%)",
36
+ borderTransparent: ["borderRightColor", "borderTopColor"],
37
+ radiusCorner: "borderBottomLeftRadius",
38
+ staticProp: "left",
39
+ },
40
+ };
@@ -0,0 +1,5 @@
1
+ import { PopoverTransitionProps } from "./Popover.types";
2
+ export declare function usePopoverTransition(opened: boolean, { transition, duration, timingFunction }: PopoverTransitionProps): {
3
+ mounted: boolean;
4
+ styles: React.CSSProperties;
5
+ };
@@ -0,0 +1,63 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ const TRANSITION_PRESETS = {
3
+ fade: {
4
+ from: { opacity: 0 },
5
+ to: { opacity: 1 },
6
+ },
7
+ scale: {
8
+ from: { opacity: 0, scale: "0.85" },
9
+ to: { opacity: 1, scale: "1" },
10
+ },
11
+ "scale-y": {
12
+ from: { opacity: 0, scale: "1 0.7" },
13
+ to: { opacity: 1, scale: "1 1" },
14
+ },
15
+ pop: {
16
+ from: { opacity: 0, scale: "0.6" },
17
+ to: { opacity: 1, scale: "1" },
18
+ },
19
+ };
20
+ export function usePopoverTransition(opened, { transition = "fade", duration = 150, timingFunction = "ease" }) {
21
+ const [mounted, setMounted] = useState(opened);
22
+ const [transitionEnabled, setTransitionEnabled] = useState(false);
23
+ const [phase, setPhase] = useState(opened ? "enter" : "exit");
24
+ const frameRef = useRef(0);
25
+ useEffect(() => {
26
+ cancelAnimationFrame(frameRef.current);
27
+ if (opened) {
28
+ setMounted(true);
29
+ setTransitionEnabled(false);
30
+ setPhase("exit");
31
+ frameRef.current = requestAnimationFrame(() => {
32
+ frameRef.current = requestAnimationFrame(() => {
33
+ setTransitionEnabled(true);
34
+ setPhase("enter");
35
+ });
36
+ });
37
+ }
38
+ else {
39
+ setTransitionEnabled(true);
40
+ setPhase("exit");
41
+ const timer = setTimeout(() => {
42
+ setMounted(false);
43
+ setTransitionEnabled(false);
44
+ }, duration);
45
+ return () => clearTimeout(timer);
46
+ }
47
+ }, [opened, duration]);
48
+ useEffect(() => {
49
+ return () => cancelAnimationFrame(frameRef.current);
50
+ }, []);
51
+ const preset = TRANSITION_PRESETS[transition];
52
+ const transitionStyles = phase === "enter" ? preset.to : preset.from;
53
+ const properties = [
54
+ ...new Set([...Object.keys(preset.from), ...Object.keys(preset.to)]),
55
+ ];
56
+ const transitionValue = properties
57
+ .map((prop) => `${prop} ${duration}ms ${timingFunction}`)
58
+ .join(", ");
59
+ return {
60
+ mounted: mounted || opened,
61
+ styles: Object.assign(Object.assign({}, transitionStyles), (transitionEnabled ? { transition: transitionValue } : {})),
62
+ };
63
+ }
@@ -0,0 +1,45 @@
1
+ import { Placement } from "@floating-ui/react";
2
+ import { ReactElement, ReactNode } from "react";
3
+ export type PopoverTransition = "fade" | "scale" | "scale-y" | "pop";
4
+ export type PopoverTrigger = "click" | "hover";
5
+ export interface PopoverTransitionProps {
6
+ transition?: PopoverTransition;
7
+ duration?: number;
8
+ timingFunction?: string;
9
+ }
10
+ export interface PopoverProps {
11
+ children: ReactNode;
12
+ opened?: boolean;
13
+ defaultOpened?: boolean;
14
+ onChange?: (opened: boolean) => void;
15
+ trigger?: PopoverTrigger;
16
+ disabled?: boolean;
17
+ position?: Placement;
18
+ offset?: number;
19
+ openDelay?: number;
20
+ closeDelay?: number;
21
+ closeOnClickOutside?: boolean;
22
+ closeOnEscape?: boolean;
23
+ withinPortal?: boolean;
24
+ trapFocus?: boolean;
25
+ returnFocus?: boolean;
26
+ keepMounted?: boolean;
27
+ withArrow?: boolean;
28
+ arrowSize?: number;
29
+ arrowRadius?: number;
30
+ zIndex?: number;
31
+ role?: "dialog" | "menu" | "tooltip";
32
+ width?: number | string;
33
+ matchTargetWidth?: boolean;
34
+ shiftPadding?: number;
35
+ flipPadding?: number;
36
+ withDelayGroup?: boolean;
37
+ delayGroupTimeoutMs?: number;
38
+ transitionProps?: PopoverTransitionProps;
39
+ }
40
+ export interface PopoverTargetProps {
41
+ children: ReactElement;
42
+ }
43
+ export interface PopoverDropdownProps extends React.HTMLAttributes<HTMLDivElement> {
44
+ children: ReactNode;
45
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import { PopoverDropdownProps } from "./Popover.types";
2
+ export declare const PopoverDropdown: React.FC<PopoverDropdownProps>;
@@ -0,0 +1,52 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { FloatingFocusManager, FloatingPortal } from "@floating-ui/react";
14
+ import { usePopoverContext } from "./Popover.context";
15
+ import { ARROW_STYLES, StyledDropdown } from "./Popover.styles";
16
+ import { usePopoverTransition } from "./Popover.transitions";
17
+ export const PopoverDropdown = (_a) => {
18
+ var _b, _c;
19
+ var { children, className, style } = _a, props = __rest(_a, ["children", "className", "style"]);
20
+ const { opened, refs, context, floatingStyles, getFloatingProps, withArrow, arrowSize, arrowRadius, arrowRef, withinPortal, trapFocus, returnFocus, keepMounted, zIndex, dropdownId, transitionProps: ctxTransitionProps, } = usePopoverContext();
21
+ const { mounted, styles: transitionStyles } = usePopoverTransition(opened, ctxTransitionProps);
22
+ const arrowX = (_b = context.middlewareData.arrow) === null || _b === void 0 ? void 0 : _b.x;
23
+ const arrowY = (_c = context.middlewareData.arrow) === null || _c === void 0 ? void 0 : _c.y;
24
+ const [placementSide, placementAlignment] = context.placement.split("-");
25
+ const arrowConfig = ARROW_STYLES[placementSide];
26
+ const originSide = {
27
+ top: "bottom",
28
+ bottom: "top",
29
+ left: "right",
30
+ right: "left",
31
+ }[placementSide];
32
+ const originAlignment = placementAlignment === "start"
33
+ ? placementSide === "top" || placementSide === "bottom"
34
+ ? "left"
35
+ : "top"
36
+ : placementAlignment === "end"
37
+ ? placementSide === "top" || placementSide === "bottom"
38
+ ? "right"
39
+ : "bottom"
40
+ : "center";
41
+ const transformOrigin = `${originSide} ${originAlignment}`;
42
+ if (!mounted && !keepMounted) {
43
+ return null;
44
+ }
45
+ const dropdown = (_jsx(FloatingFocusManager, { context: context, modal: trapFocus, returnFocus: returnFocus, children: _jsxs(StyledDropdown, Object.assign({}, getFloatingProps(props), { id: dropdownId, ref: refs.setFloating, className: className, style: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, floatingStyles), transitionStyles), { transformOrigin }), style), { zIndex }), (keepMounted && !mounted
46
+ ? { visibility: "hidden", pointerEvents: "none" }
47
+ : {})), children: [children, withArrow && (_jsx("div", { ref: arrowRef, style: Object.assign(Object.assign(Object.assign({ position: "absolute", width: Math.max(arrowSize, 6), height: Math.max(arrowSize, 6), transform: "rotate(45deg)", background: "inherit", border: "1px solid", borderColor: "inherit", pointerEvents: "none", zIndex: 1 }, (arrowX != null ? { left: arrowX } : {})), (arrowY != null ? { top: arrowY } : {})), { [arrowConfig.staticProp]: -Math.max(arrowSize, 6) / 2, [arrowConfig.radiusCorner]: arrowRadius, [arrowConfig.borderTransparent[0]]: "transparent", [arrowConfig.borderTransparent[1]]: "transparent", clipPath: arrowConfig.clipPath }) }))] })) }));
48
+ if (!withinPortal) {
49
+ return dropdown;
50
+ }
51
+ return _jsx(FloatingPortal, { children: dropdown });
52
+ };
@@ -0,0 +1,2 @@
1
+ import { PopoverTargetProps } from "./Popover.types";
2
+ export declare const PopoverTarget: React.FC<PopoverTargetProps>;
@@ -0,0 +1,11 @@
1
+ import { useMergeRefs } from "@floating-ui/react";
2
+ import { cloneElement, isValidElement } from "react";
3
+ import { usePopoverContext } from "./Popover.context";
4
+ export const PopoverTarget = ({ children }) => {
5
+ const { refs, getReferenceProps, opened, dropdownId } = usePopoverContext();
6
+ if (!isValidElement(children)) {
7
+ return null;
8
+ }
9
+ const mergedRef = useMergeRefs([refs.setReference, children.ref]);
10
+ return cloneElement(children, getReferenceProps(Object.assign({ ref: mergedRef, "aria-expanded": opened, "aria-controls": dropdownId, "aria-haspopup": "dialog" }, children.props)));
11
+ };
@@ -0,0 +1,2 @@
1
+ export { Popover } from "./Popover";
2
+ export type { PopoverProps, PopoverTargetProps, PopoverDropdownProps, PopoverTransition, PopoverTrigger, PopoverTransitionProps, } from "./Popover.types";
@@ -0,0 +1 @@
1
+ export { Popover } from "./Popover";
@@ -1,9 +1,11 @@
1
1
  import React from "react";
2
2
  import { Size } from "../core";
3
3
  import { DropDownItem } from "..";
4
+ import { DropDownMenuProps } from "../DropDownMenu/types";
4
5
  export type InsertableItem = {
5
6
  label: string;
6
7
  value: string;
8
+ group?: string;
7
9
  };
8
10
  export interface TextAreaInputProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
9
11
  variant?: "contained" | "filled" | "outlined" | "text";
@@ -20,13 +22,28 @@ export interface TextAreaInputProps extends React.TextareaHTMLAttributes<HTMLTex
20
22
  rowHeight: number;
21
23
  }) => void;
22
24
  showActionMenu?: boolean;
25
+ /**
26
+ * Visual style of the action menu trigger.
27
+ * - `"ellipsis"` renders a minimal `...` icon button (default).
28
+ * - `"dropdown"` renders an outlined button with a label and arrow, similar to the Table Filter menu.
29
+ */
30
+ actionMenuVariant?: "ellipsis" | "dropdown";
23
31
  actionMenuOptions?: Array<{
24
32
  value: string;
25
33
  label: string;
26
34
  }>;
27
35
  onActionMenuSelect?: (item: DropDownItem) => void;
36
+ /** Label displayed on the actions dropdown button. Only used when `actionMenuVariant` is `"dropdown"`. Defaults to "Actions". */
37
+ actionMenuLabel?: string;
38
+ /** Icon rendered in the left section of the actions dropdown button. Only used when `actionMenuVariant` is `"dropdown"`. Defaults to MoreHorizontal. */
39
+ actionMenuIcon?: React.ReactNode;
40
+ /** Whether the actions dropdown is searchable. Only used when `actionMenuVariant` is `"dropdown"`. Defaults to false. */
41
+ actionMenuSearchable?: boolean;
42
+ /** Additional props forwarded to the DropDownMenu component. Only used when `actionMenuVariant` is `"dropdown"`. */
43
+ actionMenuProps?: Partial<DropDownMenuProps>;
28
44
  insertableItems?: InsertableItem[];
29
45
  onInsertItem?: (item: InsertableItem) => void;
46
+ groupInsertableItems?: boolean;
30
47
  }
31
48
  declare const TextAreaInput: React.ForwardRefExoticComponent<TextAreaInputProps & React.RefAttributes<HTMLTextAreaElement>>;
32
49
  export default TextAreaInput;
@@ -50,11 +50,11 @@ const TextAreaInput = forwardRef((props, ref) => {
50
50
  // UI
51
51
  label, error, required, colSpan = 1, size = "sm", description, maxRows = 6, minRows = 3, onHeightChange, cacheMeasurements,
52
52
  // Action menu
53
- showActionMenu = false, actionMenuOptions = DEFAULT_ACTIONS, onActionMenuSelect,
53
+ showActionMenu = false, actionMenuVariant = "ellipsis", actionMenuOptions = DEFAULT_ACTIONS, onActionMenuSelect, actionMenuLabel = "Actions", actionMenuIcon, actionMenuSearchable = false, actionMenuProps,
54
54
  // Insertable items
55
- insertableItems, onInsertItem } = props,
55
+ insertableItems, onInsertItem, groupInsertableItems } = props,
56
56
  // Rest of props for TextArea
57
- rest = __rest(props, ["label", "error", "required", "colSpan", "size", "description", "maxRows", "minRows", "onHeightChange", "cacheMeasurements", "showActionMenu", "actionMenuOptions", "onActionMenuSelect", "insertableItems", "onInsertItem"]);
57
+ rest = __rest(props, ["label", "error", "required", "colSpan", "size", "description", "maxRows", "minRows", "onHeightChange", "cacheMeasurements", "showActionMenu", "actionMenuVariant", "actionMenuOptions", "onActionMenuSelect", "actionMenuLabel", "actionMenuIcon", "actionMenuSearchable", "actionMenuProps", "insertableItems", "onInsertItem", "groupInsertableItems"]);
58
58
  // State for insert menu visibility
59
59
  const [showInsertMenu, setShowInsertMenu] = useState(false);
60
60
  const [triggerSelectBoxOpen, setTriggerSelectBoxOpen] = useState(false);
@@ -75,10 +75,16 @@ const TextAreaInput = forwardRef((props, ref) => {
75
75
  if (!showInsertMenu)
76
76
  return;
77
77
  const handleClickOutside = (event) => {
78
- if (insertMenuRef.current &&
79
- !insertMenuRef.current.contains(event.target)) {
80
- setShowInsertMenu(false);
81
- }
78
+ var _a, _b, _c;
79
+ const target = event.target;
80
+ // Ignore clicks inside the insert menu container
81
+ if ((_a = insertMenuRef.current) === null || _a === void 0 ? void 0 : _a.contains(target))
82
+ return;
83
+ // Ignore clicks inside the SelectBox floating portal dropdown
84
+ const floatingEl = (_c = (_b = target).closest) === null || _c === void 0 ? void 0 : _c.call(_b, ".mfFloating");
85
+ if (floatingEl)
86
+ return;
87
+ setShowInsertMenu(false);
82
88
  };
83
89
  document.addEventListener("mousedown", handleClickOutside);
84
90
  return () => {
@@ -86,6 +92,7 @@ const TextAreaInput = forwardRef((props, ref) => {
86
92
  };
87
93
  }, [showInsertMenu]);
88
94
  const handleActionSelect = (item) => {
95
+ var _a;
89
96
  if (item.value === "insert" && (insertableItems === null || insertableItems === void 0 ? void 0 : insertableItems.length)) {
90
97
  setShowInsertMenu(true);
91
98
  // Trigger SelectBox to open using the new enhanced props
@@ -95,11 +102,10 @@ const TextAreaInput = forwardRef((props, ref) => {
95
102
  // Built-in clear functionality
96
103
  const textarea = textareaRef.current;
97
104
  if (textarea) {
98
- textarea.value = "";
105
+ const nativeSet = (_a = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value")) === null || _a === void 0 ? void 0 : _a.set;
106
+ nativeSet === null || nativeSet === void 0 ? void 0 : nativeSet.call(textarea, "");
107
+ textarea.dispatchEvent(new Event("input", { bubbles: true }));
99
108
  textarea.focus();
100
- // Trigger change event so controlled components update
101
- const event = new Event("input", { bubbles: true });
102
- textarea.dispatchEvent(event);
103
109
  }
104
110
  onActionMenuSelect === null || onActionMenuSelect === void 0 ? void 0 : onActionMenuSelect(item);
105
111
  }
@@ -112,6 +118,7 @@ const TextAreaInput = forwardRef((props, ref) => {
112
118
  setTriggerSelectBoxOpen(false);
113
119
  };
114
120
  const handleInsertSelect = (value, option) => {
121
+ var _a;
115
122
  console.log("Selected value:", value, "Selected option:", option); // Debug log
116
123
  // SelectBox passes (value, option) - we want the full option object
117
124
  const item = option;
@@ -131,28 +138,40 @@ const TextAreaInput = forwardRef((props, ref) => {
131
138
  const end = textarea.selectionEnd;
132
139
  const currentValue = textarea.value;
133
140
  const newValue = currentValue.slice(0, start) + item.value + currentValue.slice(end);
134
- textarea.value = newValue;
141
+ // Use the native setter so React's synthetic event system
142
+ // recognises the change on controlled inputs
143
+ const nativeSet = (_a = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value")) === null || _a === void 0 ? void 0 : _a.set;
144
+ nativeSet === null || nativeSet === void 0 ? void 0 : nativeSet.call(textarea, newValue);
145
+ // Dispatch as a bubbling event so React's onChange fires
146
+ textarea.dispatchEvent(new Event("input", { bubbles: true }));
135
147
  textarea.focus();
136
148
  textarea.setSelectionRange(start + item.value.length, start + item.value.length);
137
- // Trigger change event
138
- const event = new Event("input", { bubbles: true });
139
- textarea.dispatchEvent(event);
140
149
  }
141
150
  }
142
151
  setShowInsertMenu(false);
143
152
  };
144
- return (_jsxs("div", { style: { gridColumn: `span ${colSpan}`, height: "fit-content" }, children: [label && (_jsx(FieldLabel, { asterisk: required, error: error, description: description, size: size, actionComponent: showActionMenu ? (_jsx(DropDownMenu, { data: actionMenuOptions, variant: "text", size: "xs", arrow: false, onItemSelect: handleActionSelect, buttonProps: {
145
- "aria-label": "Open actions",
146
- style: {
147
- minWidth: "auto",
148
- border: "none",
149
- background: "transparent",
150
- padding: 0,
151
- margin: 0,
152
- height: 16,
153
- width: 16,
154
- },
155
- }, children: _jsx(StyledMoreHorizontal, { size: 16 }) })) : null, children: label })), _jsxs(TextAreaWrapper, { children: [_jsx(TextArea, Object.assign({ ref: mergedRef, size: size, maxRows: maxRows, minRows: minRows, onHeightChange: onHeightChange, cacheMeasurements: cacheMeasurements }, rest)), showInsertMenu && (insertableItems === null || insertableItems === void 0 ? void 0 : insertableItems.length) && (_jsx(InsertMenuOverlay, { ref: insertMenuRef, "$visible": showInsertMenu, children: _jsx(StyledInsertSelectBox, { data: insertableItems, placeholder: "Select item to insert...", searchable: true, clearable: false, arrow: false, focused: showInsertMenu, openOnFocus: true, triggerOpen: triggerSelectBoxOpen, onOpened: handleSelectBoxOpened, onChange: handleInsertSelect, size: size }) }))] })] }));
153
+ return (_jsxs("div", { style: { gridColumn: `span ${colSpan}`, height: "fit-content" }, children: [label && (_jsx(FieldLabel, { asterisk: required, error: error, description: description, size: size, actionComponent: showActionMenu
154
+ ? actionMenuVariant === "dropdown"
155
+ ? (_jsx(DropDownMenu, Object.assign({ data: actionMenuOptions, variant: "outlined", size: "xs", arrow: true, searchable: actionMenuSearchable, onItemSelect: handleActionSelect, buttonProps: {
156
+ title: actionMenuLabel,
157
+ size: "xxs",
158
+ leftSection: actionMenuIcon,
159
+ }, dropDownProps: {
160
+ style: { width: 175, maxWidth: 400 },
161
+ } }, actionMenuProps, { children: actionMenuLabel })))
162
+ : (_jsx(DropDownMenu, { data: actionMenuOptions, variant: "text", size: "xs", arrow: false, onItemSelect: handleActionSelect, buttonProps: {
163
+ "aria-label": "Open actions",
164
+ style: {
165
+ minWidth: "auto",
166
+ border: "none",
167
+ background: "transparent",
168
+ padding: 0,
169
+ margin: 0,
170
+ height: 16,
171
+ width: 16,
172
+ },
173
+ }, children: _jsx(StyledMoreHorizontal, { size: 16 }) }))
174
+ : null, children: label })), _jsxs(TextAreaWrapper, { children: [_jsx(TextArea, Object.assign({ ref: mergedRef, size: size, maxRows: maxRows, minRows: minRows, onHeightChange: onHeightChange, cacheMeasurements: cacheMeasurements }, rest)), showInsertMenu && (insertableItems === null || insertableItems === void 0 ? void 0 : insertableItems.length) && (_jsx(InsertMenuOverlay, { ref: insertMenuRef, "$visible": showInsertMenu, children: _jsx(StyledInsertSelectBox, { data: insertableItems, grouped: groupInsertableItems, searchable: true, clearable: false, arrow: false, focused: showInsertMenu, openOnFocus: true, triggerOpen: triggerSelectBoxOpen, onOpened: handleSelectBoxOpened, onChange: handleInsertSelect, size: size }) }))] })] }));
156
175
  });
157
176
  TextAreaInput.displayName = "TextAreaInput";
158
177
  export default TextAreaInput;
package/dist/index.d.ts CHANGED
@@ -42,3 +42,4 @@ export type { ColumnProps, TableProps } from "./Table";
42
42
  export * from "./Tabs";
43
43
  export * from "./Divider";
44
44
  export * from "./SegmentedControl";
45
+ export * from "./Popover";
package/dist/index.js CHANGED
@@ -34,3 +34,4 @@ export * from "./Table";
34
34
  export * from "./Tabs";
35
35
  export * from "./Divider";
36
36
  export * from "./SegmentedControl";
37
+ export * from "./Popover";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monolith-forensics/monolith-ui",
3
- "version": "1.3.112",
3
+ "version": "1.4.0",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "author": "Matt Danner (Monolith Forensics LLC)",