@tinybigui/react 0.21.1 → 0.22.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.
- package/README.md +9 -9
- package/dist/index.cjs +202 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +113 -17
- package/dist/index.d.ts +113 -17
- package/dist/index.js +202 -68
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ A modern, accessible React component library implementing Google's Material Desi
|
|
|
12
12
|
|
|
13
13
|
## ✅ Status
|
|
14
14
|
|
|
15
|
-
> **Latest Release: v0.
|
|
15
|
+
> **Latest Release: v0.22.0** (2026-06-10)
|
|
16
16
|
>
|
|
17
17
|
> **29 MD3 components** published to npm with full TypeScript support and WCAG 2.1 AA accessibility.
|
|
18
18
|
>
|
|
@@ -159,14 +159,14 @@ See [THEMING.md](./THEMING.md) for the full customization guide.
|
|
|
159
159
|
|
|
160
160
|
### Phase 3: Feedback ✅
|
|
161
161
|
|
|
162
|
-
| Component | Status | Description
|
|
163
|
-
| ------------- | ------ |
|
|
164
|
-
| `Dialog` | ✅ |
|
|
165
|
-
| `Snackbar` | ✅ | MD3 slot-based architecture, inverse-surface state layers, spring motion (v0.20.0)
|
|
166
|
-
| `Menu` | ✅ | Dropdown, context menu, submenus
|
|
167
|
-
| `Progress` | ✅ | MD3 expressive slot CVA, colorful tokens, wavy shape, thick track (v0.16.0)
|
|
168
|
-
| `BottomSheet` | ✅ | MD3 expressive handle, variants-vs-states architecture (v0.11.0)
|
|
169
|
-
| `Tooltip` | ✅ | Slot-based MD3 styling, reduced-motion guard, rich tooltip token fixes (v0.21.1)
|
|
162
|
+
| Component | Status | Description |
|
|
163
|
+
| ------------- | ------ | ----------------------------------------------------------------------------------- |
|
|
164
|
+
| `Dialog` | ✅ | MD3 expressive motion, hero icon, scroll dividers, reduced-motion support (v0.22.0) |
|
|
165
|
+
| `Snackbar` | ✅ | MD3 slot-based architecture, inverse-surface state layers, spring motion (v0.20.0) |
|
|
166
|
+
| `Menu` | ✅ | Dropdown, context menu, submenus |
|
|
167
|
+
| `Progress` | ✅ | MD3 expressive slot CVA, colorful tokens, wavy shape, thick track (v0.16.0) |
|
|
168
|
+
| `BottomSheet` | ✅ | MD3 expressive handle, variants-vs-states architecture (v0.11.0) |
|
|
169
|
+
| `Tooltip` | ✅ | Slot-based MD3 styling, reduced-motion guard, rich tooltip token fixes (v0.21.1) |
|
|
170
170
|
|
|
171
171
|
### Phase 4: Data Display ✅
|
|
172
172
|
|
package/dist/index.cjs
CHANGED
|
@@ -7721,13 +7721,14 @@ var DialogPanel = ({
|
|
|
7721
7721
|
headlineId,
|
|
7722
7722
|
contentId,
|
|
7723
7723
|
onClose,
|
|
7724
|
-
|
|
7724
|
+
onAnimationEnd,
|
|
7725
7725
|
variant,
|
|
7726
7726
|
isDismissable,
|
|
7727
7727
|
wrapperClassName,
|
|
7728
7728
|
className,
|
|
7729
7729
|
animationState,
|
|
7730
7730
|
getAnimationClassName,
|
|
7731
|
+
icon,
|
|
7731
7732
|
children
|
|
7732
7733
|
}) => {
|
|
7733
7734
|
const panelRef = React.useRef(null);
|
|
@@ -7750,9 +7751,10 @@ var DialogPanel = ({
|
|
|
7750
7751
|
panelRef
|
|
7751
7752
|
);
|
|
7752
7753
|
const panelClassName = cn(className, getAnimationClassName?.(animationState));
|
|
7754
|
+
const hasIcon = icon !== void 0 && icon !== null && variant === "basic";
|
|
7753
7755
|
return (
|
|
7754
7756
|
// Centering/positioning wrapper — structural only, no ARIA role
|
|
7755
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: wrapperClassName, children: /* @__PURE__ */ jsxRuntime.
|
|
7757
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: wrapperClassName, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7756
7758
|
"div",
|
|
7757
7759
|
{
|
|
7758
7760
|
...utils.mergeProps(overlayProps, dialogProps),
|
|
@@ -7761,8 +7763,12 @@ var DialogPanel = ({
|
|
|
7761
7763
|
className: panelClassName,
|
|
7762
7764
|
"data-animation-state": animationState,
|
|
7763
7765
|
"data-variant": variant,
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
+
"data-with-icon": hasIcon ? "" : void 0,
|
|
7767
|
+
onAnimationEnd,
|
|
7768
|
+
children: [
|
|
7769
|
+
hasIcon && icon,
|
|
7770
|
+
children
|
|
7771
|
+
]
|
|
7766
7772
|
}
|
|
7767
7773
|
) })
|
|
7768
7774
|
);
|
|
@@ -7775,9 +7781,11 @@ var DialogHeadless = React.forwardRef(
|
|
|
7775
7781
|
defaultOpen = false,
|
|
7776
7782
|
onOpenChange,
|
|
7777
7783
|
"aria-label": ariaLabel,
|
|
7784
|
+
icon,
|
|
7778
7785
|
children,
|
|
7779
7786
|
className,
|
|
7780
|
-
|
|
7787
|
+
wrapperClassName,
|
|
7788
|
+
getScrimClassName,
|
|
7781
7789
|
getAnimationClassName
|
|
7782
7790
|
}, _ref) {
|
|
7783
7791
|
const state = reactStately.useOverlayTriggerState({
|
|
@@ -7811,7 +7819,7 @@ var DialogHeadless = React.forwardRef(
|
|
|
7811
7819
|
closedRef.current = true;
|
|
7812
7820
|
setAnimationState("exited");
|
|
7813
7821
|
}
|
|
7814
|
-
},
|
|
7822
|
+
}, 250);
|
|
7815
7823
|
}
|
|
7816
7824
|
}, [isOpen, animationState]);
|
|
7817
7825
|
React.useEffect(
|
|
@@ -7822,16 +7830,20 @@ var DialogHeadless = React.forwardRef(
|
|
|
7822
7830
|
},
|
|
7823
7831
|
[]
|
|
7824
7832
|
);
|
|
7825
|
-
const
|
|
7826
|
-
|
|
7827
|
-
if (
|
|
7828
|
-
|
|
7829
|
-
exitFallbackRef.current
|
|
7833
|
+
const handleAnimationEnd = React.useCallback(
|
|
7834
|
+
(e) => {
|
|
7835
|
+
if (e.target !== e.currentTarget) return;
|
|
7836
|
+
if (animationState === "exiting" && !closedRef.current) {
|
|
7837
|
+
if (exitFallbackRef.current !== null) {
|
|
7838
|
+
clearTimeout(exitFallbackRef.current);
|
|
7839
|
+
exitFallbackRef.current = null;
|
|
7840
|
+
}
|
|
7841
|
+
closedRef.current = true;
|
|
7842
|
+
setAnimationState("exited");
|
|
7830
7843
|
}
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
|
|
7834
|
-
}, [animationState]);
|
|
7844
|
+
},
|
|
7845
|
+
[animationState]
|
|
7846
|
+
);
|
|
7835
7847
|
const baseId = React.useId();
|
|
7836
7848
|
const headlineId = `${baseId}-dialog-headline`;
|
|
7837
7849
|
const contentId = `${baseId}-dialog-content`;
|
|
@@ -7846,6 +7858,8 @@ var DialogHeadless = React.forwardRef(
|
|
|
7846
7858
|
close();
|
|
7847
7859
|
}
|
|
7848
7860
|
}, [variant, close]);
|
|
7861
|
+
const resolvedWrapperClass = wrapperClassName ?? (variant === "basic" ? "fixed inset-0 z-50 flex items-center justify-center px-4" : "fixed inset-0 z-50");
|
|
7862
|
+
const resolvedScrimClass = getScrimClassName?.(animationState) ?? "fixed inset-0 z-40 bg-scrim/32";
|
|
7849
7863
|
if (!isOpen && animationState === "exited") {
|
|
7850
7864
|
return null;
|
|
7851
7865
|
}
|
|
@@ -7854,7 +7868,7 @@ var DialogHeadless = React.forwardRef(
|
|
|
7854
7868
|
"div",
|
|
7855
7869
|
{
|
|
7856
7870
|
"data-testid": "dialog-scrim",
|
|
7857
|
-
className:
|
|
7871
|
+
className: resolvedScrimClass,
|
|
7858
7872
|
onClick: handleScrimClick,
|
|
7859
7873
|
"aria-hidden": "true"
|
|
7860
7874
|
}
|
|
@@ -7866,13 +7880,14 @@ var DialogHeadless = React.forwardRef(
|
|
|
7866
7880
|
headlineId,
|
|
7867
7881
|
contentId,
|
|
7868
7882
|
onClose: close,
|
|
7869
|
-
|
|
7883
|
+
onAnimationEnd: handleAnimationEnd,
|
|
7870
7884
|
variant,
|
|
7871
7885
|
isDismissable: variant === "basic",
|
|
7872
|
-
wrapperClassName:
|
|
7886
|
+
wrapperClassName: resolvedWrapperClass,
|
|
7873
7887
|
className,
|
|
7874
7888
|
animationState,
|
|
7875
7889
|
getAnimationClassName,
|
|
7890
|
+
icon,
|
|
7876
7891
|
children
|
|
7877
7892
|
}
|
|
7878
7893
|
) })
|
|
@@ -7882,16 +7897,28 @@ var DialogHeadless = React.forwardRef(
|
|
|
7882
7897
|
}
|
|
7883
7898
|
);
|
|
7884
7899
|
DialogHeadless.displayName = "DialogHeadless";
|
|
7885
|
-
var dialogScrimVariants = classVarianceAuthority.cva(
|
|
7886
|
-
|
|
7887
|
-
|
|
7888
|
-
|
|
7889
|
-
|
|
7890
|
-
|
|
7891
|
-
|
|
7892
|
-
|
|
7893
|
-
|
|
7894
|
-
|
|
7900
|
+
var dialogScrimVariants = classVarianceAuthority.cva(
|
|
7901
|
+
[
|
|
7902
|
+
"fixed",
|
|
7903
|
+
"inset-0",
|
|
7904
|
+
"z-40",
|
|
7905
|
+
// MD3 scrim: bg-scrim at 32% opacity — always set so instant-show works in reduced-motion
|
|
7906
|
+
"bg-scrim/32"
|
|
7907
|
+
],
|
|
7908
|
+
{
|
|
7909
|
+
variants: {
|
|
7910
|
+
animationState: {
|
|
7911
|
+
entering: ["opacity-0"],
|
|
7912
|
+
visible: ["animate-md-fade-in"],
|
|
7913
|
+
exiting: ["animate-md-fade-out"],
|
|
7914
|
+
exited: ["opacity-0", "pointer-events-none"]
|
|
7915
|
+
}
|
|
7916
|
+
},
|
|
7917
|
+
defaultVariants: {
|
|
7918
|
+
animationState: "entering"
|
|
7919
|
+
}
|
|
7920
|
+
}
|
|
7921
|
+
);
|
|
7895
7922
|
var dialogPanelVariants = classVarianceAuthority.cva(
|
|
7896
7923
|
[
|
|
7897
7924
|
// Stacking above scrim
|
|
@@ -7901,9 +7928,10 @@ var dialogPanelVariants = classVarianceAuthority.cva(
|
|
|
7901
7928
|
// Flex column layout for slots
|
|
7902
7929
|
"flex",
|
|
7903
7930
|
"flex-col",
|
|
7904
|
-
//
|
|
7905
|
-
"
|
|
7906
|
-
|
|
7931
|
+
// Compositor hint for keyframe animation
|
|
7932
|
+
"will-change-[opacity,transform]",
|
|
7933
|
+
// group scope — lets child slots consume data-with-icon via group-data-[with-icon]/dialog:
|
|
7934
|
+
"group/dialog"
|
|
7907
7935
|
],
|
|
7908
7936
|
{
|
|
7909
7937
|
variants: {
|
|
@@ -7917,11 +7945,11 @@ var dialogPanelVariants = classVarianceAuthority.cva(
|
|
|
7917
7945
|
"min-w-70",
|
|
7918
7946
|
"max-w-dialog-max",
|
|
7919
7947
|
"w-full",
|
|
7920
|
-
// Internal spacing
|
|
7948
|
+
// Internal spacing: 24dp padding, headline mb-4, content mb-6, actions pt-3
|
|
7921
7949
|
"pt-6",
|
|
7922
7950
|
"pb-3",
|
|
7923
7951
|
"px-6",
|
|
7924
|
-
//
|
|
7952
|
+
// Positioning (centering wrapper handles the viewport centering)
|
|
7925
7953
|
"relative"
|
|
7926
7954
|
],
|
|
7927
7955
|
fullscreen: [
|
|
@@ -7932,7 +7960,6 @@ var dialogPanelVariants = classVarianceAuthority.cva(
|
|
|
7932
7960
|
"rounded-none",
|
|
7933
7961
|
// No elevation shadow on fullscreen
|
|
7934
7962
|
"shadow-none",
|
|
7935
|
-
// Positioned to fill portal
|
|
7936
7963
|
"relative"
|
|
7937
7964
|
]
|
|
7938
7965
|
}
|
|
@@ -7942,7 +7969,7 @@ var dialogPanelVariants = classVarianceAuthority.cva(
|
|
|
7942
7969
|
}
|
|
7943
7970
|
}
|
|
7944
7971
|
);
|
|
7945
|
-
classVarianceAuthority.cva([], {
|
|
7972
|
+
var dialogWrapperVariants = classVarianceAuthority.cva([], {
|
|
7946
7973
|
variants: {
|
|
7947
7974
|
variant: {
|
|
7948
7975
|
basic: ["fixed", "inset-0", "z-50", "flex", "items-center", "justify-center", "px-4"],
|
|
@@ -7956,9 +7983,13 @@ classVarianceAuthority.cva([], {
|
|
|
7956
7983
|
var dialogAnimationVariants = classVarianceAuthority.cva("", {
|
|
7957
7984
|
variants: {
|
|
7958
7985
|
animationState: {
|
|
7986
|
+
// initial mount frame before the animation starts — rendered invisible
|
|
7959
7987
|
entering: [],
|
|
7988
|
+
// entry animation active
|
|
7960
7989
|
visible: [],
|
|
7990
|
+
// exit animation active
|
|
7961
7991
|
exiting: [],
|
|
7992
|
+
// fully dismissed; portal gate will remove the element
|
|
7962
7993
|
exited: []
|
|
7963
7994
|
},
|
|
7964
7995
|
variant: {
|
|
@@ -7967,53 +7998,55 @@ var dialogAnimationVariants = classVarianceAuthority.cva("", {
|
|
|
7967
7998
|
}
|
|
7968
7999
|
},
|
|
7969
8000
|
compoundVariants: [
|
|
7970
|
-
// Basic
|
|
8001
|
+
// ── Basic ────────────────────────────────────────────────────────────────
|
|
8002
|
+
// entering: start invisible (animate-md-scale-in keyframe starts from scale(0.85)/opacity:0)
|
|
7971
8003
|
{
|
|
7972
8004
|
animationState: "entering",
|
|
7973
8005
|
variant: "basic",
|
|
7974
|
-
className: ["
|
|
8006
|
+
className: ["opacity-0"]
|
|
7975
8007
|
},
|
|
7976
|
-
//
|
|
8008
|
+
// visible: composite scale-in keyframe (expressive-fast-spatial 350ms)
|
|
7977
8009
|
{
|
|
7978
8010
|
animationState: "visible",
|
|
7979
8011
|
variant: "basic",
|
|
7980
|
-
className: ["
|
|
8012
|
+
className: ["animate-md-scale-in"]
|
|
7981
8013
|
},
|
|
7982
|
-
//
|
|
8014
|
+
// exiting: composite scale-out keyframe (emphasized-accelerate 200ms)
|
|
7983
8015
|
{
|
|
7984
8016
|
animationState: "exiting",
|
|
7985
8017
|
variant: "basic",
|
|
7986
|
-
className: ["
|
|
8018
|
+
className: ["animate-md-scale-out"]
|
|
7987
8019
|
},
|
|
7988
|
-
//
|
|
8020
|
+
// exited: keep hidden until portal gate removes it
|
|
7989
8021
|
{
|
|
7990
8022
|
animationState: "exited",
|
|
7991
8023
|
variant: "basic",
|
|
7992
|
-
className: ["
|
|
8024
|
+
className: ["opacity-0", "pointer-events-none"]
|
|
7993
8025
|
},
|
|
7994
|
-
// Fullscreen
|
|
8026
|
+
// ── Fullscreen ───────────────────────────────────────────────────────────
|
|
8027
|
+
// entering: start off-screen below (slide-in-bottom starts from translateY(100%)/opacity:0)
|
|
7995
8028
|
{
|
|
7996
8029
|
animationState: "entering",
|
|
7997
8030
|
variant: "fullscreen",
|
|
7998
|
-
className: ["
|
|
8031
|
+
className: ["opacity-0"]
|
|
7999
8032
|
},
|
|
8000
|
-
//
|
|
8033
|
+
// visible: composite slide-in-bottom keyframe (standard-default-spatial 500ms)
|
|
8001
8034
|
{
|
|
8002
8035
|
animationState: "visible",
|
|
8003
8036
|
variant: "fullscreen",
|
|
8004
|
-
className: ["
|
|
8037
|
+
className: ["animate-md-slide-in-bottom"]
|
|
8005
8038
|
},
|
|
8006
|
-
//
|
|
8039
|
+
// exiting: composite slide-out-bottom keyframe (emphasized-accelerate 200ms)
|
|
8007
8040
|
{
|
|
8008
8041
|
animationState: "exiting",
|
|
8009
8042
|
variant: "fullscreen",
|
|
8010
|
-
className: ["
|
|
8043
|
+
className: ["animate-md-slide-out-bottom"]
|
|
8011
8044
|
},
|
|
8012
|
-
//
|
|
8045
|
+
// exited: keep hidden until portal gate removes it
|
|
8013
8046
|
{
|
|
8014
8047
|
animationState: "exited",
|
|
8015
8048
|
variant: "fullscreen",
|
|
8016
|
-
className: ["
|
|
8049
|
+
className: ["opacity-0", "pointer-events-none"]
|
|
8017
8050
|
}
|
|
8018
8051
|
],
|
|
8019
8052
|
defaultVariants: {
|
|
@@ -8021,10 +8054,26 @@ var dialogAnimationVariants = classVarianceAuthority.cva("", {
|
|
|
8021
8054
|
variant: "basic"
|
|
8022
8055
|
}
|
|
8023
8056
|
});
|
|
8057
|
+
classVarianceAuthority.cva([
|
|
8058
|
+
// Center the icon in the panel
|
|
8059
|
+
"flex",
|
|
8060
|
+
"items-center",
|
|
8061
|
+
"justify-center",
|
|
8062
|
+
// Bottom margin separating icon from headline
|
|
8063
|
+
"mb-4",
|
|
8064
|
+
// MD3 spec: icon color = secondary
|
|
8065
|
+
"text-secondary",
|
|
8066
|
+
// 24dp icon size (children — typically an SVG — should be 24×24)
|
|
8067
|
+
"size-6"
|
|
8068
|
+
]);
|
|
8024
8069
|
var dialogHeadlineVariants = classVarianceAuthority.cva(["text-headline-small", "text-on-surface"], {
|
|
8025
8070
|
variants: {
|
|
8026
8071
|
variant: {
|
|
8027
|
-
basic: [
|
|
8072
|
+
basic: [
|
|
8073
|
+
"mb-4",
|
|
8074
|
+
// Center headline text when hero icon is present
|
|
8075
|
+
"group-data-[with-icon]/dialog:text-center"
|
|
8076
|
+
],
|
|
8028
8077
|
fullscreen: [
|
|
8029
8078
|
// Top app bar row in fullscreen: flex, items-center, gap
|
|
8030
8079
|
"flex",
|
|
@@ -8049,7 +8098,19 @@ var dialogHeadlineTitleVariants = classVarianceAuthority.cva([
|
|
|
8049
8098
|
"truncate"
|
|
8050
8099
|
]);
|
|
8051
8100
|
var dialogContentVariants = classVarianceAuthority.cva(
|
|
8052
|
-
[
|
|
8101
|
+
[
|
|
8102
|
+
"text-body-medium",
|
|
8103
|
+
"text-on-surface-variant",
|
|
8104
|
+
"overflow-y-auto",
|
|
8105
|
+
"flex-1",
|
|
8106
|
+
// Center supporting text when hero icon is present
|
|
8107
|
+
"group-data-[with-icon]/dialog:text-center",
|
|
8108
|
+
// Scroll dividers — activated by DialogContent's scroll handler
|
|
8109
|
+
"data-[scroll-divider-top]:border-t",
|
|
8110
|
+
"data-[scroll-divider-top]:border-outline-variant",
|
|
8111
|
+
"data-[scroll-divider-bottom]:border-b",
|
|
8112
|
+
"data-[scroll-divider-bottom]:border-outline-variant"
|
|
8113
|
+
],
|
|
8053
8114
|
{
|
|
8054
8115
|
variants: {
|
|
8055
8116
|
variant: {
|
|
@@ -8076,11 +8137,31 @@ var Dialog = React.forwardRef(function Dialog2({
|
|
|
8076
8137
|
defaultOpen = false,
|
|
8077
8138
|
onOpenChange,
|
|
8078
8139
|
"aria-label": ariaLabel,
|
|
8140
|
+
icon,
|
|
8079
8141
|
children,
|
|
8080
8142
|
className
|
|
8081
8143
|
}, _ref) {
|
|
8082
|
-
const
|
|
8083
|
-
const
|
|
8144
|
+
const reducedMotion = useReducedMotion();
|
|
8145
|
+
const panelClassName = cn(
|
|
8146
|
+
dialogPanelVariants({ variant }),
|
|
8147
|
+
reducedMotion && "transition-none",
|
|
8148
|
+
className
|
|
8149
|
+
);
|
|
8150
|
+
const wrapperClassName = dialogWrapperVariants({ variant });
|
|
8151
|
+
const getScrimClassName = React.useCallback(
|
|
8152
|
+
(state) => {
|
|
8153
|
+
if (reducedMotion) return "fixed inset-0 z-40 bg-scrim/32";
|
|
8154
|
+
return dialogScrimVariants({ animationState: state });
|
|
8155
|
+
},
|
|
8156
|
+
[reducedMotion]
|
|
8157
|
+
);
|
|
8158
|
+
const getAnimationClassName = React.useCallback(
|
|
8159
|
+
(state) => {
|
|
8160
|
+
if (reducedMotion) return "";
|
|
8161
|
+
return dialogAnimationVariants({ animationState: state, variant });
|
|
8162
|
+
},
|
|
8163
|
+
[reducedMotion, variant]
|
|
8164
|
+
);
|
|
8084
8165
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8085
8166
|
DialogHeadless,
|
|
8086
8167
|
{
|
|
@@ -8089,9 +8170,11 @@ var Dialog = React.forwardRef(function Dialog2({
|
|
|
8089
8170
|
...defaultOpen !== void 0 ? { defaultOpen } : {},
|
|
8090
8171
|
...onOpenChange !== void 0 ? { onOpenChange } : {},
|
|
8091
8172
|
...ariaLabel ? { "aria-label": ariaLabel } : {},
|
|
8173
|
+
...icon !== void 0 ? { icon } : {},
|
|
8092
8174
|
className: panelClassName,
|
|
8093
|
-
|
|
8094
|
-
|
|
8175
|
+
wrapperClassName,
|
|
8176
|
+
getScrimClassName,
|
|
8177
|
+
getAnimationClassName,
|
|
8095
8178
|
children
|
|
8096
8179
|
}
|
|
8097
8180
|
);
|
|
@@ -8102,7 +8185,7 @@ var DialogHeadline = React.forwardRef(
|
|
|
8102
8185
|
const { headlineId, variant } = useDialogContext();
|
|
8103
8186
|
if (variant === "fullscreen") {
|
|
8104
8187
|
return (
|
|
8105
|
-
// Top app bar row for fullscreen variant
|
|
8188
|
+
// Top app bar row for fullscreen variant — always has border-b border-outline-variant
|
|
8106
8189
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(dialogHeadlineVariants({ variant: "fullscreen" }), className), children: [
|
|
8107
8190
|
closeButton,
|
|
8108
8191
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { id: headlineId, className: dialogHeadlineTitleVariants(), children }),
|
|
@@ -8110,21 +8193,72 @@ var DialogHeadline = React.forwardRef(
|
|
|
8110
8193
|
] })
|
|
8111
8194
|
);
|
|
8112
8195
|
}
|
|
8113
|
-
return
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8196
|
+
return (
|
|
8197
|
+
// Basic variant: text-headline-small, text-on-surface, mb-4
|
|
8198
|
+
// group-data-[with-icon]/dialog:text-center is applied via the CVA base classes
|
|
8199
|
+
// when the parent panel root has data-with-icon set by DialogHeadless.
|
|
8200
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8201
|
+
"h2",
|
|
8202
|
+
{
|
|
8203
|
+
ref,
|
|
8204
|
+
id: headlineId,
|
|
8205
|
+
className: cn(dialogHeadlineVariants({ variant: "basic" }), className),
|
|
8206
|
+
children
|
|
8207
|
+
}
|
|
8208
|
+
)
|
|
8121
8209
|
);
|
|
8122
8210
|
}
|
|
8123
8211
|
);
|
|
8124
8212
|
DialogHeadline.displayName = "DialogHeadline";
|
|
8125
|
-
var DialogContent = React.forwardRef(function DialogContent2({ children, className },
|
|
8213
|
+
var DialogContent = React.forwardRef(function DialogContent2({ children, className }, forwardedRef) {
|
|
8126
8214
|
const { contentId, variant } = useDialogContext();
|
|
8127
|
-
|
|
8215
|
+
const internalRef = React.useRef(null);
|
|
8216
|
+
const setRef = React.useCallback(
|
|
8217
|
+
(node) => {
|
|
8218
|
+
internalRef.current = node;
|
|
8219
|
+
if (typeof forwardedRef === "function") {
|
|
8220
|
+
forwardedRef(node);
|
|
8221
|
+
} else if (forwardedRef !== null && forwardedRef !== void 0) {
|
|
8222
|
+
forwardedRef.current = node;
|
|
8223
|
+
}
|
|
8224
|
+
},
|
|
8225
|
+
[forwardedRef]
|
|
8226
|
+
);
|
|
8227
|
+
const updateDividers = React.useCallback(() => {
|
|
8228
|
+
const el = internalRef.current;
|
|
8229
|
+
if (!el) return;
|
|
8230
|
+
const isScrollable = el.scrollHeight > el.clientHeight;
|
|
8231
|
+
if (!isScrollable) {
|
|
8232
|
+
el.removeAttribute("data-scroll-divider-top");
|
|
8233
|
+
el.removeAttribute("data-scroll-divider-bottom");
|
|
8234
|
+
return;
|
|
8235
|
+
}
|
|
8236
|
+
const scrolledFromTop = el.scrollTop > 1;
|
|
8237
|
+
const scrolledToBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 1;
|
|
8238
|
+
if (scrolledFromTop) {
|
|
8239
|
+
el.setAttribute("data-scroll-divider-top", "");
|
|
8240
|
+
} else {
|
|
8241
|
+
el.removeAttribute("data-scroll-divider-top");
|
|
8242
|
+
}
|
|
8243
|
+
if (!scrolledToBottom) {
|
|
8244
|
+
el.setAttribute("data-scroll-divider-bottom", "");
|
|
8245
|
+
} else {
|
|
8246
|
+
el.removeAttribute("data-scroll-divider-bottom");
|
|
8247
|
+
}
|
|
8248
|
+
}, []);
|
|
8249
|
+
React.useEffect(() => {
|
|
8250
|
+
const el = internalRef.current;
|
|
8251
|
+
if (!el) return;
|
|
8252
|
+
updateDividers();
|
|
8253
|
+
el.addEventListener("scroll", updateDividers, { passive: true });
|
|
8254
|
+
const observer = new ResizeObserver(updateDividers);
|
|
8255
|
+
observer.observe(el);
|
|
8256
|
+
return () => {
|
|
8257
|
+
el.removeEventListener("scroll", updateDividers);
|
|
8258
|
+
observer.disconnect();
|
|
8259
|
+
};
|
|
8260
|
+
}, [updateDividers]);
|
|
8261
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: setRef, id: contentId, className: cn(dialogContentVariants({ variant }), className), children });
|
|
8128
8262
|
});
|
|
8129
8263
|
DialogContent.displayName = "DialogContent";
|
|
8130
8264
|
var DialogActions = React.forwardRef(function DialogActions2({ children, className }, ref) {
|