@trackunit/react-components 2.13.12 → 2.13.13
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/index.cjs.js +133 -56
- package/index.esm.js +133 -56
- package/package.json +6 -6
- package/src/components/HorizontalOverflowScroller/HorizontalOverflowScroller.d.ts +17 -9
- package/src/components/HorizontalOverflowScroller/HorizontalOverflowScroller.variants.d.ts +35 -0
- package/src/components/HorizontalOverflowScroller/OverflowIndicator.d.ts +10 -6
- package/src/components/HorizontalOverflowScroller/OverflowIndicator.variants.d.ts +17 -24
- package/src/components/Menu/MoreMenu/MoreMenu.d.ts +1 -0
- package/migrations/entry.js.map +0 -1
- package/migrations/utils/jsx-utils.js.map +0 -1
- package/migrations/v2-0-0/breadcrumb-remove-deprecated-props.js.map +0 -1
- package/migrations/v2-0-0/cardheader-onclickclose-to-actions.js.map +0 -1
- package/migrations/v2-0-0/iconbutton-add-required-name.js.map +0 -1
- package/migrations/v2-0-0/kpi-tooltiplabel-to-wrapper.js.map +0 -1
- package/migrations/v2-0-0/notice-tooltiplabel-to-wrapper.js.map +0 -1
- package/migrations/v2-0-0/pagination-add-required-titles.js.map +0 -1
- package/migrations/v2-0-0/tag-add-removetaglabel.js.map +0 -1
- package/migrations/v2-0-0/togglegroup-remove-item-style.js.map +0 -1
- package/migrations/v3-0-0/menulist-rename-to-menucontent.js.map +0 -1
package/index.cjs.js
CHANGED
|
@@ -29,6 +29,8 @@ var defaultTranslations = {
|
|
|
29
29
|
"breadcrumb.expandButton": "expand",
|
|
30
30
|
"copyButton.copied": "Copied!",
|
|
31
31
|
"copyButton.copy": "Copy",
|
|
32
|
+
"horizontalOverflowScroller.scrollLeft": "Scroll left",
|
|
33
|
+
"horizontalOverflowScroller.scrollRight": "Scroll right",
|
|
32
34
|
"moreMenu.buttonLabel": "Show more"
|
|
33
35
|
};
|
|
34
36
|
|
|
@@ -5788,34 +5790,79 @@ const ZStack = ({ children, className, "data-testid": dataTestId, style, ref })
|
|
|
5788
5790
|
}) }));
|
|
5789
5791
|
};
|
|
5790
5792
|
|
|
5793
|
+
const fadeMaskStyleSheet = `
|
|
5794
|
+
@property --tu-hos-solid-left {
|
|
5795
|
+
syntax: '<length>';
|
|
5796
|
+
initial-value: 0px;
|
|
5797
|
+
inherits: false;
|
|
5798
|
+
}
|
|
5799
|
+
|
|
5800
|
+
@property --tu-hos-solid-right {
|
|
5801
|
+
syntax: '<length>';
|
|
5802
|
+
initial-value: 0px;
|
|
5803
|
+
inherits: false;
|
|
5804
|
+
}
|
|
5805
|
+
|
|
5806
|
+
@property --tu-hos-fade-left {
|
|
5807
|
+
syntax: '<length>';
|
|
5808
|
+
initial-value: 0px;
|
|
5809
|
+
inherits: false;
|
|
5810
|
+
}
|
|
5811
|
+
|
|
5812
|
+
@property --tu-hos-fade-right {
|
|
5813
|
+
syntax: '<length>';
|
|
5814
|
+
initial-value: 0px;
|
|
5815
|
+
inherits: false;
|
|
5816
|
+
}
|
|
5817
|
+
`;
|
|
5791
5818
|
const cvaHorizontalOverflowScroller = cssClassVarianceUtilities.cva({
|
|
5792
|
-
base: [
|
|
5819
|
+
base: [
|
|
5820
|
+
"flex",
|
|
5821
|
+
"flex-nowrap",
|
|
5822
|
+
"gap-1",
|
|
5823
|
+
"overflow-y-hidden",
|
|
5824
|
+
"overflow-x-scroll",
|
|
5825
|
+
"scroll-px-9",
|
|
5826
|
+
"w-full",
|
|
5827
|
+
"no-scrollbar",
|
|
5828
|
+
],
|
|
5793
5829
|
});
|
|
5794
|
-
const cvaHorizontalOverflowScrollerAndIndicatorsContainer = cssClassVarianceUtilities.cva({
|
|
5795
|
-
|
|
5796
|
-
const cvaOverflowIndicatorContainer = cssClassVarianceUtilities.cva({
|
|
5797
|
-
base: ["pointer-events-none", "h-full", "w-full", "isolate", "pb-px"],
|
|
5830
|
+
const cvaHorizontalOverflowScrollerAndIndicatorsContainer = cssClassVarianceUtilities.cva({
|
|
5831
|
+
base: ["group", "w-full", "overflow-clip"],
|
|
5798
5832
|
});
|
|
5799
|
-
const
|
|
5833
|
+
const cvaHorizontalOverflowScrollerFadeMask = cssClassVarianceUtilities.cva({
|
|
5800
5834
|
base: [
|
|
5801
|
-
"pointer-events-none",
|
|
5802
|
-
"self-stretch",
|
|
5803
|
-
"w-16",
|
|
5804
|
-
"opacity-0",
|
|
5805
|
-
"transition-opacity",
|
|
5806
5835
|
"duration-200",
|
|
5807
|
-
"
|
|
5808
|
-
"
|
|
5836
|
+
"ease-out",
|
|
5837
|
+
"[mask-image:linear-gradient(to_right,transparent_0,transparent_var(--tu-hos-solid-left),#000_var(--tu-hos-fade-left),#000_calc(100%_-_var(--tu-hos-fade-right)),transparent_calc(100%_-_var(--tu-hos-solid-right)),transparent_100%)]",
|
|
5838
|
+
"[transition-property:--tu-hos-solid-left,--tu-hos-solid-right,--tu-hos-fade-left,--tu-hos-fade-right]",
|
|
5809
5839
|
],
|
|
5810
5840
|
variants: {
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5841
|
+
canScrollLeft: {
|
|
5842
|
+
true: [
|
|
5843
|
+
"[--tu-hos-solid-left:0px]",
|
|
5844
|
+
"[--tu-hos-fade-left:1.25rem]",
|
|
5845
|
+
"group-hover:[--tu-hos-solid-left:1rem]",
|
|
5846
|
+
"group-hover:[--tu-hos-fade-left:2.25rem]",
|
|
5847
|
+
"group-has-[:focus-visible]:[--tu-hos-fade-left:2.25rem]",
|
|
5848
|
+
],
|
|
5849
|
+
false: ["[--tu-hos-solid-left:0px]", "[--tu-hos-fade-left:0px]"],
|
|
5850
|
+
},
|
|
5851
|
+
canScrollRight: {
|
|
5852
|
+
true: [
|
|
5853
|
+
"[--tu-hos-solid-right:0px]",
|
|
5854
|
+
"[--tu-hos-fade-right:1.25rem]",
|
|
5855
|
+
"group-hover:[--tu-hos-solid-right:1rem]",
|
|
5856
|
+
"group-hover:[--tu-hos-fade-right:2.25rem]",
|
|
5857
|
+
"group-has-[:focus-visible]:[--tu-hos-fade-right:2.25rem]",
|
|
5858
|
+
],
|
|
5859
|
+
false: ["[--tu-hos-solid-right:0px]", "[--tu-hos-fade-right:0px]"],
|
|
5814
5860
|
},
|
|
5815
5861
|
},
|
|
5816
5862
|
});
|
|
5817
|
-
|
|
5818
|
-
|
|
5863
|
+
|
|
5864
|
+
const cvaOverflowIndicatorHitRow = cssClassVarianceUtilities.cva({
|
|
5865
|
+
base: ["flex", "h-full", "w-full", "items-center", "pointer-events-none", "z-10"],
|
|
5819
5866
|
variants: {
|
|
5820
5867
|
direction: {
|
|
5821
5868
|
left: ["justify-start"],
|
|
@@ -5823,43 +5870,72 @@ const cvaJustificationContainer = cssClassVarianceUtilities.cva({
|
|
|
5823
5870
|
},
|
|
5824
5871
|
},
|
|
5825
5872
|
});
|
|
5826
|
-
const
|
|
5873
|
+
const cvaOverflowIndicatorHit = cssClassVarianceUtilities.cva({
|
|
5827
5874
|
base: [
|
|
5828
|
-
"
|
|
5875
|
+
"pointer-events-auto",
|
|
5876
|
+
"inline-flex",
|
|
5877
|
+
"h-full",
|
|
5878
|
+
"items-center",
|
|
5879
|
+
"justify-center",
|
|
5880
|
+
"px-1",
|
|
5881
|
+
"border-0",
|
|
5882
|
+
"bg-transparent",
|
|
5883
|
+
"cursor-pointer",
|
|
5884
|
+
"supports-[color:contrast-color(white)]:[color:contrast-color(var(--hos-surface,Canvas))]",
|
|
5885
|
+
"supports-[not_(color:contrast-color(white))]:text-neutral-900",
|
|
5886
|
+
"supports-[not_(color:contrast-color(white))]:[filter:drop-shadow(0_0_0.5px_#fff)_drop-shadow(0_1px_0_#fff)_drop-shadow(0_-1px_0_#fff)_drop-shadow(1px_0_0_#fff)_drop-shadow(-1px_0_0_#fff)]",
|
|
5829
5887
|
"opacity-0",
|
|
5888
|
+
"starting:opacity-0",
|
|
5830
5889
|
"transition-opacity",
|
|
5831
5890
|
"duration-200",
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
"group-focus-
|
|
5836
|
-
"rounded-full",
|
|
5837
|
-
"mx-1",
|
|
5891
|
+
// Keyboard focus (not a plain mouse-click `:focus`) always reveals the control it landed
|
|
5892
|
+
// on, even the disabled one at an exhausted edge -- that's the only way a sighted keyboard
|
|
5893
|
+
// user gets to see what they just tabbed to.
|
|
5894
|
+
"group-has-[:focus-visible]:opacity-100",
|
|
5838
5895
|
],
|
|
5896
|
+
variants: {
|
|
5897
|
+
disabled: {
|
|
5898
|
+
// Nothing to scroll to on this side: don't let a mouse hover over the row reveal a
|
|
5899
|
+
// control that would be a no-op if clicked.
|
|
5900
|
+
true: [],
|
|
5901
|
+
false: ["group-hover:opacity-100"],
|
|
5902
|
+
},
|
|
5903
|
+
},
|
|
5904
|
+
defaultVariants: {
|
|
5905
|
+
disabled: false,
|
|
5906
|
+
},
|
|
5839
5907
|
});
|
|
5840
5908
|
|
|
5841
5909
|
/**
|
|
5842
|
-
*
|
|
5843
|
-
*
|
|
5910
|
+
* Edge control for HorizontalOverflowScroller. The fade lives on the content
|
|
5911
|
+
* mask; this is the hover/focus hit target that pages left or right.
|
|
5844
5912
|
*
|
|
5845
5913
|
* @param {OverflowIndicatorProps} props - The props for the component
|
|
5846
5914
|
* @returns {ReactElement} OverflowIndicator component
|
|
5847
5915
|
*/
|
|
5848
|
-
const OverflowIndicator = ({ className, "data-testid": dataTestId, direction, onClickScroll, style, }) => {
|
|
5916
|
+
const OverflowIndicator = ({ className, "data-testid": dataTestId, direction, onClickScroll, disabled = false, style, }) => {
|
|
5917
|
+
const [t] = useTranslation();
|
|
5849
5918
|
const iconName = direction === "left" ? "ChevronLeft" : "ChevronRight";
|
|
5850
|
-
|
|
5851
|
-
|
|
5919
|
+
const ariaLabel = direction === "left" ? t("horizontalOverflowScroller.scrollLeft") : t("horizontalOverflowScroller.scrollRight");
|
|
5920
|
+
return (jsxRuntime.jsx("div", { className: cvaOverflowIndicatorHitRow({ className, direction }), "data-testid": dataTestId, style: style, children: jsxRuntime.jsx("button", { "aria-disabled": disabled, "aria-label": ariaLabel, className: cvaOverflowIndicatorHit({ disabled }), "data-testid": dataTestId ? `${dataTestId}-button` : undefined, onClick: disabled ? undefined : onClickScroll, type: "button", children: jsxRuntime.jsx(Icon, { ariaHidden: true, name: iconName, size: "small" }) }) }));
|
|
5852
5921
|
};
|
|
5853
5922
|
|
|
5854
5923
|
/**
|
|
5855
5924
|
* HorizontalOverflowScroller displays child elements in a horizontal row with automatic overflow detection.
|
|
5856
|
-
* When content overflows, it
|
|
5925
|
+
* When content overflows, it fades the overflowing edge and reveals chevrons on hover or focus so the row can be paged.
|
|
5926
|
+
*
|
|
5927
|
+
* The fade is a CSS mask on the content itself, so it works on any background. At rest the ramp is short so more
|
|
5928
|
+
* items stay visible; hover grows a solid plateau under the chevron and pushes the ramp further in, while
|
|
5929
|
+
* keyboard focus only extends the ramp — a plateau there would erase the focus ring of a child flush with the
|
|
5930
|
+
* edge. Set `--hos-surface` on an ancestor to the background color behind the scroller so the chevrons pick a
|
|
5931
|
+
* contrasting color. It defaults to `Canvas`.
|
|
5857
5932
|
*
|
|
5858
5933
|
* ### When to use
|
|
5859
5934
|
* Use HorizontalOverflowScroller to display a row of items (cards, tags, buttons) that may overflow on smaller screens, with visual cues that more content is available.
|
|
5860
5935
|
*
|
|
5861
5936
|
* ### When not to use
|
|
5862
5937
|
* Do not use HorizontalOverflowScroller for tab navigation — use `TabList` which has its own scroll handling.
|
|
5938
|
+
* Do not use it to hide extra actions — use `MoreMenu` when the overflowing items are secondary actions rather than a row of content to browse.
|
|
5863
5939
|
*
|
|
5864
5940
|
* @example Horizontal scroller for KPI cards
|
|
5865
5941
|
* ```tsx
|
|
@@ -5879,36 +5955,36 @@ const OverflowIndicator = ({ className, "data-testid": dataTestId, direction, on
|
|
|
5879
5955
|
* @returns {ReactElement} HorizontalOverflowScroller component
|
|
5880
5956
|
*/
|
|
5881
5957
|
const HorizontalOverflowScroller = ({ className, "data-testid": dataTestId, children, onScrollStateChange, style, ref, }) => {
|
|
5882
|
-
const
|
|
5883
|
-
|
|
5884
|
-
|
|
5958
|
+
const onScrollStateChangeRef = react.useRef(onScrollStateChange);
|
|
5959
|
+
react.useEffect(() => {
|
|
5960
|
+
onScrollStateChangeRef.current = onScrollStateChange;
|
|
5961
|
+
}, [onScrollStateChange]);
|
|
5962
|
+
const handleScrollStateChange = react.useCallback((state) => {
|
|
5963
|
+
onScrollStateChangeRef.current?.({
|
|
5964
|
+
isScrollable: state.isScrollable,
|
|
5965
|
+
isAtBeginning: state.isAtBeginning,
|
|
5966
|
+
isAtEnd: state.isAtEnd,
|
|
5967
|
+
});
|
|
5968
|
+
}, []);
|
|
5969
|
+
const { ref: scrollRef, element, isScrollable, isAtBeginning, isAtEnd, } = useScrollDetection({
|
|
5885
5970
|
direction: "horizontal",
|
|
5886
|
-
onScrollStateChange:
|
|
5887
|
-
? (state) => onScrollStateChange({
|
|
5888
|
-
isScrollable: state.isScrollable,
|
|
5889
|
-
isAtBeginning: state.isAtBeginning,
|
|
5890
|
-
isAtEnd: state.isAtEnd,
|
|
5891
|
-
})
|
|
5892
|
-
: undefined,
|
|
5971
|
+
onScrollStateChange: handleScrollStateChange,
|
|
5893
5972
|
});
|
|
5894
|
-
const mergedRef = useMergeRefs([
|
|
5895
|
-
const
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
element
|
|
5899
|
-
left: -containerGeometry.width,
|
|
5900
|
-
behavior: "smooth",
|
|
5901
|
-
});
|
|
5902
|
-
};
|
|
5903
|
-
const handleScrollRight = () => {
|
|
5904
|
-
if (!element || containerGeometry?.width === undefined)
|
|
5973
|
+
const mergedRef = useMergeRefs([scrollRef, ref]);
|
|
5974
|
+
const canScrollLeft = isScrollable && !isAtBeginning;
|
|
5975
|
+
const canScrollRight = isScrollable && !isAtEnd;
|
|
5976
|
+
const scrollByPage = react.useCallback((direction) => {
|
|
5977
|
+
if (!element) {
|
|
5905
5978
|
return;
|
|
5979
|
+
}
|
|
5906
5980
|
element.scrollBy({
|
|
5907
|
-
left:
|
|
5981
|
+
left: direction * element.clientWidth,
|
|
5908
5982
|
behavior: "smooth",
|
|
5909
5983
|
});
|
|
5910
|
-
};
|
|
5911
|
-
return (jsxRuntime.jsxs(
|
|
5984
|
+
}, [element]);
|
|
5985
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("style", { children: fadeMaskStyleSheet }), jsxRuntime.jsxs(ZStack, { className: cvaHorizontalOverflowScrollerAndIndicatorsContainer({ className }), style: style, children: [jsxRuntime.jsx("div", { className: cvaHorizontalOverflowScroller({
|
|
5986
|
+
className: cvaHorizontalOverflowScrollerFadeMask({ canScrollLeft, canScrollRight }),
|
|
5987
|
+
}), "data-testid": dataTestId, ref: mergedRef, children: children }), isScrollable ? (jsxRuntime.jsx(OverflowIndicator, { "data-testid": dataTestId ? `${dataTestId}-left-indicator` : undefined, direction: "left", disabled: !canScrollLeft, onClickScroll: () => scrollByPage(-1) })) : null, isScrollable ? (jsxRuntime.jsx(OverflowIndicator, { "data-testid": dataTestId ? `${dataTestId}-right-indicator` : undefined, direction: "right", disabled: !canScrollRight, onClickScroll: () => scrollByPage(1) })) : null] })] }));
|
|
5912
5988
|
};
|
|
5913
5989
|
|
|
5914
5990
|
const cvaIndicator = cssClassVarianceUtilities.cva({ base: ["inline-flex", "items-center"] });
|
|
@@ -8290,6 +8366,7 @@ const cvaMoreMenu = cssClassVarianceUtilities.cva({ base: ["p-0"] });
|
|
|
8290
8366
|
*
|
|
8291
8367
|
* ### When not to use
|
|
8292
8368
|
* Do not use MoreMenu for primary actions that should always be visible. Use `Button` instead.
|
|
8369
|
+
* Do not use it to overflow a row of content (tags, KPIs, chips) — use `HorizontalOverflowScroller` when those items should stay visible and be browsed horizontally.
|
|
8293
8370
|
*
|
|
8294
8371
|
* @example Action items with render prop — Pass a function as `children` to receive the `close` callback and dismiss the menu after an action.
|
|
8295
8372
|
* ```tsx
|
package/index.esm.js
CHANGED
|
@@ -28,6 +28,8 @@ var defaultTranslations = {
|
|
|
28
28
|
"breadcrumb.expandButton": "expand",
|
|
29
29
|
"copyButton.copied": "Copied!",
|
|
30
30
|
"copyButton.copy": "Copy",
|
|
31
|
+
"horizontalOverflowScroller.scrollLeft": "Scroll left",
|
|
32
|
+
"horizontalOverflowScroller.scrollRight": "Scroll right",
|
|
31
33
|
"moreMenu.buttonLabel": "Show more"
|
|
32
34
|
};
|
|
33
35
|
|
|
@@ -5787,34 +5789,79 @@ const ZStack = ({ children, className, "data-testid": dataTestId, style, ref })
|
|
|
5787
5789
|
}) }));
|
|
5788
5790
|
};
|
|
5789
5791
|
|
|
5792
|
+
const fadeMaskStyleSheet = `
|
|
5793
|
+
@property --tu-hos-solid-left {
|
|
5794
|
+
syntax: '<length>';
|
|
5795
|
+
initial-value: 0px;
|
|
5796
|
+
inherits: false;
|
|
5797
|
+
}
|
|
5798
|
+
|
|
5799
|
+
@property --tu-hos-solid-right {
|
|
5800
|
+
syntax: '<length>';
|
|
5801
|
+
initial-value: 0px;
|
|
5802
|
+
inherits: false;
|
|
5803
|
+
}
|
|
5804
|
+
|
|
5805
|
+
@property --tu-hos-fade-left {
|
|
5806
|
+
syntax: '<length>';
|
|
5807
|
+
initial-value: 0px;
|
|
5808
|
+
inherits: false;
|
|
5809
|
+
}
|
|
5810
|
+
|
|
5811
|
+
@property --tu-hos-fade-right {
|
|
5812
|
+
syntax: '<length>';
|
|
5813
|
+
initial-value: 0px;
|
|
5814
|
+
inherits: false;
|
|
5815
|
+
}
|
|
5816
|
+
`;
|
|
5790
5817
|
const cvaHorizontalOverflowScroller = cva({
|
|
5791
|
-
base: [
|
|
5818
|
+
base: [
|
|
5819
|
+
"flex",
|
|
5820
|
+
"flex-nowrap",
|
|
5821
|
+
"gap-1",
|
|
5822
|
+
"overflow-y-hidden",
|
|
5823
|
+
"overflow-x-scroll",
|
|
5824
|
+
"scroll-px-9",
|
|
5825
|
+
"w-full",
|
|
5826
|
+
"no-scrollbar",
|
|
5827
|
+
],
|
|
5792
5828
|
});
|
|
5793
|
-
const cvaHorizontalOverflowScrollerAndIndicatorsContainer = cva({
|
|
5794
|
-
|
|
5795
|
-
const cvaOverflowIndicatorContainer = cva({
|
|
5796
|
-
base: ["pointer-events-none", "h-full", "w-full", "isolate", "pb-px"],
|
|
5829
|
+
const cvaHorizontalOverflowScrollerAndIndicatorsContainer = cva({
|
|
5830
|
+
base: ["group", "w-full", "overflow-clip"],
|
|
5797
5831
|
});
|
|
5798
|
-
const
|
|
5832
|
+
const cvaHorizontalOverflowScrollerFadeMask = cva({
|
|
5799
5833
|
base: [
|
|
5800
|
-
"pointer-events-none",
|
|
5801
|
-
"self-stretch",
|
|
5802
|
-
"w-16",
|
|
5803
|
-
"opacity-0",
|
|
5804
|
-
"transition-opacity",
|
|
5805
5834
|
"duration-200",
|
|
5806
|
-
"
|
|
5807
|
-
"
|
|
5835
|
+
"ease-out",
|
|
5836
|
+
"[mask-image:linear-gradient(to_right,transparent_0,transparent_var(--tu-hos-solid-left),#000_var(--tu-hos-fade-left),#000_calc(100%_-_var(--tu-hos-fade-right)),transparent_calc(100%_-_var(--tu-hos-solid-right)),transparent_100%)]",
|
|
5837
|
+
"[transition-property:--tu-hos-solid-left,--tu-hos-solid-right,--tu-hos-fade-left,--tu-hos-fade-right]",
|
|
5808
5838
|
],
|
|
5809
5839
|
variants: {
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5840
|
+
canScrollLeft: {
|
|
5841
|
+
true: [
|
|
5842
|
+
"[--tu-hos-solid-left:0px]",
|
|
5843
|
+
"[--tu-hos-fade-left:1.25rem]",
|
|
5844
|
+
"group-hover:[--tu-hos-solid-left:1rem]",
|
|
5845
|
+
"group-hover:[--tu-hos-fade-left:2.25rem]",
|
|
5846
|
+
"group-has-[:focus-visible]:[--tu-hos-fade-left:2.25rem]",
|
|
5847
|
+
],
|
|
5848
|
+
false: ["[--tu-hos-solid-left:0px]", "[--tu-hos-fade-left:0px]"],
|
|
5849
|
+
},
|
|
5850
|
+
canScrollRight: {
|
|
5851
|
+
true: [
|
|
5852
|
+
"[--tu-hos-solid-right:0px]",
|
|
5853
|
+
"[--tu-hos-fade-right:1.25rem]",
|
|
5854
|
+
"group-hover:[--tu-hos-solid-right:1rem]",
|
|
5855
|
+
"group-hover:[--tu-hos-fade-right:2.25rem]",
|
|
5856
|
+
"group-has-[:focus-visible]:[--tu-hos-fade-right:2.25rem]",
|
|
5857
|
+
],
|
|
5858
|
+
false: ["[--tu-hos-solid-right:0px]", "[--tu-hos-fade-right:0px]"],
|
|
5813
5859
|
},
|
|
5814
5860
|
},
|
|
5815
5861
|
});
|
|
5816
|
-
|
|
5817
|
-
|
|
5862
|
+
|
|
5863
|
+
const cvaOverflowIndicatorHitRow = cva({
|
|
5864
|
+
base: ["flex", "h-full", "w-full", "items-center", "pointer-events-none", "z-10"],
|
|
5818
5865
|
variants: {
|
|
5819
5866
|
direction: {
|
|
5820
5867
|
left: ["justify-start"],
|
|
@@ -5822,43 +5869,72 @@ const cvaJustificationContainer = cva({
|
|
|
5822
5869
|
},
|
|
5823
5870
|
},
|
|
5824
5871
|
});
|
|
5825
|
-
const
|
|
5872
|
+
const cvaOverflowIndicatorHit = cva({
|
|
5826
5873
|
base: [
|
|
5827
|
-
"
|
|
5874
|
+
"pointer-events-auto",
|
|
5875
|
+
"inline-flex",
|
|
5876
|
+
"h-full",
|
|
5877
|
+
"items-center",
|
|
5878
|
+
"justify-center",
|
|
5879
|
+
"px-1",
|
|
5880
|
+
"border-0",
|
|
5881
|
+
"bg-transparent",
|
|
5882
|
+
"cursor-pointer",
|
|
5883
|
+
"supports-[color:contrast-color(white)]:[color:contrast-color(var(--hos-surface,Canvas))]",
|
|
5884
|
+
"supports-[not_(color:contrast-color(white))]:text-neutral-900",
|
|
5885
|
+
"supports-[not_(color:contrast-color(white))]:[filter:drop-shadow(0_0_0.5px_#fff)_drop-shadow(0_1px_0_#fff)_drop-shadow(0_-1px_0_#fff)_drop-shadow(1px_0_0_#fff)_drop-shadow(-1px_0_0_#fff)]",
|
|
5828
5886
|
"opacity-0",
|
|
5887
|
+
"starting:opacity-0",
|
|
5829
5888
|
"transition-opacity",
|
|
5830
5889
|
"duration-200",
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
"group-focus-
|
|
5835
|
-
"rounded-full",
|
|
5836
|
-
"mx-1",
|
|
5890
|
+
// Keyboard focus (not a plain mouse-click `:focus`) always reveals the control it landed
|
|
5891
|
+
// on, even the disabled one at an exhausted edge -- that's the only way a sighted keyboard
|
|
5892
|
+
// user gets to see what they just tabbed to.
|
|
5893
|
+
"group-has-[:focus-visible]:opacity-100",
|
|
5837
5894
|
],
|
|
5895
|
+
variants: {
|
|
5896
|
+
disabled: {
|
|
5897
|
+
// Nothing to scroll to on this side: don't let a mouse hover over the row reveal a
|
|
5898
|
+
// control that would be a no-op if clicked.
|
|
5899
|
+
true: [],
|
|
5900
|
+
false: ["group-hover:opacity-100"],
|
|
5901
|
+
},
|
|
5902
|
+
},
|
|
5903
|
+
defaultVariants: {
|
|
5904
|
+
disabled: false,
|
|
5905
|
+
},
|
|
5838
5906
|
});
|
|
5839
5907
|
|
|
5840
5908
|
/**
|
|
5841
|
-
*
|
|
5842
|
-
*
|
|
5909
|
+
* Edge control for HorizontalOverflowScroller. The fade lives on the content
|
|
5910
|
+
* mask; this is the hover/focus hit target that pages left or right.
|
|
5843
5911
|
*
|
|
5844
5912
|
* @param {OverflowIndicatorProps} props - The props for the component
|
|
5845
5913
|
* @returns {ReactElement} OverflowIndicator component
|
|
5846
5914
|
*/
|
|
5847
|
-
const OverflowIndicator = ({ className, "data-testid": dataTestId, direction, onClickScroll, style, }) => {
|
|
5915
|
+
const OverflowIndicator = ({ className, "data-testid": dataTestId, direction, onClickScroll, disabled = false, style, }) => {
|
|
5916
|
+
const [t] = useTranslation();
|
|
5848
5917
|
const iconName = direction === "left" ? "ChevronLeft" : "ChevronRight";
|
|
5849
|
-
|
|
5850
|
-
|
|
5918
|
+
const ariaLabel = direction === "left" ? t("horizontalOverflowScroller.scrollLeft") : t("horizontalOverflowScroller.scrollRight");
|
|
5919
|
+
return (jsx("div", { className: cvaOverflowIndicatorHitRow({ className, direction }), "data-testid": dataTestId, style: style, children: jsx("button", { "aria-disabled": disabled, "aria-label": ariaLabel, className: cvaOverflowIndicatorHit({ disabled }), "data-testid": dataTestId ? `${dataTestId}-button` : undefined, onClick: disabled ? undefined : onClickScroll, type: "button", children: jsx(Icon, { ariaHidden: true, name: iconName, size: "small" }) }) }));
|
|
5851
5920
|
};
|
|
5852
5921
|
|
|
5853
5922
|
/**
|
|
5854
5923
|
* HorizontalOverflowScroller displays child elements in a horizontal row with automatic overflow detection.
|
|
5855
|
-
* When content overflows, it
|
|
5924
|
+
* When content overflows, it fades the overflowing edge and reveals chevrons on hover or focus so the row can be paged.
|
|
5925
|
+
*
|
|
5926
|
+
* The fade is a CSS mask on the content itself, so it works on any background. At rest the ramp is short so more
|
|
5927
|
+
* items stay visible; hover grows a solid plateau under the chevron and pushes the ramp further in, while
|
|
5928
|
+
* keyboard focus only extends the ramp — a plateau there would erase the focus ring of a child flush with the
|
|
5929
|
+
* edge. Set `--hos-surface` on an ancestor to the background color behind the scroller so the chevrons pick a
|
|
5930
|
+
* contrasting color. It defaults to `Canvas`.
|
|
5856
5931
|
*
|
|
5857
5932
|
* ### When to use
|
|
5858
5933
|
* Use HorizontalOverflowScroller to display a row of items (cards, tags, buttons) that may overflow on smaller screens, with visual cues that more content is available.
|
|
5859
5934
|
*
|
|
5860
5935
|
* ### When not to use
|
|
5861
5936
|
* Do not use HorizontalOverflowScroller for tab navigation — use `TabList` which has its own scroll handling.
|
|
5937
|
+
* Do not use it to hide extra actions — use `MoreMenu` when the overflowing items are secondary actions rather than a row of content to browse.
|
|
5862
5938
|
*
|
|
5863
5939
|
* @example Horizontal scroller for KPI cards
|
|
5864
5940
|
* ```tsx
|
|
@@ -5878,36 +5954,36 @@ const OverflowIndicator = ({ className, "data-testid": dataTestId, direction, on
|
|
|
5878
5954
|
* @returns {ReactElement} HorizontalOverflowScroller component
|
|
5879
5955
|
*/
|
|
5880
5956
|
const HorizontalOverflowScroller = ({ className, "data-testid": dataTestId, children, onScrollStateChange, style, ref, }) => {
|
|
5881
|
-
const
|
|
5882
|
-
|
|
5883
|
-
|
|
5957
|
+
const onScrollStateChangeRef = useRef(onScrollStateChange);
|
|
5958
|
+
useEffect(() => {
|
|
5959
|
+
onScrollStateChangeRef.current = onScrollStateChange;
|
|
5960
|
+
}, [onScrollStateChange]);
|
|
5961
|
+
const handleScrollStateChange = useCallback((state) => {
|
|
5962
|
+
onScrollStateChangeRef.current?.({
|
|
5963
|
+
isScrollable: state.isScrollable,
|
|
5964
|
+
isAtBeginning: state.isAtBeginning,
|
|
5965
|
+
isAtEnd: state.isAtEnd,
|
|
5966
|
+
});
|
|
5967
|
+
}, []);
|
|
5968
|
+
const { ref: scrollRef, element, isScrollable, isAtBeginning, isAtEnd, } = useScrollDetection({
|
|
5884
5969
|
direction: "horizontal",
|
|
5885
|
-
onScrollStateChange:
|
|
5886
|
-
? (state) => onScrollStateChange({
|
|
5887
|
-
isScrollable: state.isScrollable,
|
|
5888
|
-
isAtBeginning: state.isAtBeginning,
|
|
5889
|
-
isAtEnd: state.isAtEnd,
|
|
5890
|
-
})
|
|
5891
|
-
: undefined,
|
|
5970
|
+
onScrollStateChange: handleScrollStateChange,
|
|
5892
5971
|
});
|
|
5893
|
-
const mergedRef = useMergeRefs([
|
|
5894
|
-
const
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
element
|
|
5898
|
-
left: -containerGeometry.width,
|
|
5899
|
-
behavior: "smooth",
|
|
5900
|
-
});
|
|
5901
|
-
};
|
|
5902
|
-
const handleScrollRight = () => {
|
|
5903
|
-
if (!element || containerGeometry?.width === undefined)
|
|
5972
|
+
const mergedRef = useMergeRefs([scrollRef, ref]);
|
|
5973
|
+
const canScrollLeft = isScrollable && !isAtBeginning;
|
|
5974
|
+
const canScrollRight = isScrollable && !isAtEnd;
|
|
5975
|
+
const scrollByPage = useCallback((direction) => {
|
|
5976
|
+
if (!element) {
|
|
5904
5977
|
return;
|
|
5978
|
+
}
|
|
5905
5979
|
element.scrollBy({
|
|
5906
|
-
left:
|
|
5980
|
+
left: direction * element.clientWidth,
|
|
5907
5981
|
behavior: "smooth",
|
|
5908
5982
|
});
|
|
5909
|
-
};
|
|
5910
|
-
return (jsxs(
|
|
5983
|
+
}, [element]);
|
|
5984
|
+
return (jsxs(Fragment, { children: [jsx("style", { children: fadeMaskStyleSheet }), jsxs(ZStack, { className: cvaHorizontalOverflowScrollerAndIndicatorsContainer({ className }), style: style, children: [jsx("div", { className: cvaHorizontalOverflowScroller({
|
|
5985
|
+
className: cvaHorizontalOverflowScrollerFadeMask({ canScrollLeft, canScrollRight }),
|
|
5986
|
+
}), "data-testid": dataTestId, ref: mergedRef, children: children }), isScrollable ? (jsx(OverflowIndicator, { "data-testid": dataTestId ? `${dataTestId}-left-indicator` : undefined, direction: "left", disabled: !canScrollLeft, onClickScroll: () => scrollByPage(-1) })) : null, isScrollable ? (jsx(OverflowIndicator, { "data-testid": dataTestId ? `${dataTestId}-right-indicator` : undefined, direction: "right", disabled: !canScrollRight, onClickScroll: () => scrollByPage(1) })) : null] })] }));
|
|
5911
5987
|
};
|
|
5912
5988
|
|
|
5913
5989
|
const cvaIndicator = cva({ base: ["inline-flex", "items-center"] });
|
|
@@ -8289,6 +8365,7 @@ const cvaMoreMenu = cva({ base: ["p-0"] });
|
|
|
8289
8365
|
*
|
|
8290
8366
|
* ### When not to use
|
|
8291
8367
|
* Do not use MoreMenu for primary actions that should always be visible. Use `Button` instead.
|
|
8368
|
+
* Do not use it to overflow a row of content (tags, KPIs, chips) — use `HorizontalOverflowScroller` when those items should stay visible and be browsed horizontally.
|
|
8292
8369
|
*
|
|
8293
8370
|
* @example Action items with render prop — Pass a function as `children` to receive the `close` callback and dismiss the menu after an action.
|
|
8294
8371
|
* ```tsx
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-components",
|
|
3
|
-
"version": "2.13.
|
|
3
|
+
"version": "2.13.13",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"migrations": "./migrations.json",
|
|
@@ -14,16 +14,16 @@
|
|
|
14
14
|
"@floating-ui/react": "^0.26.25",
|
|
15
15
|
"string-ts": "^2.0.0",
|
|
16
16
|
"tailwind-merge": "^2.0.0",
|
|
17
|
-
"@trackunit/ui-design-tokens": "1.15.
|
|
18
|
-
"@trackunit/css-class-variance-utilities": "2.0.
|
|
19
|
-
"@trackunit/shared-utils": "1.16.
|
|
20
|
-
"@trackunit/ui-icons": "1.14.
|
|
17
|
+
"@trackunit/ui-design-tokens": "1.15.28",
|
|
18
|
+
"@trackunit/css-class-variance-utilities": "2.0.9",
|
|
19
|
+
"@trackunit/shared-utils": "1.16.44",
|
|
20
|
+
"@trackunit/ui-icons": "1.14.37",
|
|
21
21
|
"es-toolkit": "^1.39.10",
|
|
22
22
|
"@tanstack/react-virtual": "^3.14.3",
|
|
23
23
|
"dequal": "^2.0.3",
|
|
24
24
|
"fflate": "^0.8.2",
|
|
25
25
|
"zod": "^3.25.76",
|
|
26
|
-
"@trackunit/i18n-library-translation": "2.4.
|
|
26
|
+
"@trackunit/i18n-library-translation": "2.4.53"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"react": "^19.0.0",
|
|
@@ -1,27 +1,35 @@
|
|
|
1
|
-
import { ReactElement, ReactNode } from "react";
|
|
1
|
+
import { type ReactElement, type ReactNode } from "react";
|
|
2
2
|
import { CommonProps } from "../../common/CommonProps";
|
|
3
|
-
import type { Styleable } from "../../common/Styleable";
|
|
4
3
|
import { Refable } from "../../common/Refable";
|
|
4
|
+
import type { Styleable } from "../../common/Styleable";
|
|
5
|
+
export type HorizontalOverflowScrollState = {
|
|
6
|
+
readonly isScrollable: boolean;
|
|
7
|
+
readonly isAtBeginning: boolean;
|
|
8
|
+
readonly isAtEnd: boolean;
|
|
9
|
+
};
|
|
5
10
|
export interface HorizontalOverflowScrollerProps extends CommonProps, Styleable, Refable<HTMLDivElement> {
|
|
6
11
|
children: ReactNode;
|
|
7
12
|
/**
|
|
8
|
-
*
|
|
13
|
+
* Called when overflow or edge position changes.
|
|
9
14
|
*/
|
|
10
|
-
onScrollStateChange?: (state:
|
|
11
|
-
isScrollable: boolean;
|
|
12
|
-
isAtBeginning: boolean;
|
|
13
|
-
isAtEnd: boolean;
|
|
14
|
-
}) => void;
|
|
15
|
+
onScrollStateChange?: (state: HorizontalOverflowScrollState) => void;
|
|
15
16
|
}
|
|
16
17
|
/**
|
|
17
18
|
* HorizontalOverflowScroller displays child elements in a horizontal row with automatic overflow detection.
|
|
18
|
-
* When content overflows, it
|
|
19
|
+
* When content overflows, it fades the overflowing edge and reveals chevrons on hover or focus so the row can be paged.
|
|
20
|
+
*
|
|
21
|
+
* The fade is a CSS mask on the content itself, so it works on any background. At rest the ramp is short so more
|
|
22
|
+
* items stay visible; hover grows a solid plateau under the chevron and pushes the ramp further in, while
|
|
23
|
+
* keyboard focus only extends the ramp — a plateau there would erase the focus ring of a child flush with the
|
|
24
|
+
* edge. Set `--hos-surface` on an ancestor to the background color behind the scroller so the chevrons pick a
|
|
25
|
+
* contrasting color. It defaults to `Canvas`.
|
|
19
26
|
*
|
|
20
27
|
* ### When to use
|
|
21
28
|
* Use HorizontalOverflowScroller to display a row of items (cards, tags, buttons) that may overflow on smaller screens, with visual cues that more content is available.
|
|
22
29
|
*
|
|
23
30
|
* ### When not to use
|
|
24
31
|
* Do not use HorizontalOverflowScroller for tab navigation — use `TabList` which has its own scroll handling.
|
|
32
|
+
* Do not use it to hide extra actions — use `MoreMenu` when the overflowing items are secondary actions rather than a row of content to browse.
|
|
25
33
|
*
|
|
26
34
|
* @example Horizontal scroller for KPI cards
|
|
27
35
|
* ```tsx
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare const fadeMaskStyleSheet = "\n @property --tu-hos-solid-left {\n syntax: '<length>';\n initial-value: 0px;\n inherits: false;\n }\n\n @property --tu-hos-solid-right {\n syntax: '<length>';\n initial-value: 0px;\n inherits: false;\n }\n\n @property --tu-hos-fade-left {\n syntax: '<length>';\n initial-value: 0px;\n inherits: false;\n }\n\n @property --tu-hos-fade-right {\n syntax: '<length>';\n initial-value: 0px;\n inherits: false;\n }\n";
|
|
1
2
|
export declare const cvaHorizontalOverflowScroller: import("cva").CVAComponent<Omit<{
|
|
2
3
|
base: string[];
|
|
3
4
|
}, "defaultVariants"> & {
|
|
@@ -10,3 +11,37 @@ export declare const cvaHorizontalOverflowScrollerAndIndicatorsContainer: import
|
|
|
10
11
|
variants: unknown;
|
|
11
12
|
defaultVariants: Omit<{}, never>;
|
|
12
13
|
}, unknown>;
|
|
14
|
+
export declare const cvaHorizontalOverflowScrollerFadeMask: import("cva").CVAComponent<Omit<{
|
|
15
|
+
base: string[];
|
|
16
|
+
variants: {
|
|
17
|
+
canScrollLeft: {
|
|
18
|
+
true: string[];
|
|
19
|
+
false: string[];
|
|
20
|
+
};
|
|
21
|
+
canScrollRight: {
|
|
22
|
+
true: string[];
|
|
23
|
+
false: string[];
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
}, "defaultVariants"> & {
|
|
27
|
+
variants: {
|
|
28
|
+
canScrollLeft: {
|
|
29
|
+
true: string[];
|
|
30
|
+
false: string[];
|
|
31
|
+
};
|
|
32
|
+
canScrollRight: {
|
|
33
|
+
true: string[];
|
|
34
|
+
false: string[];
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
defaultVariants: Omit<{}, never>;
|
|
38
|
+
}, {
|
|
39
|
+
canScrollLeft: {
|
|
40
|
+
true: string[];
|
|
41
|
+
false: string[];
|
|
42
|
+
};
|
|
43
|
+
canScrollRight: {
|
|
44
|
+
true: string[];
|
|
45
|
+
false: string[];
|
|
46
|
+
};
|
|
47
|
+
}>;
|
|
@@ -1,23 +1,27 @@
|
|
|
1
|
-
import { MouseEventHandler, ReactElement } from "react";
|
|
1
|
+
import { type MouseEventHandler, type ReactElement } from "react";
|
|
2
2
|
import { CommonProps } from "../../common/CommonProps";
|
|
3
3
|
import type { Styleable } from "../../common/Styleable";
|
|
4
4
|
type OverflowDirection = "left" | "right";
|
|
5
5
|
export interface OverflowIndicatorProps extends CommonProps, Styleable {
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Which edge of the scroller this control sits on.
|
|
8
8
|
*/
|
|
9
9
|
direction: OverflowDirection;
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Called when the chevron is activated to page in this direction.
|
|
12
12
|
*/
|
|
13
13
|
onClickScroll?: MouseEventHandler<HTMLButtonElement>;
|
|
14
|
+
/**
|
|
15
|
+
* Whether the control has reached the corresponding scroll edge.
|
|
16
|
+
*/
|
|
17
|
+
disabled?: boolean;
|
|
14
18
|
}
|
|
15
19
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
20
|
+
* Edge control for HorizontalOverflowScroller. The fade lives on the content
|
|
21
|
+
* mask; this is the hover/focus hit target that pages left or right.
|
|
18
22
|
*
|
|
19
23
|
* @param {OverflowIndicatorProps} props - The props for the component
|
|
20
24
|
* @returns {ReactElement} OverflowIndicator component
|
|
21
25
|
*/
|
|
22
|
-
export declare const OverflowIndicator: ({ className, "data-testid": dataTestId, direction, onClickScroll, style, }: OverflowIndicatorProps) => ReactElement;
|
|
26
|
+
export declare const OverflowIndicator: ({ className, "data-testid": dataTestId, direction, onClickScroll, disabled, style, }: OverflowIndicatorProps) => ReactElement;
|
|
23
27
|
export {};
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
base: string[];
|
|
3
|
-
}, "defaultVariants"> & {
|
|
4
|
-
variants: unknown;
|
|
5
|
-
defaultVariants: Omit<{}, never>;
|
|
6
|
-
}, unknown>;
|
|
7
|
-
export declare const cvaOverflowIndicatorGradient: import("cva").CVAComponent<Omit<{
|
|
1
|
+
export declare const cvaOverflowIndicatorHitRow: import("cva").CVAComponent<Omit<{
|
|
8
2
|
base: string[];
|
|
9
3
|
variants: {
|
|
10
4
|
direction: {
|
|
@@ -26,31 +20,30 @@ export declare const cvaOverflowIndicatorGradient: import("cva").CVAComponent<Om
|
|
|
26
20
|
right: string[];
|
|
27
21
|
};
|
|
28
22
|
}>;
|
|
29
|
-
export declare const
|
|
23
|
+
export declare const cvaOverflowIndicatorHit: import("cva").CVAComponent<Omit<{
|
|
30
24
|
base: string[];
|
|
31
25
|
variants: {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
disabled: {
|
|
27
|
+
true: never[];
|
|
28
|
+
false: string[];
|
|
35
29
|
};
|
|
36
30
|
};
|
|
31
|
+
defaultVariants: {
|
|
32
|
+
disabled: false;
|
|
33
|
+
};
|
|
37
34
|
}, "defaultVariants"> & {
|
|
38
35
|
variants: {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
disabled: {
|
|
37
|
+
true: never[];
|
|
38
|
+
false: string[];
|
|
42
39
|
};
|
|
43
40
|
};
|
|
44
|
-
defaultVariants: Omit<{},
|
|
41
|
+
defaultVariants: Omit<{}, "disabled"> & {
|
|
42
|
+
disabled: false;
|
|
43
|
+
};
|
|
45
44
|
}, {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
disabled: {
|
|
46
|
+
true: never[];
|
|
47
|
+
false: string[];
|
|
49
48
|
};
|
|
50
49
|
}>;
|
|
51
|
-
export declare const cvaOverflowIndicatorButton: import("cva").CVAComponent<Omit<{
|
|
52
|
-
base: string[];
|
|
53
|
-
}, "defaultVariants"> & {
|
|
54
|
-
variants: unknown;
|
|
55
|
-
defaultVariants: Omit<{}, never>;
|
|
56
|
-
}, unknown>;
|
|
@@ -50,6 +50,7 @@ export interface MoreMenuProps extends CommonProps, Styleable, Refable<HTMLDivEl
|
|
|
50
50
|
*
|
|
51
51
|
* ### When not to use
|
|
52
52
|
* Do not use MoreMenu for primary actions that should always be visible. Use `Button` instead.
|
|
53
|
+
* Do not use it to overflow a row of content (tags, KPIs, chips) — use `HorizontalOverflowScroller` when those items should stay visible and be browsed horizontally.
|
|
53
54
|
*
|
|
54
55
|
* @example Action items with render prop — Pass a function as `children` to receive the `close` callback and dismiss the menu after an action.
|
|
55
56
|
* ```tsx
|
package/migrations/entry.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"entry.js","sourceRoot":"","sources":["../../../../../libs/react/components/migrations/entry.ts"],"names":[],"mappings":"","sourcesContent":["// Migration entry point for @nx/js:tsc build target.\n// Migrations are registered in ../migrations.json and resolved by NX at runtime.\nexport {};\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"jsx-utils.js","sourceRoot":"","sources":["../../../../../../libs/react/components/migrations/utils/jsx-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { logger, type Tree, visitNotIgnoredFiles } from \"@nx/devkit\";\nimport * as ts from \"typescript\";\n\nconst TSX_EXTENSIONS = [\".tsx\", \".jsx\"] as const;\nconst TS_EXTENSIONS = [\".ts\", \".tsx\", \".jsx\"] as const;\n\nconst isTsxFile = (filePath: string): boolean => TSX_EXTENSIONS.some(ext => filePath.endsWith(ext));\nconst isTsFile = (filePath: string): boolean => TS_EXTENSIONS.some(ext => filePath.endsWith(ext));\n\nconst isUnderNodeModules = (filePath: string): boolean =>\n filePath.includes(\"/node_modules/\") || filePath.startsWith(\"node_modules/\");\n\nconst isUnderDist = (filePath: string): boolean =>\n filePath.includes(\"/dist/\") || filePath.startsWith(\"dist/\") || filePath.includes(\"/.nx/\");\n\n/**\n * Visits every `.tsx`/`.jsx` file under the workspace root and invokes the\n * callback with the file path and its current contents. Files that don't\n * include the marker substring are skipped, which makes large workspaces\n * cheap to scan.\n */\nexport const visitTsxFiles = (\n tree: Tree,\n marker: string,\n callback: (filePath: string, content: string) => string | null | undefined\n): number => {\n let touched = 0;\n visitNotIgnoredFiles(tree, \"/\", filePath => {\n if (!isTsxFile(filePath)) return;\n if (isUnderNodeModules(filePath) || isUnderDist(filePath)) return;\n const content = tree.read(filePath, \"utf-8\");\n if (content === null) return;\n if (!content.includes(marker)) return;\n const updated = callback(filePath, content);\n if (updated !== null && updated !== undefined && updated !== content) {\n tree.write(filePath, updated);\n touched += 1;\n }\n });\n return touched;\n};\n\n/**\n * Same as {@link visitTsxFiles} but also includes plain `.ts` files. Use this\n * when the codemod also rewrites non-JSX files such as helpers or hooks.\n */\nexport const visitTsFiles = (\n tree: Tree,\n marker: string,\n callback: (filePath: string, content: string) => string | null | undefined\n): number => {\n let touched = 0;\n visitNotIgnoredFiles(tree, \"/\", filePath => {\n if (!isTsFile(filePath)) return;\n if (isUnderNodeModules(filePath) || isUnderDist(filePath)) return;\n const content = tree.read(filePath, \"utf-8\");\n if (content === null) return;\n if (!content.includes(marker)) return;\n const updated = callback(filePath, content);\n if (updated !== null && updated !== undefined && updated !== content) {\n tree.write(filePath, updated);\n touched += 1;\n }\n });\n return touched;\n};\n\n/**\n * Mapping of imported component aliases to their original names for a given\n * package. For `import { IconButton as Btn } from \"@trackunit/react-components\"`\n * this returns `{ Btn: \"IconButton\" }`.\n *\n * Returns `null` when the file imports nothing from the package, which lets\n * callers short-circuit before parsing JSX.\n */\nexport const getImportedAliases = (sourceFile: ts.SourceFile, packageName: string): Record<string, string> | null => {\n const result: Record<string, string> = {};\n let found = false;\n\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const moduleSpecifier = stmt.moduleSpecifier;\n if (!ts.isStringLiteral(moduleSpecifier)) continue;\n if (moduleSpecifier.text !== packageName) continue;\n\n const namedBindings = stmt.importClause?.namedBindings;\n if (namedBindings === undefined || !ts.isNamedImports(namedBindings)) continue;\n\n for (const element of namedBindings.elements) {\n const localName = element.name.text;\n const importedName = element.propertyName?.text ?? localName;\n result[localName] = importedName;\n found = true;\n }\n }\n\n return found ? result : null;\n};\n\n/**\n * Returns the local alias used in this file for `originalName` when imported\n * from `packageName`, or `null` if the component is not imported.\n */\nexport const getLocalAliasFor = (\n sourceFile: ts.SourceFile,\n packageName: string,\n originalName: string\n): string | null => {\n const aliases = getImportedAliases(sourceFile, packageName);\n if (aliases === null) return null;\n for (const [local, original] of Object.entries(aliases)) {\n if (original === originalName) return local;\n }\n return null;\n};\n\nexport type JsxElementMatch = {\n /** The opening JSX element (the one carrying the attributes). */\n openingElement: ts.JsxOpeningElement | ts.JsxSelfClosingElement;\n /** The full element including children, or the self-closing element. */\n element: ts.JsxElement | ts.JsxSelfClosingElement;\n};\n\n/**\n * Finds every JSX element whose tag name resolves to one of `tagNames`\n * (typically the local aliases returned by {@link getImportedAliases}).\n *\n * The result intentionally includes both opening and full elements so callers\n * can manipulate attributes (via `openingElement`) or wrap/replace the whole\n * element (via `element`).\n */\nexport const findJsxElements = (\n sourceFile: ts.SourceFile,\n tagNames: ReadonlyArray<string>\n): ReadonlyArray<JsxElementMatch> => {\n const matches: Array<JsxElementMatch> = [];\n const tagSet = new Set(tagNames);\n\n const visit = (node: ts.Node): void => {\n if (ts.isJsxSelfClosingElement(node)) {\n if (ts.isIdentifier(node.tagName) && tagSet.has(node.tagName.text)) {\n matches.push({ openingElement: node, element: node });\n }\n } else if (ts.isJsxElement(node)) {\n const opening = node.openingElement;\n if (ts.isIdentifier(opening.tagName) && tagSet.has(opening.tagName.text)) {\n matches.push({ openingElement: opening, element: node });\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return matches;\n};\n\n/**\n * Looks up a named JSX attribute on the opening element. Returns `null` when\n * the attribute is missing or part of a spread attribute (which we cannot\n * statically inspect).\n */\nexport const findJsxAttribute = (\n openingElement: ts.JsxOpeningElement | ts.JsxSelfClosingElement,\n attributeName: string\n): ts.JsxAttribute | null => {\n for (const attr of openingElement.attributes.properties) {\n if (!ts.isJsxAttribute(attr)) continue;\n if (!ts.isIdentifier(attr.name)) continue;\n if (attr.name.text === attributeName) return attr;\n }\n return null;\n};\n\n/**\n * `true` when the element forwards a spread expression such as `{...rest}`,\n * which means we can't be sure which attributes are actually set.\n */\nexport const hasSpreadAttribute = (openingElement: ts.JsxOpeningElement | ts.JsxSelfClosingElement): boolean => {\n return openingElement.attributes.properties.some(prop => ts.isJsxSpreadAttribute(prop));\n};\n\n/**\n * Parses the file as TSX so JSX is recognised. We do not need a full program\n * here; tsquery's `ast` helper produces a script-kind source file which loses\n * JSX context, so we go through `createSourceFile` directly.\n */\nexport const parseTsx = (content: string, fileName = \"file.tsx\"): ts.SourceFile =>\n ts.createSourceFile(fileName, content, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);\n\n/**\n * Helper for codemods to log a one-line summary at the end of a run. Migration\n * runners aggregate logs per migration, so this keeps output focused.\n */\nexport const logSummary = (migrationName: string, touched: number, manualReviewNeeded?: number): void => {\n if (touched === 0) {\n logger.info(` ${migrationName}: no files changed`);\n return;\n }\n const reviewSuffix =\n manualReviewNeeded !== undefined && manualReviewNeeded > 0\n ? ` (${manualReviewNeeded} location(s) need manual review)`\n : \"\";\n logger.info(` ${migrationName}: updated ${touched} file(s)${reviewSuffix}`);\n};\n\n/**\n * Inserts an attribute string immediately after the tag name (so the new\n * attribute appears first). Returns the resulting source content.\n *\n * The added attribute is rendered verbatim, so callers are responsible for\n * including the leading space (e.g. ` title=\"Close\"`).\n */\nexport const insertAttributeIntoOpeningTag = (\n content: string,\n openingElement: ts.JsxOpeningElement | ts.JsxSelfClosingElement,\n attributeText: string\n): string => {\n const tagName = openingElement.tagName;\n const insertPos = tagName.getEnd();\n return `${content.slice(0, insertPos)} ${attributeText}${content.slice(insertPos)}`;\n};\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"breadcrumb-remove-deprecated-props.js","sourceRoot":"","sources":["../../../../../../libs/react/components/migrations/v2-0-0/breadcrumb-remove-deprecated-props.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Tree, logger } from \"@nx/devkit\";\nimport {\n findJsxAttribute,\n findJsxElements,\n getImportedAliases,\n logSummary,\n parseTsx,\n visitTsxFiles,\n} from \"../utils/jsx-utils\";\n\nconst PACKAGE_NAME = \"@trackunit/react-components\";\nconst COMPONENT_NAMES = [\"Breadcrumb\", \"BreadcrumbContainer\", \"BreadcrumbForMediumScreen\"] as const;\nconst PROPS_TO_REMOVE = [\"backButtonTitle\", \"expandCollapsedItemsTitle\"] as const;\n\nconst stripDeprecatedProps = (filePath: string, content: string): string | null => {\n const sourceFile = parseTsx(content, filePath);\n\n const aliases = getImportedAliases(sourceFile, PACKAGE_NAME);\n if (aliases === null) return null;\n\n const localTagNames: Array<string> = [];\n for (const [local, original] of Object.entries(aliases)) {\n if (COMPONENT_NAMES.some(name => name === original)) {\n localTagNames.push(local);\n }\n }\n if (localTagNames.length === 0) return null;\n\n const matches = findJsxElements(sourceFile, localTagNames);\n if (matches.length === 0) return null;\n\n // Collect every (start, end) range we want to delete. We process them in\n // reverse so earlier offsets stay valid while we splice.\n const ranges: Array<{ start: number; end: number }> = [];\n for (const { openingElement } of matches) {\n for (const propName of PROPS_TO_REMOVE) {\n const attr = findJsxAttribute(openingElement, propName);\n if (attr === null) continue;\n\n // Drop trailing whitespace + the attribute itself so we don't leave a\n // dangling space inside the opening tag. e.g. `<X foo=\"a\" bar=\"b\" />`\n // becomes `<X foo=\"a\" />` and `<X bar=\"b\" />` becomes `<X />`.\n let start = attr.getFullStart();\n const end = attr.getEnd();\n // getFullStart includes leading whitespace which is what we want.\n // Guard against negative ranges if multiple props collapse later.\n if (start < 0) start = attr.getStart();\n ranges.push({ start, end });\n }\n }\n\n if (ranges.length === 0) return null;\n\n ranges.sort((a, b) => b.start - a.start);\n\n let updated = content;\n for (const { start, end } of ranges) {\n updated = updated.slice(0, start) + updated.slice(end);\n }\n\n return updated;\n};\n\n/**\n * Removes the no-longer-supported `backButtonTitle` and\n * `expandCollapsedItemsTitle` props from `<Breadcrumb>`,\n * `<BreadcrumbContainer>`, and `<BreadcrumbForMediumScreen>`. Their accessible\n * names are now sourced from the `react-components` library translations.\n */\nexport const breadcrumbRemoveDeprecatedProps = (tree: Tree): void => {\n const touched = visitTsxFiles(tree, \"Breadcrumb\", stripDeprecatedProps);\n logSummary(\"breadcrumb-remove-deprecated-props\", touched);\n logger.info(\n \" Ensure the host application registers the @trackunit/react-components library translations so the back/expand buttons render localized labels.\"\n );\n};\n\nexport default breadcrumbRemoveDeprecatedProps;\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cardheader-onclickclose-to-actions.js","sourceRoot":"","sources":["../../../../../../libs/react/components/migrations/v2-0-0/cardheader-onclickclose-to-actions.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Tree } from \"@nx/devkit\";\nimport * as ts from \"typescript\";\nimport {\n findJsxAttribute,\n findJsxElements,\n getImportedAliases,\n logSummary,\n parseTsx,\n visitTsxFiles,\n} from \"../utils/jsx-utils\";\n\nconst PACKAGE_NAME = \"@trackunit/react-components\";\nconst COMPONENT_NAME = \"CardHeader\";\n\nconst CLOSE_BUTTON_NAMES = [\"IconButton\", \"Icon\"] as const;\n\nconst renderCloseButton = (handlerExpr: string, iconAlias: string, iconButtonAlias: string): string =>\n `<${iconButtonAlias} icon={<${iconAlias} name=\"XMark\" size=\"small\" />} onClick={${handlerExpr}} title=\"Close\" variant=\"ghost-neutral\" />`;\n\nconst ensureNamedImport = (content: string, packageName: string, namesToAdd: ReadonlyArray<string>): string => {\n const sourceFile = parseTsx(content, \"source.tsx\");\n const aliases = getImportedAliases(sourceFile, packageName) ?? {};\n\n const missing = namesToAdd.filter(name => !Object.values(aliases).includes(name));\n if (missing.length === 0) return content;\n\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const moduleSpecifier = stmt.moduleSpecifier;\n if (!ts.isStringLiteral(moduleSpecifier) || moduleSpecifier.text !== packageName) continue;\n\n const namedBindings = stmt.importClause?.namedBindings;\n if (namedBindings === undefined || !ts.isNamedImports(namedBindings)) continue;\n\n const elementsText = namedBindings.elements.map(el => el.getText()).join(\", \");\n const merged = [elementsText, ...missing].join(\", \");\n const before = content.slice(0, namedBindings.getStart());\n const after = content.slice(namedBindings.getEnd());\n return `${before}{ ${merged} }${after}`;\n }\n\n // No existing import from the package; add a fresh line near the top.\n const importLine = `import { ${missing.join(\", \")} } from \"${packageName}\";\\n`;\n return importLine + content;\n};\n\nconst transformCardHeaderUsage = (filePath: string, content: string): string | null => {\n const sourceFile = parseTsx(content, filePath);\n\n const aliases = getImportedAliases(sourceFile, PACKAGE_NAME);\n if (aliases === null) return null;\n\n const cardHeaderAlias = Object.entries(aliases).find(([, name]) => name === COMPONENT_NAME)?.[0];\n if (cardHeaderAlias === undefined) return null;\n\n const matches = findJsxElements(sourceFile, [cardHeaderAlias]);\n if (matches.length === 0) return null;\n\n type Edit = { start: number; end: number; replacement: string };\n const edits: Array<Edit> = [];\n\n for (const { openingElement } of matches) {\n const onClickCloseAttr = findJsxAttribute(openingElement, \"onClickClose\");\n if (onClickCloseAttr === null) continue;\n\n const initializer = onClickCloseAttr.initializer;\n if (initializer === undefined) continue;\n\n let handlerExpr: string;\n if (ts.isJsxExpression(initializer) && initializer.expression !== undefined) {\n handlerExpr = initializer.expression.getText();\n } else if (ts.isStringLiteral(initializer)) {\n handlerExpr = `\"${initializer.text}\"`;\n } else {\n continue;\n }\n\n const actionsAttr = findJsxAttribute(openingElement, \"actions\");\n if (actionsAttr !== null) {\n // Don't try to merge with an existing actions prop; flag and skip.\n continue;\n }\n\n const replacement = `actions={${renderCloseButton(handlerExpr, \"Icon\", \"IconButton\")}}`;\n edits.push({\n start: onClickCloseAttr.getStart(),\n end: onClickCloseAttr.getEnd(),\n replacement,\n });\n }\n\n if (edits.length === 0) return null;\n\n edits.sort((a, b) => b.start - a.start);\n\n let updated = content;\n for (const { start, end, replacement } of edits) {\n updated = updated.slice(0, start) + replacement + updated.slice(end);\n }\n\n updated = ensureNamedImport(updated, PACKAGE_NAME, [...CLOSE_BUTTON_NAMES]);\n\n return updated;\n};\n\n/**\n * Replaces the removed `onClickClose` prop on `<CardHeader>` with the\n * equivalent action rendered through the `actions` slot using `IconButton` +\n * the `XMark` icon.\n *\n * Cards that already declared `actions` are skipped to avoid clobbering\n * existing markup.\n */\nexport const cardHeaderOnClickCloseToActions = (tree: Tree): void => {\n const touched = visitTsxFiles(tree, \"CardHeader\", transformCardHeaderUsage);\n logSummary(\"cardheader-onclickclose-to-actions\", touched);\n};\n\nexport default cardHeaderOnClickCloseToActions;\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"iconbutton-add-required-name.js","sourceRoot":"","sources":["../../../../../../libs/react/components/migrations/v2-0-0/iconbutton-add-required-name.ts"],"names":[],"mappings":";;;AAAA,uCAA+C;AAC/C,kDAQ4B;AAE5B,MAAM,YAAY,GAAG,6BAA6B,CAAC;AACnD,MAAM,cAAc,GAAG,YAAY,CAAC;AAEpC,MAAM,iBAAiB,GAAG,0CAA0C,CAAC;AAErE,MAAM,wBAAwB,GAAG,CAAC,QAAgB,EAAE,OAAe,EAAiB,EAAE;IACpF,MAAM,UAAU,GAAG,IAAA,oBAAQ,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAE/C,MAAM,OAAO,GAAG,IAAA,8BAAkB,EAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAC7D,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAElC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5F,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAE1C,MAAM,OAAO,GAAG,IAAA,2BAAe,EAAC,UAAU,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAC1D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAGtC,MAAM,KAAK,GAAgB,EAAE,CAAC;IAE9B,KAAK,MAAM,EAAE,cAAc,EAAE,IAAI,OAAO,EAAE,CAAC;QACzC,IAAI,IAAA,8BAAkB,EAAC,cAAc,CAAC;YAAE,SAAS;QAEjD,MAAM,QAAQ,GAAG,IAAA,4BAAgB,EAAC,cAAc,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QACpE,MAAM,YAAY,GAAG,IAAA,4BAAgB,EAAC,cAAc,EAAE,WAAW,CAAC,KAAK,IAAI,CAAC;QAC5E,IAAI,QAAQ,IAAI,YAAY;YAAE,SAAS;QAEvC,KAAK,CAAC,IAAI,CAAC;YACT,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE;YACvC,IAAI,EAAE,WAAW,iBAAiB,GAAG;SACtC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAExE,IAAI,OAAO,GAAG,OAAO,CAAC;IACtB,KAAK,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,KAAK,EAAE,CAAC;QACrC,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF;;;;;;;GAOG;AACI,MAAM,yBAAyB,GAAG,CAAC,IAAU,EAAQ,EAAE;IAC5D,MAAM,OAAO,GAAG,IAAA,yBAAa,EAAC,IAAI,EAAE,YAAY,EAAE,wBAAwB,CAAC,CAAC;IAC5E,IAAA,sBAAU,EAAC,8BAA8B,EAAE,OAAO,CAAC,CAAC;IACpD,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,eAAM,CAAC,IAAI,CACT,8BAA8B,iBAAiB,6EAA6E,CAC7H,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AARW,QAAA,yBAAyB,6BAQpC;AAEF,kBAAe,iCAAyB,CAAC","sourcesContent":["import { type Tree, logger } from \"@nx/devkit\";\nimport {\n findJsxAttribute,\n findJsxElements,\n getImportedAliases,\n hasSpreadAttribute,\n logSummary,\n parseTsx,\n visitTsxFiles,\n} from \"../utils/jsx-utils\";\n\nconst PACKAGE_NAME = \"@trackunit/react-components\";\nconst COMPONENT_NAME = \"IconButton\";\n\nconst PLACEHOLDER_TITLE = \"TODO Replace with localized button title\";\n\nconst transformIconButtonUsage = (filePath: string, content: string): string | null => {\n const sourceFile = parseTsx(content, filePath);\n\n const aliases = getImportedAliases(sourceFile, PACKAGE_NAME);\n if (aliases === null) return null;\n\n const localAlias = Object.entries(aliases).find(([, name]) => name === COMPONENT_NAME)?.[0];\n if (localAlias === undefined) return null;\n\n const matches = findJsxElements(sourceFile, [localAlias]);\n if (matches.length === 0) return null;\n\n type Edit = { offset: number; text: string };\n const edits: Array<Edit> = [];\n\n for (const { openingElement } of matches) {\n if (hasSpreadAttribute(openingElement)) continue;\n\n const hasTitle = findJsxAttribute(openingElement, \"title\") !== null;\n const hasAriaLabel = findJsxAttribute(openingElement, \"ariaLabel\") !== null;\n if (hasTitle || hasAriaLabel) continue;\n\n edits.push({\n offset: openingElement.tagName.getEnd(),\n text: ` title=\"${PLACEHOLDER_TITLE}\"`,\n });\n }\n\n if (edits.length === 0) return null;\n\n edits.sort((a, b) => (a.offset === b.offset ? 0 : b.offset - a.offset));\n\n let updated = content;\n for (const { offset, text } of edits) {\n updated = updated.slice(0, offset) + text + updated.slice(offset);\n }\n return updated;\n};\n\n/**\n * Adds a placeholder `title` to `<IconButton>` usages that don't already\n * provide either `title` or `ariaLabel`. The new accessible name requirement\n * means every icon button must carry one of these two props.\n *\n * Usages with a spread attribute (e.g. `<IconButton {...props} />`) are\n * skipped because we cannot tell whether `title`/`ariaLabel` is forwarded.\n */\nexport const iconButtonAddRequiredName = (tree: Tree): void => {\n const touched = visitTsxFiles(tree, \"IconButton\", transformIconButtonUsage);\n logSummary(\"iconbutton-add-required-name\", touched);\n if (touched > 0) {\n logger.info(\n ` Replace the placeholder \"${PLACEHOLDER_TITLE}\" titles with localized strings (or switch to ariaLabel where appropriate).`\n );\n }\n};\n\nexport default iconButtonAddRequiredName;\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"kpi-tooltiplabel-to-wrapper.js","sourceRoot":"","sources":["../../../../../../libs/react/components/migrations/v2-0-0/kpi-tooltiplabel-to-wrapper.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Tree } from \"@nx/devkit\";\nimport * as ts from \"typescript\";\nimport {\n findJsxAttribute,\n findJsxElements,\n getImportedAliases,\n logSummary,\n parseTsx,\n visitTsxFiles,\n} from \"../utils/jsx-utils\";\n\nconst PACKAGE_NAME = \"@trackunit/react-components\";\nconst COMPONENT_NAME = \"KPI\";\n\nconst ensureTooltipImport = (content: string): string => {\n const sourceFile = parseTsx(content, \"source.tsx\");\n const aliases = getImportedAliases(sourceFile, PACKAGE_NAME);\n if (aliases !== null && Object.values(aliases).includes(\"Tooltip\")) return content;\n\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const moduleSpecifier = stmt.moduleSpecifier;\n if (!ts.isStringLiteral(moduleSpecifier) || moduleSpecifier.text !== PACKAGE_NAME) continue;\n\n const namedBindings = stmt.importClause?.namedBindings;\n if (namedBindings === undefined || !ts.isNamedImports(namedBindings)) continue;\n\n const elementsText = namedBindings.elements.map(el => el.getText()).join(\", \");\n const merged = `${elementsText}, Tooltip`;\n const before = content.slice(0, namedBindings.getStart());\n const after = content.slice(namedBindings.getEnd());\n return `${before}{ ${merged} }${after}`;\n }\n\n return `import { Tooltip } from \"${PACKAGE_NAME}\";\\n${content}`;\n};\n\nconst renderTooltipExpression = (label: string): string => label;\n\nconst transformKpiUsage = (filePath: string, content: string): string | null => {\n const sourceFile = parseTsx(content, filePath);\n\n const aliases = getImportedAliases(sourceFile, PACKAGE_NAME);\n if (aliases === null) return null;\n\n const localAlias = Object.entries(aliases).find(([, name]) => name === COMPONENT_NAME)?.[0];\n if (localAlias === undefined) return null;\n\n const matches = findJsxElements(sourceFile, [localAlias]);\n if (matches.length === 0) return null;\n\n type Edit = {\n elementStart: number;\n elementEnd: number;\n attrStart: number;\n attrEnd: number;\n label: string;\n elementText: string;\n };\n const edits: Array<Edit> = [];\n\n for (const { openingElement, element } of matches) {\n const tooltipLabelAttr = findJsxAttribute(openingElement, \"tooltipLabel\");\n if (tooltipLabelAttr === null) continue;\n\n const initializer = tooltipLabelAttr.initializer;\n if (initializer === undefined) continue;\n\n let label: string;\n if (ts.isStringLiteral(initializer)) {\n label = `\"${initializer.text}\"`;\n } else if (ts.isJsxExpression(initializer) && initializer.expression !== undefined) {\n label = `{${initializer.expression.getText()}}`;\n } else {\n continue;\n }\n\n edits.push({\n elementStart: element.getStart(),\n elementEnd: element.getEnd(),\n attrStart: tooltipLabelAttr.getFullStart(),\n attrEnd: tooltipLabelAttr.getEnd(),\n label,\n elementText: content.slice(element.getStart(), element.getEnd()),\n });\n }\n\n if (edits.length === 0) return null;\n\n edits.sort((a, b) => b.elementStart - a.elementStart);\n\n let updated = content;\n for (const edit of edits) {\n // Remove the tooltipLabel attribute first (it's inside the element).\n const elementWithoutAttr =\n edit.elementText.slice(0, edit.attrStart - edit.elementStart) +\n edit.elementText.slice(edit.attrEnd - edit.elementStart);\n const wrapped = `<Tooltip label=${renderTooltipExpression(edit.label)} placement=\"bottom\">${elementWithoutAttr}</Tooltip>`;\n updated = updated.slice(0, edit.elementStart) + wrapped + updated.slice(edit.elementEnd);\n }\n\n updated = ensureTooltipImport(updated);\n\n return updated;\n};\n\n/**\n * Replaces the removed `tooltipLabel` prop on `<KPI>` with an explicit\n * `<Tooltip>` wrapper. The `KPICard` variant is intentionally not touched\n * because it still owns its own `tooltipLabel` prop.\n */\nexport const kpiTooltipLabelToWrapper = (tree: Tree): void => {\n const touched = visitTsxFiles(tree, \"tooltipLabel\", transformKpiUsage);\n logSummary(\"kpi-tooltiplabel-to-wrapper\", touched);\n};\n\nexport default kpiTooltipLabelToWrapper;\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"notice-tooltiplabel-to-wrapper.js","sourceRoot":"","sources":["../../../../../../libs/react/components/migrations/v2-0-0/notice-tooltiplabel-to-wrapper.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Tree } from \"@nx/devkit\";\nimport * as ts from \"typescript\";\nimport {\n findJsxAttribute,\n findJsxElements,\n getImportedAliases,\n logSummary,\n parseTsx,\n visitTsxFiles,\n} from \"../utils/jsx-utils\";\n\nconst PACKAGE_NAME = \"@trackunit/react-components\";\nconst COMPONENT_NAME = \"Notice\";\n\nconst ensureTooltipImport = (content: string): string => {\n const sourceFile = parseTsx(content, \"source.tsx\");\n const aliases = getImportedAliases(sourceFile, PACKAGE_NAME);\n if (aliases !== null && Object.values(aliases).includes(\"Tooltip\")) return content;\n\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const moduleSpecifier = stmt.moduleSpecifier;\n if (!ts.isStringLiteral(moduleSpecifier) || moduleSpecifier.text !== PACKAGE_NAME) continue;\n\n const namedBindings = stmt.importClause?.namedBindings;\n if (namedBindings === undefined || !ts.isNamedImports(namedBindings)) continue;\n\n const elementsText = namedBindings.elements.map(el => el.getText()).join(\", \");\n const merged = `${elementsText}, Tooltip`;\n const before = content.slice(0, namedBindings.getStart());\n const after = content.slice(namedBindings.getEnd());\n return `${before}{ ${merged} }${after}`;\n }\n\n return `import { Tooltip } from \"${PACKAGE_NAME}\";\\n${content}`;\n};\n\nconst transformNoticeUsage = (filePath: string, content: string): string | null => {\n const sourceFile = parseTsx(content, filePath);\n\n const aliases = getImportedAliases(sourceFile, PACKAGE_NAME);\n if (aliases === null) return null;\n\n const localAlias = Object.entries(aliases).find(([, name]) => name === COMPONENT_NAME)?.[0];\n if (localAlias === undefined) return null;\n\n const matches = findJsxElements(sourceFile, [localAlias]);\n if (matches.length === 0) return null;\n\n type Edit = {\n elementStart: number;\n elementEnd: number;\n elementText: string;\n label: string | null;\n attrEdits: Array<{ start: number; end: number }>;\n };\n const edits: Array<Edit> = [];\n\n for (const { openingElement, element } of matches) {\n const tooltipLabelAttr = findJsxAttribute(openingElement, \"tooltipLabel\");\n const withTooltipAttr = findJsxAttribute(openingElement, \"withTooltip\");\n if (tooltipLabelAttr === null && withTooltipAttr === null) continue;\n\n let label: string | null = null;\n if (tooltipLabelAttr !== null) {\n const initializer = tooltipLabelAttr.initializer;\n if (initializer !== undefined) {\n if (ts.isStringLiteral(initializer)) {\n label = `\"${initializer.text}\"`;\n } else if (ts.isJsxExpression(initializer) && initializer.expression !== undefined) {\n label = `{${initializer.expression.getText()}}`;\n }\n }\n }\n\n const attrEdits: Array<{ start: number; end: number }> = [];\n for (const attr of [tooltipLabelAttr, withTooltipAttr]) {\n if (attr === null) continue;\n attrEdits.push({ start: attr.getFullStart(), end: attr.getEnd() });\n }\n\n edits.push({\n elementStart: element.getStart(),\n elementEnd: element.getEnd(),\n elementText: content.slice(element.getStart(), element.getEnd()),\n label,\n attrEdits,\n });\n }\n\n if (edits.length === 0) return null;\n\n edits.sort((a, b) => b.elementStart - a.elementStart);\n\n let updated = content;\n let needsTooltipImport = false;\n\n for (const edit of edits) {\n // Remove the tooltipLabel/withTooltip attributes from the element first.\n let elementWithoutAttrs = edit.elementText;\n const sortedAttrEdits = [...edit.attrEdits].sort((a, b) => b.start - a.start);\n for (const { start, end } of sortedAttrEdits) {\n elementWithoutAttrs =\n elementWithoutAttrs.slice(0, start - edit.elementStart) + elementWithoutAttrs.slice(end - edit.elementStart);\n }\n\n if (edit.label !== null) {\n const wrapped = `<Tooltip label=${edit.label} placement=\"bottom\">${elementWithoutAttrs}</Tooltip>`;\n updated = updated.slice(0, edit.elementStart) + wrapped + updated.slice(edit.elementEnd);\n needsTooltipImport = true;\n } else {\n // No label to forward (e.g. only `withTooltip`); just strip the props.\n updated = updated.slice(0, edit.elementStart) + elementWithoutAttrs + updated.slice(edit.elementEnd);\n }\n }\n\n if (needsTooltipImport) {\n updated = ensureTooltipImport(updated);\n }\n\n return updated;\n};\n\n/**\n * Removes the deprecated `withTooltip`/`tooltipLabel` props from `<Notice>`\n * usages. When a label is present the element is wrapped in `<Tooltip>` to\n * preserve hover behaviour; when only `withTooltip` was set the props are\n * dropped because they had no remaining effect.\n */\nexport const noticeTooltipLabelToWrapper = (tree: Tree): void => {\n const touched = visitTsxFiles(tree, \"Notice\", transformNoticeUsage);\n logSummary(\"notice-tooltiplabel-to-wrapper\", touched);\n};\n\nexport default noticeTooltipLabelToWrapper;\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pagination-add-required-titles.js","sourceRoot":"","sources":["../../../../../../libs/react/components/migrations/v2-0-0/pagination-add-required-titles.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Tree, logger } from \"@nx/devkit\";\nimport {\n findJsxAttribute,\n findJsxElements,\n getImportedAliases,\n hasSpreadAttribute,\n logSummary,\n parseTsx,\n visitTsxFiles,\n} from \"../utils/jsx-utils\";\n\nconst PACKAGE_NAME = \"@trackunit/react-components\";\nconst COMPONENT_NAME = \"Pagination\";\n\nconst PLACEHOLDERS: Record<string, string> = {\n previousPageTitle: \"Previous page\",\n nextPageTitle: \"Next page\",\n};\n\nconst transformPaginationUsage = (filePath: string, content: string): string | null => {\n const sourceFile = parseTsx(content, filePath);\n\n const aliases = getImportedAliases(sourceFile, PACKAGE_NAME);\n if (aliases === null) return null;\n\n const localAlias = Object.entries(aliases).find(([, name]) => name === COMPONENT_NAME)?.[0];\n if (localAlias === undefined) return null;\n\n const matches = findJsxElements(sourceFile, [localAlias]);\n if (matches.length === 0) return null;\n\n type Edit = { offset: number; text: string };\n const edits: Array<Edit> = [];\n\n for (const { openingElement } of matches) {\n if (hasSpreadAttribute(openingElement)) continue;\n\n for (const [propName, placeholder] of Object.entries(PLACEHOLDERS)) {\n if (findJsxAttribute(openingElement, propName) !== null) continue;\n edits.push({\n offset: openingElement.tagName.getEnd(),\n text: ` ${propName}=\"${placeholder}\"`,\n });\n }\n }\n\n if (edits.length === 0) return null;\n\n // Apply in reverse so earlier offsets stay valid; keep order at the same\n // offset so attributes appear in declaration order in the source.\n edits.sort((a, b) => (a.offset === b.offset ? 0 : b.offset - a.offset));\n\n let updated = content;\n for (const { offset, text } of edits) {\n updated = updated.slice(0, offset) + text + updated.slice(offset);\n }\n return updated;\n};\n\n/**\n * Adds the now-required `previousPageTitle` and `nextPageTitle` props to\n * `<Pagination>` usages that don't already provide them. The values default\n * to the English strings \"Previous page\"/\"Next page\"; consumers should\n * replace them with their own localized strings.\n *\n * Usages with a spread attribute (e.g. `<Pagination {...props} />`) are\n * skipped because we cannot tell whether the props are already provided.\n */\nexport const paginationAddRequiredTitles = (tree: Tree): void => {\n const touched = visitTsxFiles(tree, \"Pagination\", transformPaginationUsage);\n logSummary(\"pagination-add-required-titles\", touched);\n if (touched > 0) {\n logger.info(` Replace the placeholder \"Previous page\"/\"Next page\" strings with your own localized values.`);\n }\n};\n\nexport default paginationAddRequiredTitles;\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tag-add-removetaglabel.js","sourceRoot":"","sources":["../../../../../../libs/react/components/migrations/v2-0-0/tag-add-removetaglabel.ts"],"names":[],"mappings":";;;AAAA,uCAA+C;AAC/C,kDAQ4B;AAE5B,MAAM,YAAY,GAAG,6BAA6B,CAAC;AACnD,MAAM,cAAc,GAAG,KAAK,CAAC;AAE7B,MAAM,4BAA4B,GAAG,YAAY,CAAC;AAElD,MAAM,iBAAiB,GAAG,CAAC,QAAgB,EAAE,OAAe,EAAiB,EAAE;IAC7E,MAAM,UAAU,GAAG,IAAA,oBAAQ,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAE/C,MAAM,OAAO,GAAG,IAAA,8BAAkB,EAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAC7D,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAElC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5F,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAE1C,MAAM,OAAO,GAAG,IAAA,2BAAe,EAAC,UAAU,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAC1D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAGtC,MAAM,KAAK,GAAgB,EAAE,CAAC;IAE9B,KAAK,MAAM,EAAE,cAAc,EAAE,IAAI,OAAO,EAAE,CAAC;QACzC,IAAI,IAAA,8BAAkB,EAAC,cAAc,CAAC;YAAE,SAAS;QAEjD,0EAA0E;QAC1E,wBAAwB;QACxB,IAAI,IAAA,4BAAgB,EAAC,cAAc,EAAE,cAAc,CAAC,KAAK,IAAI;YAAE,SAAS;QACxE,IAAI,IAAA,4BAAgB,EAAC,cAAc,EAAE,gBAAgB,CAAC,KAAK,IAAI;YAAE,SAAS;QAE1E,KAAK,CAAC,IAAI,CAAC;YACT,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE;YACvC,IAAI,EAAE,oBAAoB,4BAA4B,GAAG;SAC1D,CAAC,CAAC;IACL,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAExE,IAAI,OAAO,GAAG,OAAO,CAAC;IACtB,KAAK,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,KAAK,EAAE,CAAC;QACrC,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF;;;;;GAKG;AACI,MAAM,oBAAoB,GAAG,CAAC,IAAU,EAAQ,EAAE;IACvD,MAAM,OAAO,GAAG,IAAA,yBAAa,EAAC,IAAI,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC;IAC9D,IAAA,sBAAU,EAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;IAC9C,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,eAAM,CAAC,IAAI,CAAC,8EAA8E,CAAC,CAAC;IAC9F,CAAC;AACH,CAAC,CAAC;AANW,QAAA,oBAAoB,wBAM/B;AAEF,kBAAe,4BAAoB,CAAC","sourcesContent":["import { type Tree, logger } from \"@nx/devkit\";\nimport {\n findJsxAttribute,\n findJsxElements,\n getImportedAliases,\n hasSpreadAttribute,\n logSummary,\n parseTsx,\n visitTsxFiles,\n} from \"../utils/jsx-utils\";\n\nconst PACKAGE_NAME = \"@trackunit/react-components\";\nconst COMPONENT_NAME = \"Tag\";\n\nconst REMOVE_TAG_LABEL_PLACEHOLDER = \"Remove tag\";\n\nconst transformTagUsage = (filePath: string, content: string): string | null => {\n const sourceFile = parseTsx(content, filePath);\n\n const aliases = getImportedAliases(sourceFile, PACKAGE_NAME);\n if (aliases === null) return null;\n\n const localAlias = Object.entries(aliases).find(([, name]) => name === COMPONENT_NAME)?.[0];\n if (localAlias === undefined) return null;\n\n const matches = findJsxElements(sourceFile, [localAlias]);\n if (matches.length === 0) return null;\n\n type Edit = { offset: number; text: string };\n const edits: Array<Edit> = [];\n\n for (const { openingElement } of matches) {\n if (hasSpreadAttribute(openingElement)) continue;\n\n // Only act when the tag is dismissible (has onClickClose) and missing the\n // newly required label.\n if (findJsxAttribute(openingElement, \"onClickClose\") === null) continue;\n if (findJsxAttribute(openingElement, \"removeTagLabel\") !== null) continue;\n\n edits.push({\n offset: openingElement.tagName.getEnd(),\n text: ` removeTagLabel=\"${REMOVE_TAG_LABEL_PLACEHOLDER}\"`,\n });\n }\n\n if (edits.length === 0) return null;\n\n edits.sort((a, b) => (a.offset === b.offset ? 0 : b.offset - a.offset));\n\n let updated = content;\n for (const { offset, text } of edits) {\n updated = updated.slice(0, offset) + text + updated.slice(offset);\n }\n return updated;\n};\n\n/**\n * Adds the now-required `removeTagLabel` prop to dismissible `<Tag>` usages\n * (those with `onClickClose`) when it is missing. Default value is the English\n * string \"Remove tag\"; consumers should replace it with their own localized\n * label.\n */\nexport const tagAddRemoveTagLabel = (tree: Tree): void => {\n const touched = visitTsxFiles(tree, \"Tag\", transformTagUsage);\n logSummary(\"tag-add-removetaglabel\", touched);\n if (touched > 0) {\n logger.info(` Replace the placeholder \"Remove tag\" string with your own localized value.`);\n }\n};\n\nexport default tagAddRemoveTagLabel;\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"togglegroup-remove-item-style.js","sourceRoot":"","sources":["../../../../../../libs/react/components/migrations/v2-0-0/togglegroup-remove-item-style.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Tree, logger } from \"@nx/devkit\";\nimport * as ts from \"typescript\";\nimport {\n findJsxAttribute,\n findJsxElements,\n getImportedAliases,\n logSummary,\n parseTsx,\n visitTsxFiles,\n} from \"../utils/jsx-utils\";\n\nconst PACKAGE_NAME = \"@trackunit/react-components\";\nconst COMPONENT_NAME = \"ToggleGroup\";\n\ntype Removal = { start: number; end: number };\n\nconst collectStyleRemovalsFromArray = (arrayLiteral: ts.ArrayLiteralExpression): ReadonlyArray<Removal> => {\n const removals: Array<Removal> = [];\n for (const element of arrayLiteral.elements) {\n if (!ts.isObjectLiteralExpression(element)) continue;\n for (const prop of element.properties) {\n if (\n (ts.isPropertyAssignment(prop) || ts.isShorthandPropertyAssignment(prop)) &&\n ts.isIdentifier(prop.name) &&\n prop.name.text === \"style\"\n ) {\n removals.push({ start: prop.getFullStart(), end: prop.getEnd() });\n }\n }\n }\n return removals;\n};\n\nconst transformToggleGroupUsage = (\n filePath: string,\n content: string\n): { content: string | null; skippedNonInline: number } => {\n const sourceFile = parseTsx(content, filePath);\n\n const aliases = getImportedAliases(sourceFile, PACKAGE_NAME);\n if (aliases === null) return { content: null, skippedNonInline: 0 };\n\n const localAlias = Object.entries(aliases).find(([, name]) => name === COMPONENT_NAME)?.[0];\n if (localAlias === undefined) return { content: null, skippedNonInline: 0 };\n\n const matches = findJsxElements(sourceFile, [localAlias]);\n if (matches.length === 0) return { content: null, skippedNonInline: 0 };\n\n const removals: Array<Removal> = [];\n let skippedNonInline = 0;\n\n for (const { openingElement } of matches) {\n const listAttr = findJsxAttribute(openingElement, \"list\");\n if (listAttr === null) continue;\n\n const initializer = listAttr.initializer;\n if (initializer === undefined || !ts.isJsxExpression(initializer)) continue;\n const expr = initializer.expression;\n if (expr === undefined) continue;\n\n if (!ts.isArrayLiteralExpression(expr)) {\n // The list is referenced through a variable / function call; we can't\n // safely strip `style` without potentially editing unrelated objects.\n skippedNonInline += 1;\n continue;\n }\n\n removals.push(...collectStyleRemovalsFromArray(expr));\n }\n\n if (removals.length === 0) return { content: null, skippedNonInline };\n\n // Remove the property and its trailing comma if present so we don't leave\n // dangling `, ,` sequences.\n const sorted = [...removals].sort((a, b) => b.start - a.start);\n let updated = content;\n for (let { start, end } of sorted) {\n while (start > 0 && (updated[start - 1] === \" \" || updated[start - 1] === \"\\t\")) {\n start -= 1;\n }\n if (updated[end] === \",\") {\n end += 1;\n }\n updated = updated.slice(0, start) + updated.slice(end);\n }\n\n return { content: updated, skippedNonInline };\n};\n\n/**\n * Removes the `style` property from items in `<ToggleGroup list={[...]}>`\n * because `BasicToggleGroupListProps` no longer extends `Styleable`.\n *\n * Only inline array literals are processed; lists pulled in via a variable or\n * function call are left untouched and reported in the migration summary so\n * the developer can review them.\n */\nexport const toggleGroupRemoveItemStyle = (tree: Tree): void => {\n let touched = 0;\n let totalSkipped = 0;\n visitTsxFiles(tree, COMPONENT_NAME, (filePath, content) => {\n const { content: updated, skippedNonInline } = transformToggleGroupUsage(filePath, content);\n totalSkipped += skippedNonInline;\n if (updated !== null && updated !== content) {\n touched += 1;\n return updated;\n }\n return null;\n });\n logSummary(\"togglegroup-remove-item-style\", touched, totalSkipped);\n if (totalSkipped > 0) {\n logger.info(\n ` ${totalSkipped} ToggleGroup usage(s) referenced their list through a variable/function. Remove any 'style' properties from those item objects manually.`\n );\n }\n};\n\nexport default toggleGroupRemoveItemStyle;\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"menulist-rename-to-menucontent.js","sourceRoot":"","sources":["../../../../../../libs/react/components/migrations/v3-0-0/menulist-rename-to-menucontent.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Tree } from \"@nx/devkit\";\nimport * as ts from \"typescript\";\nimport { getImportedAliases, logSummary, parseTsx, visitTsxFiles } from \"../utils/jsx-utils\";\n\nconst PACKAGE_NAME = \"@trackunit/react-components\";\n\nconst RENAMES: ReadonlyArray<{ readonly from: string; readonly to: string }> = [\n { from: \"MenuList\", to: \"MenuContent\" },\n { from: \"MenuListProps\", to: \"MenuContentProps\" },\n];\n\ntype Edit = { start: number; end: number; text: string };\n\n/**\n * Every `Identifier` node in the file matching `name`. Safe to use as a\n * blanket rename once we've confirmed (via `getImportedAliases`) that `name`\n * is genuinely imported from the target package with no local alias — in\n * that case the import specifier, JSX tag references, and type references\n * all share the same identifier text, so one pass covers every site.\n */\nconst collectIdentifierEdits = (sourceFile: ts.SourceFile, name: string, replacement: string): Array<Edit> => {\n const edits: Array<Edit> = [];\n const visit = (node: ts.Node): void => {\n if (ts.isIdentifier(node) && node.text === name) {\n edits.push({ start: node.getStart(sourceFile), end: node.getEnd(), text: replacement });\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n return edits;\n};\n\n/**\n * Locates the `propertyName` of an aliased named import specifier\n * (`{ MenuList as Foo }`) for `importedName`. Only that part needs\n * rewriting — the local binding `Foo` (and therefore every usage site in\n * the file) stays exactly as the author wrote it.\n */\nconst findAliasedImportSpecifierEdit = (\n sourceFile: ts.SourceFile,\n packageName: string,\n importedName: string,\n replacement: string\n): Edit | null => {\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const moduleSpecifier = stmt.moduleSpecifier;\n if (!ts.isStringLiteral(moduleSpecifier) || moduleSpecifier.text !== packageName) continue;\n\n const namedBindings = stmt.importClause?.namedBindings;\n if (namedBindings === undefined || !ts.isNamedImports(namedBindings)) continue;\n\n for (const element of namedBindings.elements) {\n if (element.propertyName === undefined) continue;\n if (element.propertyName.text !== importedName) continue;\n return {\n start: element.propertyName.getStart(sourceFile),\n end: element.propertyName.getEnd(),\n text: replacement,\n };\n }\n }\n return null;\n};\n\nconst transformMenuListUsage = (filePath: string, content: string): string | null => {\n const sourceFile = parseTsx(content, filePath);\n\n const aliases = getImportedAliases(sourceFile, PACKAGE_NAME);\n if (aliases === null) return null;\n\n const edits: Array<Edit> = [];\n\n for (const { from, to } of RENAMES) {\n const localAlias = Object.entries(aliases).find(([, original]) => original === from)?.[0];\n if (localAlias === undefined) continue;\n\n if (localAlias === from) {\n edits.push(...collectIdentifierEdits(sourceFile, from, to));\n } else {\n const edit = findAliasedImportSpecifierEdit(sourceFile, PACKAGE_NAME, from, to);\n if (edit !== null) edits.push(edit);\n }\n }\n\n if (edits.length === 0) return null;\n\n edits.sort((a, b) => b.start - a.start);\n\n let updated = content;\n for (const { start, end, text } of edits) {\n updated = updated.slice(0, start) + text + updated.slice(end);\n }\n return updated;\n};\n\n/**\n * Renames `MenuList`/`MenuListProps` to `MenuContent`/`MenuContentProps`\n * everywhere they're imported from `@trackunit/react-components` — the\n * import specifier, every JSX tag usage, and every type reference (e.g.\n * `Omit<MenuListProps, \"children\">`).\n *\n * Aliased imports (`{ MenuList as Foo }`) only need the imported name\n * rewritten; the local alias and its usage sites are left untouched.\n * Unrelated same-prefix exports like `cvaMenuList`/`cvaMenuListItem` are\n * never matched since identifier comparisons are exact, not substring.\n */\nexport const menuListRenameToMenuContent = (tree: Tree): void => {\n const touched = visitTsxFiles(tree, \"MenuList\", transformMenuListUsage);\n logSummary(\"menulist-rename-to-menucontent\", touched);\n};\n\nexport default menuListRenameToMenuContent;\n"]}
|