@qoretechnologies/reqore 0.74.11 → 0.74.12-pr.663.g65f34a4

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.
@@ -80,6 +80,7 @@ var styled_1 = require("../../helpers/styled");
80
80
  var utils_1 = require("../../helpers/utils");
81
81
  var useCombinedRefs_1 = require("../../hooks/useCombinedRefs");
82
82
  var useReqoreContext_1 = require("../../hooks/useReqoreContext");
83
+ var useFitTextSize_1 = require("../../hooks/useFitTextSize");
83
84
  var useTheme_1 = require("../../hooks/useTheme");
84
85
  var styles_1 = require("../../styles");
85
86
  var Breadcrumbs_1 = __importDefault(require("../Breadcrumbs"));
@@ -134,16 +135,29 @@ var getScrollportInset = function (el) {
134
135
  border: parseFloat(style.borderTopWidth) || 0,
135
136
  };
136
137
  };
137
- exports.StyledPanelTitleHeader = styled_components_1.default.div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n display: flex;\n justify-content: flex-start;\n align-items: center;\n flex: 1 1 auto;\n width: 100%;\n overflow: hidden;\n"], ["\n display: flex;\n justify-content: flex-start;\n align-items: center;\n flex: 1 1 auto;\n width: 100%;\n overflow: hidden;\n"])));
138
- exports.StyledPanelTitleHeaderContent = styled_components_1.default.div(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n // When the icon lives in the outer container (iconVerticalAlign mode),\n // we use a 2-column \u00D7 N-row CSS Grid where the LABEL ROW and DESCRIPTION\n // ROW are direct grid items \u2014 not wrapped inside a span-2 stack. That\n // makes each row's auto-sized height equal to the actual text row's\n // line-box height, so 'align-self: center' on the icon (in column 1)\n // visually centres the icon against the text row it shares a grid row\n // with \u2014 no font-metric guesswork.\n display: ", ";\n ", "\n flex: 0 1 auto;\n overflow: hidden;\n min-width: ", "px;\n"], ["\n // When the icon lives in the outer container (iconVerticalAlign mode),\n // we use a 2-column \u00D7 N-row CSS Grid where the LABEL ROW and DESCRIPTION\n // ROW are direct grid items \u2014 not wrapped inside a span-2 stack. That\n // makes each row's auto-sized height equal to the actual text row's\n // line-box height, so 'align-self: center' on the icon (in column 1)\n // visually centres the icon against the text row it shares a grid row\n // with \u2014 no font-metric guesswork.\n display: ", ";\n ", "\n flex: 0 1 auto;\n overflow: hidden;\n min-width: ", "px;\n"])), function (_a) {
138
+ /**
139
+ * The box the title lives in and, when the title may wrap, the thing that clamps it.
140
+ *
141
+ * It exists first as a measuring box: as a `min-width: 0` flex child it reports the width the
142
+ * row actually left for the title, where the heading itself would report what its text wants.
143
+ * `overflow: hidden` is what makes it shrinkable at all, and `display: flex` keeps it from
144
+ * opening a line box around the inline-flex heading — a block wrapper adds the row's leading on
145
+ * top of the heading's own box, which made a `tiny` panel 3px taller than it used to be.
146
+ */
147
+ var StyledPanelTitleLabelBox = styled_components_1.default.div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n display: flex;\n min-width: 0;\n overflow: hidden;\n flex: 0 1 auto;\n\n ", "\n"], ["\n display: flex;\n min-width: 0;\n overflow: hidden;\n flex: 0 1 auto;\n\n ", "\n"])), function (_a) {
148
+ var $clampLines = _a.$clampLines;
149
+ return $clampLines > 1 && (0, styled_components_1.css)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n .reqore-heading {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: ", ";\n overflow: hidden;\n white-space: normal;\n /* A single word longer than the box would push past it rather than break, and the\n clamp would have nothing to ellipsize. */\n overflow-wrap: anywhere;\n max-width: 100%;\n\n /* The heading wraps its text in a span of its own, and `-webkit-line-clamp` counts the\n box's CHILDREN rather than the lines inside them \u2014 so one block-level child reads as\n a single line and nothing is ever clamped, however far the text overruns. Putting the\n text back into the heading's own line boxes is what the clamp actually measures. */\n .reqore-span {\n display: inline;\n }\n }\n "], ["\n .reqore-heading {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: ", ";\n overflow: hidden;\n white-space: normal;\n /* A single word longer than the box would push past it rather than break, and the\n clamp would have nothing to ellipsize. */\n overflow-wrap: anywhere;\n max-width: 100%;\n\n /* The heading wraps its text in a span of its own, and \\`-webkit-line-clamp\\` counts the\n box's CHILDREN rather than the lines inside them \u2014 so one block-level child reads as\n a single line and nothing is ever clamped, however far the text overruns. Putting the\n text back into the heading's own line boxes is what the clamp actually measures. */\n .reqore-span {\n display: inline;\n }\n }\n "])), $clampLines);
150
+ });
151
+ exports.StyledPanelTitleHeader = styled_components_1.default.div(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n\n display: flex;\n justify-content: flex-start;\n align-items: center;\n /* A CONTENT basis, and both extremes were tried before settling here. Basis 0 hands the action\n group beside this one its full content width, so nothing ever overflows and the fold into the\n menu never fires \u2014 actions labelled \"hidden when small\" stay visible on a small panel. A 100%\n width does the opposite: this header claims the entire row, so the group is always crushed to\n its floor and always folds however much room there is, which hid Tree's save button behind an\n overflow menu on a panel with space to spare. On a content basis the two shrink against each\n other in proportion to what they each need, which is the only version where folding means\n \"there is no room\" rather than \"there is a header\". */\n flex: 1 1 auto;\n overflow: hidden;\n"], ["\n\n display: flex;\n justify-content: flex-start;\n align-items: center;\n /* A CONTENT basis, and both extremes were tried before settling here. Basis 0 hands the action\n group beside this one its full content width, so nothing ever overflows and the fold into the\n menu never fires \u2014 actions labelled \"hidden when small\" stay visible on a small panel. A 100%\n width does the opposite: this header claims the entire row, so the group is always crushed to\n its floor and always folds however much room there is, which hid Tree's save button behind an\n overflow menu on a panel with space to spare. On a content basis the two shrink against each\n other in proportion to what they each need, which is the only version where folding means\n \"there is no room\" rather than \"there is a header\". */\n flex: 1 1 auto;\n overflow: hidden;\n"])));
152
+ exports.StyledPanelTitleHeaderContent = styled_components_1.default.div(templateObject_9 || (templateObject_9 = __makeTemplateObject(["\n // When the icon lives in the outer container (iconVerticalAlign mode),\n // we use a 2-column \u00D7 N-row CSS Grid where the LABEL ROW and DESCRIPTION\n // ROW are direct grid items \u2014 not wrapped inside a span-2 stack. That\n // makes each row's auto-sized height equal to the actual text row's\n // line-box height, so 'align-self: center' on the icon (in column 1)\n // visually centres the icon against the text row it shares a grid row\n // with \u2014 no font-metric guesswork.\n display: ", ";\n ", "\n flex: 0 1 auto;\n overflow: hidden;\n min-width: ", "px;\n"], ["\n // When the icon lives in the outer container (iconVerticalAlign mode),\n // we use a 2-column \u00D7 N-row CSS Grid where the LABEL ROW and DESCRIPTION\n // ROW are direct grid items \u2014 not wrapped inside a span-2 stack. That\n // makes each row's auto-sized height equal to the actual text row's\n // line-box height, so 'align-self: center' on the icon (in column 1)\n // visually centres the icon against the text row it shares a grid row\n // with \u2014 no font-metric guesswork.\n display: ", ";\n ", "\n flex: 0 1 auto;\n overflow: hidden;\n min-width: ", "px;\n"])), function (_a) {
139
153
  var $hasOuterIcon = _a.$hasOuterIcon;
140
154
  return ($hasOuterIcon ? 'grid' : 'flex');
141
155
  }, function (_a) {
142
156
  var $hasOuterIcon = _a.$hasOuterIcon, size = _a.size, _b = _a.$iconVerticalAlign, $iconVerticalAlign = _b === void 0 ? 'center' : _b, $hasDescription = _a.$hasDescription;
143
157
  return $hasOuterIcon
144
- ? (0, styled_components_1.css)(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n // 'auto' lets the column grow to the icon's actual rendered size \u2014\n // important when consumers pass a custom 'iconProps.size' that does\n // not match the default size derived from 'panelSize'/'labelSize'.\n // 'iconSize' is still passed via 'min-width' below to ensure a\n // sensible minimum reservation when the row is otherwise empty.\n grid-template-columns: auto minmax(0, 1fr);\n grid-template-rows: ", ";\n column-gap: ", "px;\n row-gap: 3px;\n align-items: start;\n\n & > .reqore-panel-title-icon {\n ", "\n grid-column: 1;\n align-self: center;\n justify-self: start;\n // Suppress 'vertical-align: super' that ReqoreIcon applies to its\n // SVG for inline-text contexts. In our grid layout the wrapper is\n // already vertically centred against the text row's line-box;\n // 'display: block' takes the SVG out of inline flow entirely so\n // baseline/super offsets cannot push it off-centre. The wrapper's\n // own 'align-items: center' then centres the SVG within itself.\n & svg {\n display: block;\n vertical-align: middle;\n }\n }\n\n & > .reqore-panel-title-label-row {\n grid-column: 2;\n grid-row: 1;\n min-width: 0;\n }\n\n & > .reqore-panel-title-description {\n grid-column: 2;\n grid-row: 2;\n min-width: 0;\n }\n "], ["\n // 'auto' lets the column grow to the icon's actual rendered size \u2014\n // important when consumers pass a custom 'iconProps.size' that does\n // not match the default size derived from 'panelSize'/'labelSize'.\n // 'iconSize' is still passed via 'min-width' below to ensure a\n // sensible minimum reservation when the row is otherwise empty.\n grid-template-columns: auto minmax(0, 1fr);\n grid-template-rows: ", ";\n column-gap: ", "px;\n row-gap: 3px;\n align-items: start;\n\n & > .reqore-panel-title-icon {\n ", "\n grid-column: 1;\n align-self: center;\n justify-self: start;\n // Suppress 'vertical-align: super' that ReqoreIcon applies to its\n // SVG for inline-text contexts. In our grid layout the wrapper is\n // already vertically centred against the text row's line-box;\n // 'display: block' takes the SVG out of inline flow entirely so\n // baseline/super offsets cannot push it off-centre. The wrapper's\n // own 'align-items: center' then centres the SVG within itself.\n & svg {\n display: block;\n vertical-align: middle;\n }\n }\n\n & > .reqore-panel-title-label-row {\n grid-column: 2;\n grid-row: 1;\n min-width: 0;\n }\n\n & > .reqore-panel-title-description {\n grid-column: 2;\n grid-row: 2;\n min-width: 0;\n }\n "])), $hasDescription ? 'auto auto' : 'auto', sizes_1.PADDING_FROM_SIZE[size || 'normal'], $iconVerticalAlign === 'top'
145
- ? (0, styled_components_1.css)(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n grid-row: 1;\n "], ["\n grid-row: 1;\n "]))) : $iconVerticalAlign === 'bottom' && $hasDescription
146
- ? (0, styled_components_1.css)(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n grid-row: 2;\n "], ["\n grid-row: 2;\n "]))) : (0, styled_components_1.css)(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n grid-row: 1 / ", ";\n "], ["\n grid-row: 1 / ", ";\n "])), $hasDescription ? 3 : 2)) : (0, styled_components_1.css)(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n justify-content: flex-start;\n align-items: center;\n "], ["\n justify-content: flex-start;\n align-items: center;\n "])));
158
+ ? (0, styled_components_1.css)(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n // 'auto' lets the column grow to the icon's actual rendered size \u2014\n // important when consumers pass a custom 'iconProps.size' that does\n // not match the default size derived from 'panelSize'/'labelSize'.\n // 'iconSize' is still passed via 'min-width' below to ensure a\n // sensible minimum reservation when the row is otherwise empty.\n grid-template-columns: auto minmax(0, 1fr);\n grid-template-rows: ", ";\n column-gap: ", "px;\n row-gap: 3px;\n align-items: start;\n\n & > .reqore-panel-title-icon {\n ", "\n grid-column: 1;\n align-self: center;\n justify-self: start;\n // Suppress 'vertical-align: super' that ReqoreIcon applies to its\n // SVG for inline-text contexts. In our grid layout the wrapper is\n // already vertically centred against the text row's line-box;\n // 'display: block' takes the SVG out of inline flow entirely so\n // baseline/super offsets cannot push it off-centre. The wrapper's\n // own 'align-items: center' then centres the SVG within itself.\n & svg {\n display: block;\n vertical-align: middle;\n }\n }\n\n & > .reqore-panel-title-label-row {\n grid-column: 2;\n grid-row: 1;\n min-width: 0;\n }\n\n & > .reqore-panel-title-description {\n grid-column: 2;\n grid-row: 2;\n min-width: 0;\n }\n "], ["\n // 'auto' lets the column grow to the icon's actual rendered size \u2014\n // important when consumers pass a custom 'iconProps.size' that does\n // not match the default size derived from 'panelSize'/'labelSize'.\n // 'iconSize' is still passed via 'min-width' below to ensure a\n // sensible minimum reservation when the row is otherwise empty.\n grid-template-columns: auto minmax(0, 1fr);\n grid-template-rows: ", ";\n column-gap: ", "px;\n row-gap: 3px;\n align-items: start;\n\n & > .reqore-panel-title-icon {\n ", "\n grid-column: 1;\n align-self: center;\n justify-self: start;\n // Suppress 'vertical-align: super' that ReqoreIcon applies to its\n // SVG for inline-text contexts. In our grid layout the wrapper is\n // already vertically centred against the text row's line-box;\n // 'display: block' takes the SVG out of inline flow entirely so\n // baseline/super offsets cannot push it off-centre. The wrapper's\n // own 'align-items: center' then centres the SVG within itself.\n & svg {\n display: block;\n vertical-align: middle;\n }\n }\n\n & > .reqore-panel-title-label-row {\n grid-column: 2;\n grid-row: 1;\n min-width: 0;\n }\n\n & > .reqore-panel-title-description {\n grid-column: 2;\n grid-row: 2;\n min-width: 0;\n }\n "])), $hasDescription ? 'auto auto' : 'auto', sizes_1.PADDING_FROM_SIZE[size || 'normal'], $iconVerticalAlign === 'top'
159
+ ? (0, styled_components_1.css)(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n grid-row: 1;\n "], ["\n grid-row: 1;\n "]))) : $iconVerticalAlign === 'bottom' && $hasDescription
160
+ ? (0, styled_components_1.css)(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n grid-row: 2;\n "], ["\n grid-row: 2;\n "]))) : (0, styled_components_1.css)(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n grid-row: 1 / ", ";\n "], ["\n grid-row: 1 / ", ";\n "])), $hasDescription ? 3 : 2)) : (0, styled_components_1.css)(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n justify-content: flex-start;\n align-items: center;\n "], ["\n justify-content: flex-start;\n align-items: center;\n "])));
147
161
  }, function (_a) {
148
162
  var iconSize = _a.iconSize, hasIcon = _a.hasIcon;
149
163
  var width = 0;
@@ -152,8 +166,8 @@ exports.StyledPanelTitleHeaderContent = styled_components_1.default.div(template
152
166
  }
153
167
  return width;
154
168
  });
155
- exports.StyledPanelTitleHeaderLabelAndDescription = styled_components_1.default.div(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n display: flex;\n flex-flow: column;\n gap: 3px;\n min-width: 0;\n flex: 1 auto;\n"], ["\n display: flex;\n flex-flow: column;\n gap: 3px;\n min-width: 0;\n flex: 1 auto;\n"])));
156
- exports.StyledPanelTitleHeaderLabelAndBadge = styled_components_1.default.div(templateObject_9 || (templateObject_9 = __makeTemplateObject(["\n display: inline-flex;\n align-items: center;\n max-width: 100%;\n"], ["\n display: inline-flex;\n align-items: center;\n max-width: 100%;\n"])));
169
+ exports.StyledPanelTitleHeaderLabelAndDescription = styled_components_1.default.div(templateObject_10 || (templateObject_10 = __makeTemplateObject(["\n display: flex;\n flex-flow: column;\n gap: 3px;\n min-width: 0;\n flex: 1 auto;\n"], ["\n display: flex;\n flex-flow: column;\n gap: 3px;\n min-width: 0;\n flex: 1 auto;\n"])));
170
+ exports.StyledPanelTitleHeaderLabelAndBadge = styled_components_1.default.div(templateObject_11 || (templateObject_11 = __makeTemplateObject(["\n display: inline-flex;\n align-items: center;\n max-width: 100%;\n"], ["\n display: inline-flex;\n align-items: center;\n max-width: 100%;\n"])));
157
171
  /**
158
172
  * Does the panel wrapper draw its 1px border?
159
173
  *
@@ -184,7 +198,7 @@ exports.StyledPanel = (0, styled_components_1.default)(Effect_1.StyledEffect).wi
184
198
  // Everything else follows styled-components' own rule, so re-resizable still receives its
185
199
  // `enable` / size / handle config — those are component props, not HTML attributes.
186
200
  shouldForwardProp: (0, styled_1.omitStyleProps)('fill', 'accentPosition'),
187
- })(templateObject_18 || (templateObject_18 = __makeTemplateObject(["\n background-color: ", ";\n border-radius: ", "px;\n border: ", ";\n color: ", ";\n ", "\n overflow: ", ";\n display: flex;\n flex-flow: column;\n position: relative;\n backdrop-filter: ", ";\n width: ", ";\n max-width: 100%;\n flex: ", ";\n\n /* Hover-hiding applies ONLY where the pointer can hover. A touch device never\n fires :hover, so without this gate a `show: 'hover'` action is display:none\n forever \u2014 not merely invisible but absent from the layout, with nothing on\n screen hinting it exists. Where hover is unavailable the action stays\n visible; losing the tidiness beats losing the action. */\n @media (hover: hover) and (pointer: fine) {\n &:not(:hover) {\n .reqore-panel-action-hidden {\n display: none;\n }\n }\n }\n\n &.reqore-panel-floating-active {\n border-top-right-radius: 0;\n }\n\n ", "\n\n ", "\n\n ", "\n\n ", "\n"], ["\n background-color: ", ";\n border-radius: ", "px;\n border: ", ";\n color: ", ";\n ", "\n overflow: ", ";\n display: flex;\n flex-flow: column;\n position: relative;\n backdrop-filter: ", ";\n width: ", ";\n max-width: 100%;\n flex: ", ";\n\n /* Hover-hiding applies ONLY where the pointer can hover. A touch device never\n fires :hover, so without this gate a \\`show: 'hover'\\` action is display:none\n forever \u2014 not merely invisible but absent from the layout, with nothing on\n screen hinting it exists. Where hover is unavailable the action stays\n visible; losing the tidiness beats losing the action. */\n @media (hover: hover) and (pointer: fine) {\n &:not(:hover) {\n .reqore-panel-action-hidden {\n display: none;\n }\n }\n }\n\n &.reqore-panel-floating-active {\n border-top-right-radius: 0;\n }\n\n ", "\n\n ", "\n\n ", "\n\n ", "\n"])), function (_a) {
201
+ })(templateObject_20 || (templateObject_20 = __makeTemplateObject(["\n background-color: ", ";\n border-radius: ", "px;\n border: ", ";\n color: ", ";\n ", "\n overflow: ", ";\n display: flex;\n flex-flow: column;\n position: relative;\n backdrop-filter: ", ";\n width: ", ";\n max-width: 100%;\n flex: ", ";\n\n /* Hover-hiding applies ONLY where the pointer can hover. A touch device never\n fires :hover, so without this gate a `show: 'hover'` action is display:none\n forever \u2014 not merely invisible but absent from the layout, with nothing on\n screen hinting it exists. Where hover is unavailable the action stays\n visible; losing the tidiness beats losing the action. */\n @media (hover: hover) and (pointer: fine) {\n &:not(:hover) {\n .reqore-panel-action-hidden {\n display: none;\n }\n }\n }\n\n &.reqore-panel-floating-active {\n border-top-right-radius: 0;\n }\n\n ", "\n\n ", "\n\n ", "\n\n ", "\n"], ["\n background-color: ", ";\n border-radius: ", "px;\n border: ", ";\n color: ", ";\n ", "\n overflow: ", ";\n display: flex;\n flex-flow: column;\n position: relative;\n backdrop-filter: ", ";\n width: ", ";\n max-width: 100%;\n flex: ", ";\n\n /* Hover-hiding applies ONLY where the pointer can hover. A touch device never\n fires :hover, so without this gate a \\`show: 'hover'\\` action is display:none\n forever \u2014 not merely invisible but absent from the layout, with nothing on\n screen hinting it exists. Where hover is unavailable the action stays\n visible; losing the tidiness beats losing the action. */\n @media (hover: hover) and (pointer: fine) {\n &:not(:hover) {\n .reqore-panel-action-hidden {\n display: none;\n }\n }\n }\n\n &.reqore-panel-floating-active {\n border-top-right-radius: 0;\n }\n\n ", "\n\n ", "\n\n ", "\n\n ", "\n"])), function (_a) {
188
202
  var theme = _a.theme, _b = _a.opacity, opacity = _b === void 0 ? 1 : _b;
189
203
  return (0, polished_1.rgba)((0, colors_2.changeDarkness)((0, colors_2.getMainBackgroundColor)(theme), 0.03), opacity);
190
204
  }, function (_a) {
@@ -219,10 +233,10 @@ exports.StyledPanel = (0, styled_components_1.default)(Effect_1.StyledEffect).wi
219
233
  ? Math.max(0, (0, sizes_1.resolveRadius)('normal', radiusSize) -
220
234
  (hasPanelBorder({ flat: flat, intent: intent, accentPosition: accentPosition }) ? 1 : 0))
221
235
  : 0;
222
- return (0, styled_components_1.css)(templateObject_14 || (templateObject_14 = __makeTemplateObject(["\n position: relative;\n /* Reserve the strip's thickness so the title bar and content never sit\n under it \u2014 the same reservation ReqoreCallout makes. */\n padding-", ": ", "px;\n\n &::before {\n content: '';\n position: absolute;\n ", "\n ", "\n background-color: ", ";\n }\n "], ["\n position: relative;\n /* Reserve the strip's thickness so the title bar and content never sit\n under it \u2014 the same reservation ReqoreCallout makes. */\n padding-", ": ", "px;\n\n &::before {\n content: '';\n position: absolute;\n ", "\n ", "\n background-color: ", ";\n }\n "])), accentPosition === 'left' ? 'left' : 'top', $accentSize, accentPosition === 'left'
223
- ? (0, styled_components_1.css)(templateObject_10 || (templateObject_10 = __makeTemplateObject(["\n top: 0;\n bottom: 0;\n left: 0;\n width: ", "px;\n "], ["\n top: 0;\n bottom: 0;\n left: 0;\n width: ", "px;\n "])), $accentSize) : (0, styled_components_1.css)(templateObject_11 || (templateObject_11 = __makeTemplateObject(["\n top: 0;\n right: 0;\n left: 0;\n height: ", "px;\n "], ["\n top: 0;\n right: 0;\n left: 0;\n height: ", "px;\n "])), $accentSize), stripRadius
236
+ return (0, styled_components_1.css)(templateObject_16 || (templateObject_16 = __makeTemplateObject(["\n position: relative;\n /* Reserve the strip's thickness so the title bar and content never sit\n under it \u2014 the same reservation ReqoreCallout makes. */\n padding-", ": ", "px;\n\n &::before {\n content: '';\n position: absolute;\n ", "\n ", "\n background-color: ", ";\n }\n "], ["\n position: relative;\n /* Reserve the strip's thickness so the title bar and content never sit\n under it \u2014 the same reservation ReqoreCallout makes. */\n padding-", ": ", "px;\n\n &::before {\n content: '';\n position: absolute;\n ", "\n ", "\n background-color: ", ";\n }\n "])), accentPosition === 'left' ? 'left' : 'top', $accentSize, accentPosition === 'left'
237
+ ? (0, styled_components_1.css)(templateObject_12 || (templateObject_12 = __makeTemplateObject(["\n top: 0;\n bottom: 0;\n left: 0;\n width: ", "px;\n "], ["\n top: 0;\n bottom: 0;\n left: 0;\n width: ", "px;\n "])), $accentSize) : (0, styled_components_1.css)(templateObject_13 || (templateObject_13 = __makeTemplateObject(["\n top: 0;\n right: 0;\n left: 0;\n height: ", "px;\n "], ["\n top: 0;\n right: 0;\n left: 0;\n height: ", "px;\n "])), $accentSize), stripRadius
224
238
  ? accentPosition === 'left'
225
- ? (0, styled_components_1.css)(templateObject_12 || (templateObject_12 = __makeTemplateObject(["\n border-top-left-radius: ", "px;\n border-bottom-left-radius: ", "px;\n "], ["\n border-top-left-radius: ", "px;\n border-bottom-left-radius: ", "px;\n "])), stripRadius, stripRadius) : (0, styled_components_1.css)(templateObject_13 || (templateObject_13 = __makeTemplateObject(["\n border-top-left-radius: ", "px;\n border-top-right-radius: ", "px;\n "], ["\n border-top-left-radius: ", "px;\n border-top-right-radius: ", "px;\n "])), stripRadius, stripRadius)
239
+ ? (0, styled_components_1.css)(templateObject_14 || (templateObject_14 = __makeTemplateObject(["\n border-top-left-radius: ", "px;\n border-bottom-left-radius: ", "px;\n "], ["\n border-top-left-radius: ", "px;\n border-bottom-left-radius: ", "px;\n "])), stripRadius, stripRadius) : (0, styled_components_1.css)(templateObject_15 || (templateObject_15 = __makeTemplateObject(["\n border-top-left-radius: ", "px;\n border-top-right-radius: ", "px;\n "], ["\n border-top-left-radius: ", "px;\n border-top-right-radius: ", "px;\n "])), stripRadius, stripRadius)
226
240
  : undefined, intent
227
241
  ? theme.intents[intent]
228
242
  : (0, colors_2.changeLightness)((0, colors_2.getMainBackgroundColor)(theme), 0.22));
@@ -241,25 +255,34 @@ exports.StyledPanel = (0, styled_components_1.default)(Effect_1.StyledEffect).wi
241
255
  }, function (_a) {
242
256
  var interactive = _a.interactive, theme = _a.theme, _b = _a.opacity, opacity = _b === void 0 ? 1 : _b, flat = _a.flat, intent = _a.intent, accentPosition = _a.accentPosition;
243
257
  return interactive
244
- ? (0, styled_components_1.css)(templateObject_16 || (templateObject_16 = __makeTemplateObject(["\n cursor: pointer;\n\n &:hover {\n ", " ", " .reqore-panel-title-icon {\n transform: scale(", ");\n }\n\n background-color: ", ";\n\n border-color: ", ";\n\n ", "\n }\n "], ["\n cursor: pointer;\n\n &:hover {\n ", " ", " .reqore-panel-title-icon {\n transform: scale(", ");\n }\n\n background-color: ", ";\n\n border-color: ", ";\n\n ", "\n }\n "])), exports.StyledPanelTitle, exports.StyledPanelTitleHeaderContent, styles_1.ACTIVE_ICON_SCALE, opacity === 0 && flat
258
+ ? (0, styled_components_1.css)(templateObject_18 || (templateObject_18 = __makeTemplateObject(["\n cursor: pointer;\n\n &:hover {\n ", " ", " .reqore-panel-title-icon {\n transform: scale(", ");\n }\n\n background-color: ", ";\n\n border-color: ", ";\n\n ", "\n }\n "], ["\n cursor: pointer;\n\n &:hover {\n ", " ", " .reqore-panel-title-icon {\n transform: scale(", ");\n }\n\n background-color: ", ";\n\n border-color: ", ";\n\n ", "\n }\n "])), exports.StyledPanelTitle, exports.StyledPanelTitleHeaderContent, styles_1.ACTIVE_ICON_SCALE, opacity === 0 && flat
245
259
  ? undefined
246
260
  : (0, polished_1.rgba)((0, polished_1.darken)(0.025, (0, polished_1.rgba)((0, colors_2.changeDarkness)((0, colors_2.getMainBackgroundColor)(theme), 0.03), opacity)), opacity), hasPanelBorder({ flat: flat, intent: intent, accentPosition: accentPosition })
247
261
  ? (0, colors_2.changeLightness)(getPanelBorderBaseColor(theme, { intent: intent, accentPosition: accentPosition }), 0.25)
248
- : undefined, opacity !== 0 && (0, styled_components_1.css)(templateObject_15 || (templateObject_15 = __makeTemplateObject(["\n ", ":after {\n background: linear-gradient(\n to top,\n ", "\n 0%,\n transparent 100%\n );\n }\n "], ["\n ", ":after {\n background: linear-gradient(\n to top,\n ", "\n 0%,\n transparent 100%\n );\n }\n "])), item_1.StyledCollectionItemContent, (0, polished_1.rgba)((0, polished_1.darken)(0.025, (0, polished_1.rgba)((0, colors_2.changeDarkness)((0, colors_2.getMainBackgroundColor)(theme), 0.03), opacity)), opacity))) : undefined;
262
+ : undefined, opacity !== 0 && (0, styled_components_1.css)(templateObject_17 || (templateObject_17 = __makeTemplateObject(["\n ", ":after {\n background: linear-gradient(\n to top,\n ", "\n 0%,\n transparent 100%\n );\n }\n "], ["\n ", ":after {\n background: linear-gradient(\n to top,\n ", "\n 0%,\n transparent 100%\n );\n }\n "])), item_1.StyledCollectionItemContent, (0, polished_1.rgba)((0, polished_1.darken)(0.025, (0, polished_1.rgba)((0, colors_2.changeDarkness)((0, colors_2.getMainBackgroundColor)(theme), 0.03), opacity)), opacity))) : undefined;
249
263
  }, function (_a) {
250
264
  var raised = _a.raised, flat = _a.flat, intent = _a.intent, accentPosition = _a.accentPosition;
251
265
  return raised && !hasPanelBorder({ flat: flat, intent: intent, accentPosition: accentPosition }) && styles_1.RaisedElement;
252
266
  }, function (_a) {
253
267
  var fill = _a.fill, isCollapsed = _a.isCollapsed;
254
268
  return !isCollapsed && fill
255
- ? (0, styled_components_1.css)(templateObject_17 || (templateObject_17 = __makeTemplateObject(["\n height: 100%;\n flex: 1;\n "], ["\n height: 100%;\n flex: 1;\n "]))) : undefined;
269
+ ? (0, styled_components_1.css)(templateObject_19 || (templateObject_19 = __makeTemplateObject(["\n height: 100%;\n flex: 1;\n "], ["\n height: 100%;\n flex: 1;\n "]))) : undefined;
256
270
  }, function (_a) {
257
271
  var disabled = _a.disabled;
258
272
  return disabled && styles_1.DisabledElement;
259
273
  });
260
- exports.StyledPanelTitle = styled_components_1.default.div(templateObject_20 || (templateObject_20 = __makeTemplateObject(["\n display: flex;\n flex-flow: ", ";\n background-color: ", ";\n justify-content: space-between;\n\n padding: ", ";\n\n align-items: center;\n border-bottom: ", ";\n transition: background-color 0.2s ease-out;\n overflow: hidden;\n flex: 0 0 auto;\n gap: ", "px;\n\n ", " .reqore-panel-title-icon {\n transform: scale(", ");\n }\n\n ", "\n"], ["\n display: flex;\n flex-flow: ", ";\n background-color: ", ";\n justify-content: space-between;\n\n padding: ", ";\n\n align-items: center;\n border-bottom: ", ";\n transition: background-color 0.2s ease-out;\n overflow: hidden;\n flex: 0 0 auto;\n gap: ", "px;\n\n ", " .reqore-panel-title-icon {\n transform: scale(", ");\n }\n\n ", "\n"])), function (_a) {
261
- var responsive = _a.responsive, isMobile = _a.isMobile;
262
- return (responsive ? (isMobile ? 'column' : 'row') : 'row');
274
+ exports.StyledPanelTitle = styled_components_1.default.div(templateObject_25 || (templateObject_25 = __makeTemplateObject(["\n display: flex;\n /* Always a row. The title bar used to flip to a column when narrow; it now ellipsizes its\n label and lets the responsive action group collapse instead, which is what the \"hidden when\n small\" actions are for and what the stack was quietly defeating (a column made the group\n fluid, and a full-width group had room not to collapse). */\n flex-flow: ", ";\n\n ", "\n\n ", "\n\n ", "\n\n background-color: ", ";\n justify-content: space-between;\n\n padding: ", ";\n\n align-items: center;\n border-bottom: ", ";\n transition: background-color 0.2s ease-out;\n overflow: hidden;\n flex: 0 0 auto;\n gap: ", "px;\n\n ", " .reqore-panel-title-icon {\n transform: scale(", ");\n }\n\n ", "\n"], ["\n display: flex;\n /* Always a row. The title bar used to flip to a column when narrow; it now ellipsizes its\n label and lets the responsive action group collapse instead, which is what the \"hidden when\n small\" actions are for and what the stack was quietly defeating (a column made the group\n fluid, and a full-width group had room not to collapse). */\n flex-flow: ", ";\n\n ", "\n\n ", "\n\n ", "\n\n background-color: ", ";\n justify-content: space-between;\n\n padding: ", ";\n\n align-items: center;\n border-bottom: ", ";\n transition: background-color 0.2s ease-out;\n overflow: hidden;\n flex: 0 0 auto;\n gap: ", "px;\n\n ", " .reqore-panel-title-icon {\n transform: scale(", ");\n }\n\n ", "\n"])), function (_a) {
275
+ var $descriptionBelow = _a.$descriptionBelow;
276
+ return ($descriptionBelow ? 'row wrap' : 'row');
277
+ }, function (_a) {
278
+ var $descriptionFontPx = _a.$descriptionFontPx;
279
+ return !!$descriptionFontPx && (0, styled_components_1.css)(templateObject_21 || (templateObject_21 = __makeTemplateObject(["\n /* The description is a fixed px from `TEXT_FROM_SIZE` and knows nothing about the title\n having shrunk, so a fitted title crosses under it: at the 12px floor the support text\n renders at 15px and outranks the heading it supports. Scaling it by the SAME factor the\n title took keeps the two in their original proportion instead of giving the description\n a fit of its own \u2014 which would size it against its own box and let the pair drift apart\n again, in the other direction. */\n .reqore-panel-title-description {\n font-size: ", "px;\n }\n "], ["\n /* The description is a fixed px from \\`TEXT_FROM_SIZE\\` and knows nothing about the title\n having shrunk, so a fitted title crosses under it: at the 12px floor the support text\n renders at 15px and outranks the heading it supports. Scaling it by the SAME factor the\n title took keeps the two in their original proportion instead of giving the description\n a fit of its own \u2014 which would size it against its own box and let the pair drift apart\n again, in the other direction. */\n .reqore-panel-title-description {\n font-size: ", "px;\n }\n "])), $descriptionFontPx);
280
+ }, function (_a) {
281
+ var $descriptionBelow = _a.$descriptionBelow;
282
+ return $descriptionBelow && (0, styled_components_1.css)(templateObject_22 || (templateObject_22 = __makeTemplateObject(["\n /* Only on a wrapping bar. The header claims the row so the action group beside it gets\n squeezed and folds \u2014 that is what the base rule is for \u2014 but in a WRAPPING row a\n full-width claim takes the whole line and pushes the actions onto their own, which is\n not what \"description below\" asked for. Here the header grows from 0 into whatever the\n actions leave, on line one, and the description takes line two. */\n > .reqore-panel-title-header {\n width: auto;\n flex: 1 1 0%;\n min-width: 0;\n }\n "], ["\n /* Only on a wrapping bar. The header claims the row so the action group beside it gets\n squeezed and folds \u2014 that is what the base rule is for \u2014 but in a WRAPPING row a\n full-width claim takes the whole line and pushes the actions onto their own, which is\n not what \"description below\" asked for. Here the header grows from 0 into whatever the\n actions leave, on line one, and the description takes line two. */\n > .reqore-panel-title-header {\n width: auto;\n flex: 1 1 0%;\n min-width: 0;\n }\n "])));
283
+ }, function (_a) {
284
+ var $descriptionMaxLines = _a.$descriptionMaxLines;
285
+ return !!$descriptionMaxLines && (0, styled_components_1.css)(templateObject_23 || (templateObject_23 = __makeTemplateObject(["\n .reqore-panel-title-description {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: ", ";\n overflow: hidden;\n white-space: normal;\n overflow-wrap: anywhere;\n }\n "], ["\n .reqore-panel-title-description {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: ", ";\n overflow: hidden;\n white-space: normal;\n overflow-wrap: anywhere;\n }\n "])), $descriptionMaxLines);
263
286
  }, function (_a) {
264
287
  var theme = _a.theme, _b = _a.opacity, opacity = _b === void 0 ? 1 : _b;
265
288
  return (0, polished_1.rgba)((0, colors_2.changeLightness)((0, colors_2.getMainBackgroundColor)(theme), 0.03), opacity);
@@ -273,12 +296,12 @@ exports.StyledPanelTitle = styled_components_1.default.div(templateObject_20 ||
273
296
  : null;
274
297
  }, sizes_1.GAP_FROM_SIZE.normal, exports.StyledPanelTitleHeaderContent, styles_1.INACTIVE_ICON_SCALE, function (_a) {
275
298
  var collapsible = _a.collapsible;
276
- return collapsible && (0, styled_components_1.css)(templateObject_19 || (templateObject_19 = __makeTemplateObject(["\n cursor: pointer;\n &:hover {\n ", " .reqore-panel-title-icon {\n transform: scale(", ");\n }\n\n background-color: ", ";\n }\n "], ["\n cursor: pointer;\n &:hover {\n ", " .reqore-panel-title-icon {\n transform: scale(", ");\n }\n\n background-color: ", ";\n }\n "])), exports.StyledPanelTitleHeaderContent, styles_1.ACTIVE_ICON_SCALE, function (_a) {
299
+ return collapsible && (0, styled_components_1.css)(templateObject_24 || (templateObject_24 = __makeTemplateObject(["\n cursor: pointer;\n &:hover {\n ", " .reqore-panel-title-icon {\n transform: scale(", ");\n }\n\n background-color: ", ";\n }\n "], ["\n cursor: pointer;\n &:hover {\n ", " .reqore-panel-title-icon {\n transform: scale(", ");\n }\n\n background-color: ", ";\n }\n "])), exports.StyledPanelTitleHeaderContent, styles_1.ACTIVE_ICON_SCALE, function (_a) {
277
300
  var theme = _a.theme, _b = _a.opacity, opacity = _b === void 0 ? 1 : _b;
278
301
  return (0, polished_1.rgba)((0, colors_2.changeLightness)((0, colors_2.getMainBackgroundColor)(theme), 0.05), opacity);
279
302
  });
280
303
  });
281
- exports.StyledPanelTopBar = (0, styled_components_1.default)(exports.StyledPanelTitle)(templateObject_22 || (templateObject_22 = __makeTemplateObject(["\n padding-bottom: ", ";\n padding-top: ", ";\n position: ", ";\n /* `top: 0` must mean \"flush with the visible top edge of whatever scrolls\",\n which is what every call site assumes. Sticky resolves against the scroll\n container's CONTENT box, so on a padded scrollport \u2014 which every default\n panel/drawer/modal body is, since StyledPanelContent puts padding and\n overflow on one element \u2014 an uncompensated 0 parks the header below the\n padding and lets content scroll through the gap. `stickyHeaderInset` is\n that padding, measured from the real scroll ancestor at runtime;\n `stickyHeaderOffset` stays a deliberate caller offset on top of a now\n correct zero. */\n top: ", ";\n z-index: ", ";\n // A sticky header forces the panel wrapper to overflow visible (so the\n // header can stick), which stops the wrapper from clipping the header's top\n // corners \u2014 so without this the panel reads as square-topped even at rest.\n // AT REST, round the header's own top corners to the panel's inner radius so\n // the panel keeps its radius (inset 1px past a visible border to match the\n // wrapper's inner curve; flat border-less panels need no inset). ONCE STUCK\n // (pinned to the scroll container, detected at runtime via isStuck), drop the\n // radius to 0 so the pinned header reads as a full-width bar and only loses\n // its corners while it is actually moving with the scroll.\n border-top-left-radius: ", ";\n border-top-right-radius: ", ";\n background: ", ";\n // When the header is sticky AND the panel is minimal / transparent (opacity === 0), the\n // header has no surface of its own \u2014 scrolling content slides straight under it and the\n // label / actions become illegible. Apply a backdrop blur so the underlying content stays\n // visible but is softened enough for the header text to read clearly. Idle (no overflow,\n // nothing behind) the blur is a no-op so the static appearance is unchanged.\n ", "\n"], ["\n padding-bottom: ", ";\n padding-top: ", ";\n position: ", ";\n /* \\`top: 0\\` must mean \"flush with the visible top edge of whatever scrolls\",\n which is what every call site assumes. Sticky resolves against the scroll\n container's CONTENT box, so on a padded scrollport \u2014 which every default\n panel/drawer/modal body is, since StyledPanelContent puts padding and\n overflow on one element \u2014 an uncompensated 0 parks the header below the\n padding and lets content scroll through the gap. \\`stickyHeaderInset\\` is\n that padding, measured from the real scroll ancestor at runtime;\n \\`stickyHeaderOffset\\` stays a deliberate caller offset on top of a now\n correct zero. */\n top: ", ";\n z-index: ", ";\n // A sticky header forces the panel wrapper to overflow visible (so the\n // header can stick), which stops the wrapper from clipping the header's top\n // corners \u2014 so without this the panel reads as square-topped even at rest.\n // AT REST, round the header's own top corners to the panel's inner radius so\n // the panel keeps its radius (inset 1px past a visible border to match the\n // wrapper's inner curve; flat border-less panels need no inset). ONCE STUCK\n // (pinned to the scroll container, detected at runtime via isStuck), drop the\n // radius to 0 so the pinned header reads as a full-width bar and only loses\n // its corners while it is actually moving with the scroll.\n border-top-left-radius: ", ";\n border-top-right-radius: ", ";\n background: ", ";\n // When the header is sticky AND the panel is minimal / transparent (opacity === 0), the\n // header has no surface of its own \u2014 scrolling content slides straight under it and the\n // label / actions become illegible. Apply a backdrop blur so the underlying content stays\n // visible but is softened enough for the header text to read clearly. Idle (no overflow,\n // nothing behind) the blur is a no-op so the static appearance is unchanged.\n ", "\n"])), function (_a) {
304
+ exports.StyledPanelTopBar = (0, styled_components_1.default)(exports.StyledPanelTitle)(templateObject_27 || (templateObject_27 = __makeTemplateObject(["\n padding-bottom: ", ";\n padding-top: ", ";\n position: ", ";\n /* `top: 0` must mean \"flush with the visible top edge of whatever scrolls\",\n which is what every call site assumes. Sticky resolves against the scroll\n container's CONTENT box, so on a padded scrollport \u2014 which every default\n panel/drawer/modal body is, since StyledPanelContent puts padding and\n overflow on one element \u2014 an uncompensated 0 parks the header below the\n padding and lets content scroll through the gap. `stickyHeaderInset` is\n that padding, measured from the real scroll ancestor at runtime;\n `stickyHeaderOffset` stays a deliberate caller offset on top of a now\n correct zero. */\n top: ", ";\n z-index: ", ";\n // A sticky header forces the panel wrapper to overflow visible (so the\n // header can stick), which stops the wrapper from clipping the header's top\n // corners \u2014 so without this the panel reads as square-topped even at rest.\n // AT REST, round the header's own top corners to the panel's inner radius so\n // the panel keeps its radius (inset 1px past a visible border to match the\n // wrapper's inner curve; flat border-less panels need no inset). ONCE STUCK\n // (pinned to the scroll container, detected at runtime via isStuck), drop the\n // radius to 0 so the pinned header reads as a full-width bar and only loses\n // its corners while it is actually moving with the scroll.\n border-top-left-radius: ", ";\n border-top-right-radius: ", ";\n background: ", ";\n // When the header is sticky AND the panel is minimal / transparent (opacity === 0), the\n // header has no surface of its own \u2014 scrolling content slides straight under it and the\n // label / actions become illegible. Apply a backdrop blur so the underlying content stays\n // visible but is softened enough for the header text to read clearly. Idle (no overflow,\n // nothing behind) the blur is a no-op so the static appearance is unchanged.\n ", "\n"], ["\n padding-bottom: ", ";\n padding-top: ", ";\n position: ", ";\n /* \\`top: 0\\` must mean \"flush with the visible top edge of whatever scrolls\",\n which is what every call site assumes. Sticky resolves against the scroll\n container's CONTENT box, so on a padded scrollport \u2014 which every default\n panel/drawer/modal body is, since StyledPanelContent puts padding and\n overflow on one element \u2014 an uncompensated 0 parks the header below the\n padding and lets content scroll through the gap. \\`stickyHeaderInset\\` is\n that padding, measured from the real scroll ancestor at runtime;\n \\`stickyHeaderOffset\\` stays a deliberate caller offset on top of a now\n correct zero. */\n top: ", ";\n z-index: ", ";\n // A sticky header forces the panel wrapper to overflow visible (so the\n // header can stick), which stops the wrapper from clipping the header's top\n // corners \u2014 so without this the panel reads as square-topped even at rest.\n // AT REST, round the header's own top corners to the panel's inner radius so\n // the panel keeps its radius (inset 1px past a visible border to match the\n // wrapper's inner curve; flat border-less panels need no inset). ONCE STUCK\n // (pinned to the scroll container, detected at runtime via isStuck), drop the\n // radius to 0 so the pinned header reads as a full-width bar and only loses\n // its corners while it is actually moving with the scroll.\n border-top-left-radius: ", ";\n border-top-right-radius: ", ";\n background: ", ";\n // When the header is sticky AND the panel is minimal / transparent (opacity === 0), the\n // header has no surface of its own \u2014 scrolling content slides straight under it and the\n // label / actions become illegible. Apply a backdrop blur so the underlying content stays\n // visible but is softened enough for the header text to read clearly. Idle (no overflow,\n // nothing behind) the blur is a no-op so the static appearance is unchanged.\n ", "\n"])), function (_a) {
282
305
  var padded = _a.padded, size = _a.size, isCollapsed = _a.isCollapsed, minimal = _a.minimal;
283
306
  return !padded || isCollapsed || !minimal
284
307
  ? "".concat(getPaddingSize(padded, size), "px")
@@ -323,9 +346,9 @@ exports.StyledPanelTopBar = (0, styled_components_1.default)(exports.StyledPanel
323
346
  }, function (_a) {
324
347
  var stickyHeader = _a.stickyHeader, _b = _a.opacity, opacity = _b === void 0 ? 1 : _b;
325
348
  return stickyHeader &&
326
- opacity === 0 && (0, styled_components_1.css)(templateObject_21 || (templateObject_21 = __makeTemplateObject(["\n backdrop-filter: blur(30px);\n -webkit-backdrop-filter: blur(30px);\n "], ["\n backdrop-filter: blur(30px);\n -webkit-backdrop-filter: blur(30px);\n "])));
349
+ opacity === 0 && (0, styled_components_1.css)(templateObject_26 || (templateObject_26 = __makeTemplateObject(["\n backdrop-filter: blur(30px);\n -webkit-backdrop-filter: blur(30px);\n "], ["\n backdrop-filter: blur(30px);\n -webkit-backdrop-filter: blur(30px);\n "])));
327
350
  });
328
- exports.StyledPanelBottomActions = (0, styled_components_1.default)(exports.StyledPanelTitle)(templateObject_23 || (templateObject_23 = __makeTemplateObject(["\n padding-top: ", ";\n padding-bottom: ", ";\n border-bottom: 0;\n border-top: ", ";\n"], ["\n padding-top: ", ";\n padding-bottom: ", ";\n border-bottom: 0;\n border-top: ", ";\n"])), function (_a) {
351
+ exports.StyledPanelBottomActions = (0, styled_components_1.default)(exports.StyledPanelTitle)(templateObject_28 || (templateObject_28 = __makeTemplateObject(["\n padding-top: ", ";\n padding-bottom: ", ";\n border-bottom: 0;\n border-top: ", ";\n"], ["\n padding-top: ", ";\n padding-bottom: ", ";\n border-bottom: 0;\n border-top: ", ";\n"])), function (_a) {
329
352
  var padded = _a.padded, size = _a.size, minimal = _a.minimal;
330
353
  return !padded || !minimal
331
354
  ? "".concat(getPaddingSize(padded, size), "px")
@@ -345,7 +368,7 @@ exports.StyledPanelBottomActions = (0, styled_components_1.default)(exports.Styl
345
368
  ? "1px solid ".concat((0, polished_1.rgba)((0, colors_2.changeLightness)((0, colors_2.getMainBackgroundColor)(theme), 0.08), opacity))
346
369
  : null;
347
370
  });
348
- exports.StyledPanelContent = styled_components_1.default.div(templateObject_24 || (templateObject_24 = __makeTemplateObject(["\n display: ", ";\n padding: ", ";\n flex: 1;\n /* A flex child's min-height defaults to its content size, so without this the\n scrollable content can't shrink: a panel/drawer body taller than the panel\n pushes the (flex: 0 0 auto) bottom-actions footer past the panel's clipped\n edge and strands it, instead of scrolling. */\n min-height: 0;\n overflow: auto;\n overflow-wrap: anywhere;\n font-size: ", "px;\n"], ["\n display: ", ";\n padding: ", ";\n flex: 1;\n /* A flex child's min-height defaults to its content size, so without this the\n scrollable content can't shrink: a panel/drawer body taller than the panel\n pushes the (flex: 0 0 auto) bottom-actions footer past the panel's clipped\n edge and strands it, instead of scrolling. */\n min-height: 0;\n overflow: auto;\n overflow-wrap: anywhere;\n font-size: ", "px;\n"])), function (_a) {
371
+ exports.StyledPanelContent = styled_components_1.default.div(templateObject_29 || (templateObject_29 = __makeTemplateObject(["\n display: ", ";\n padding: ", ";\n flex: 1;\n /* A flex child's min-height defaults to its content size, so without this the\n scrollable content can't shrink: a panel/drawer body taller than the panel\n pushes the (flex: 0 0 auto) bottom-actions footer past the panel's clipped\n edge and strands it, instead of scrolling. */\n min-height: 0;\n overflow: auto;\n overflow-wrap: anywhere;\n font-size: ", "px;\n"], ["\n display: ", ";\n padding: ", ";\n flex: 1;\n /* A flex child's min-height defaults to its content size, so without this the\n scrollable content can't shrink: a panel/drawer body taller than the panel\n pushes the (flex: 0 0 auto) bottom-actions footer past the panel's clipped\n edge and strands it, instead of scrolling. */\n min-height: 0;\n overflow: auto;\n overflow-wrap: anywhere;\n font-size: ", "px;\n"])), function (_a) {
349
372
  var isCollapsed = _a.isCollapsed;
350
373
  return (isCollapsed ? 'none !important' : undefined);
351
374
  }, function (_a) {
@@ -359,7 +382,7 @@ exports.StyledPanelContent = styled_components_1.default.div(templateObject_24 |
359
382
  var size = _a.size;
360
383
  return sizes_1.TEXT_FROM_SIZE[size];
361
384
  });
362
- exports.StyledFloatingActions = styled_components_1.default.div(templateObject_25 || (templateObject_25 = __makeTemplateObject(["\n position: fixed;\n z-index: 999999;\n display: flex;\n padding: ", "px;\n background-color: ", ";\n border: ", ";\n border-bottom: none;\n border-radius: ", "px\n ", "px 0 0;\n gap: ", "px;\n pointer-events: auto;\n"], ["\n position: fixed;\n z-index: 999999;\n display: flex;\n padding: ", "px;\n background-color: ", ";\n border: ", ";\n border-bottom: none;\n border-radius: ", "px\n ", "px 0 0;\n gap: ", "px;\n pointer-events: auto;\n"])), function (_a) {
385
+ exports.StyledFloatingActions = styled_components_1.default.div(templateObject_30 || (templateObject_30 = __makeTemplateObject(["\n position: fixed;\n z-index: 999999;\n display: flex;\n padding: ", "px;\n background-color: ", ";\n border: ", ";\n border-bottom: none;\n border-radius: ", "px\n ", "px 0 0;\n gap: ", "px;\n pointer-events: auto;\n"], ["\n position: fixed;\n z-index: 999999;\n display: flex;\n padding: ", "px;\n background-color: ", ";\n border: ", ";\n border-bottom: none;\n border-radius: ", "px\n ", "px 0 0;\n gap: ", "px;\n pointer-events: auto;\n"])), function (_a) {
363
386
  var size = _a.size;
364
387
  return sizes_1.PADDING_FROM_SIZE[size];
365
388
  }, function (_a) {
@@ -387,11 +410,12 @@ exports.ReqorePanelSkeleton = (0, react_2.memo)(function (_a) {
387
410
  (children ? (children) : ((0, jsx_runtime_1.jsx)(ControlGroup_1.default, { vertical: true, children: (0, jsx_runtime_1.jsx)(Skeleton_1.ReqoreSkeleton, { lines: 5, width: '100%', size: 'tiny' }) })))] }));
388
411
  });
389
412
  exports.ReqorePanel = (0, react_2.forwardRef)(function (_a, ref) {
390
- var children = _a.children, label = _a.label, description = _a.description, _b = _a.collapseButtonProps, collapseButtonProps = _b === void 0 ? {} : _b, collapsible = _a.collapsible, onClose = _a.onClose, _c = _a.closeButtonProps, closeButtonProps = _c === void 0 ? {} : _c, _d = _a.rounded, rounded = _d === void 0 ? true : _d, _e = _a.actions, actions = _e === void 0 ? [] : _e, _f = _a.bottomActions, bottomActions = _f === void 0 ? [] : _f, isCollapsed = _a.isCollapsed, customTheme = _a.customTheme, inheritCustomTheme = _a.inheritCustomTheme, icon = _a.icon, iconImage = _a.iconImage, _g = _a.iconWithLabel, iconWithLabel = _g === void 0 ? false : _g, _h = _a.iconVerticalAlign, iconVerticalAlign = _h === void 0 ? 'center' : _h, intent = _a.intent, className = _a.className, flat = _a.flat, _j = _a.unMountContentOnCollapse, unMountContentOnCollapse = _j === void 0 ? true : _j, onCollapseChange = _a.onCollapseChange, _k = _a.padded, padded = _k === void 0 ? true : _k, _l = _a.wrapperPadding, wrapperPadding = _l === void 0 ? 'both' : _l, contentStyle = _a.contentStyle, contentEffect = _a.contentEffect, _m = _a.labelEffect, labelEffect = _m === void 0 ? {} : _m, _o = _a.descriptionEffect, descriptionEffect = _o === void 0 ? {} : _o, descriptionIntent = _a.descriptionIntent, labelSize = _a.labelSize, contentSize = _a.contentSize, minimal = _a.minimal, badge = _a.badge, iconColor = _a.iconColor, _p = _a.iconProps, iconProps = _p === void 0 ? {} : _p, fluid = _a.fluid, _q = _a.responsiveActions, responsiveActions = _q === void 0 ? true : _q, _r = _a.responsiveTitle, responsiveTitle = _r === void 0 ? true : _r, _s = _a.size, panelSize = _s === void 0 ? 'normal' : _s, getContentRef = _a.getContentRef, _t = _a.labelProps, labelProps = _t === void 0 ? {} : _t, disabled = _a.disabled, breadcrumbs = _a.breadcrumbs, _u = _a.showActionsWhenCollapsed, showActionsWhenCollapsed = _u === void 0 ? true : _u, showLabelTooltip = _a.showLabelTooltip, customLabelTooltip = _a.customLabelTooltip, resizable = _a.resizable, onLabelEdit = _a.onLabelEdit, responsiveActionsWrapperProps = _a.responsiveActionsWrapperProps, loading = _a.loading, loadingIconType = _a.loadingIconType, skeleton = _a.skeleton, errorBoundaryOptions = _a.errorBoundaryOptions, floatingActions = _a.floatingActions, _v = _a.collapseTooltip, collapseTooltip = _v === void 0 ? 'Collapse' : _v, _w = _a.expandTooltip, expandTooltip = _w === void 0 ? 'Expand' : _w, _x = _a.closeTooltip, closeTooltip = _x === void 0 ? 'Close' : _x, accentPosition = _a.accentPosition, accentSize = _a.accentSize, rest = __rest(_a, ["children", "label", "description", "collapseButtonProps", "collapsible", "onClose", "closeButtonProps", "rounded", "actions", "bottomActions", "isCollapsed", "customTheme", "inheritCustomTheme", "icon", "iconImage", "iconWithLabel", "iconVerticalAlign", "intent", "className", "flat", "unMountContentOnCollapse", "onCollapseChange", "padded", "wrapperPadding", "contentStyle", "contentEffect", "labelEffect", "descriptionEffect", "descriptionIntent", "labelSize", "contentSize", "minimal", "badge", "iconColor", "iconProps", "fluid", "responsiveActions", "responsiveTitle", "size", "getContentRef", "labelProps", "disabled", "breadcrumbs", "showActionsWhenCollapsed", "showLabelTooltip", "customLabelTooltip", "resizable", "onLabelEdit", "responsiveActionsWrapperProps", "loading", "loadingIconType", "skeleton", "errorBoundaryOptions", "floatingActions", "collapseTooltip", "expandTooltip", "closeTooltip", "accentPosition", "accentSize"]);
413
+ var _b, _c;
414
+ var children = _a.children, label = _a.label, description = _a.description, _d = _a.collapseButtonProps, collapseButtonProps = _d === void 0 ? {} : _d, collapsible = _a.collapsible, onClose = _a.onClose, _e = _a.closeButtonProps, closeButtonProps = _e === void 0 ? {} : _e, _f = _a.rounded, rounded = _f === void 0 ? true : _f, _g = _a.actions, actions = _g === void 0 ? [] : _g, _h = _a.bottomActions, bottomActions = _h === void 0 ? [] : _h, isCollapsed = _a.isCollapsed, customTheme = _a.customTheme, inheritCustomTheme = _a.inheritCustomTheme, icon = _a.icon, iconImage = _a.iconImage, _j = _a.iconWithLabel, iconWithLabel = _j === void 0 ? false : _j, _k = _a.iconVerticalAlign, iconVerticalAlign = _k === void 0 ? 'center' : _k, intent = _a.intent, className = _a.className, flat = _a.flat, _l = _a.unMountContentOnCollapse, unMountContentOnCollapse = _l === void 0 ? true : _l, onCollapseChange = _a.onCollapseChange, _m = _a.padded, padded = _m === void 0 ? true : _m, _o = _a.wrapperPadding, wrapperPadding = _o === void 0 ? 'both' : _o, contentStyle = _a.contentStyle, contentEffect = _a.contentEffect, _p = _a.labelEffect, labelEffect = _p === void 0 ? {} : _p, _q = _a.descriptionEffect, descriptionEffect = _q === void 0 ? {} : _q, descriptionIntent = _a.descriptionIntent, labelSize = _a.labelSize, contentSize = _a.contentSize, minimal = _a.minimal, badge = _a.badge, iconColor = _a.iconColor, _r = _a.iconProps, iconProps = _r === void 0 ? {} : _r, fluid = _a.fluid, _s = _a.responsiveActions, responsiveActions = _s === void 0 ? true : _s, _t = _a.responsiveTitle, responsiveTitle = _t === void 0 ? true : _t, _u = _a.compactTitle, compactTitle = _u === void 0 ? false : _u, _v = _a.fitLabel, fitLabel = _v === void 0 ? true : _v, _w = _a.labelMaxLines, labelMaxLines = _w === void 0 ? 2 : _w, _x = _a.descriptionPosition, descriptionPosition = _x === void 0 ? 'inline' : _x, _y = _a.descriptionMaxLines, descriptionMaxLines = _y === void 0 ? 2 : _y, labelMinTextSize = _a.labelMinTextSize, _z = _a.size, panelSize = _z === void 0 ? 'normal' : _z, getContentRef = _a.getContentRef, _0 = _a.labelProps, labelProps = _0 === void 0 ? {} : _0, disabled = _a.disabled, breadcrumbs = _a.breadcrumbs, _1 = _a.showActionsWhenCollapsed, showActionsWhenCollapsed = _1 === void 0 ? true : _1, showLabelTooltip = _a.showLabelTooltip, customLabelTooltip = _a.customLabelTooltip, resizable = _a.resizable, onLabelEdit = _a.onLabelEdit, responsiveActionsWrapperProps = _a.responsiveActionsWrapperProps, loading = _a.loading, loadingIconType = _a.loadingIconType, skeleton = _a.skeleton, errorBoundaryOptions = _a.errorBoundaryOptions, floatingActions = _a.floatingActions, _2 = _a.collapseTooltip, collapseTooltip = _2 === void 0 ? 'Collapse' : _2, _3 = _a.expandTooltip, expandTooltip = _3 === void 0 ? 'Expand' : _3, _4 = _a.closeTooltip, closeTooltip = _4 === void 0 ? 'Close' : _4, accentPosition = _a.accentPosition, accentSize = _a.accentSize, rest = __rest(_a, ["children", "label", "description", "collapseButtonProps", "collapsible", "onClose", "closeButtonProps", "rounded", "actions", "bottomActions", "isCollapsed", "customTheme", "inheritCustomTheme", "icon", "iconImage", "iconWithLabel", "iconVerticalAlign", "intent", "className", "flat", "unMountContentOnCollapse", "onCollapseChange", "padded", "wrapperPadding", "contentStyle", "contentEffect", "labelEffect", "descriptionEffect", "descriptionIntent", "labelSize", "contentSize", "minimal", "badge", "iconColor", "iconProps", "fluid", "responsiveActions", "responsiveTitle", "compactTitle", "fitLabel", "labelMaxLines", "descriptionPosition", "descriptionMaxLines", "labelMinTextSize", "size", "getContentRef", "labelProps", "disabled", "breadcrumbs", "showActionsWhenCollapsed", "showLabelTooltip", "customLabelTooltip", "resizable", "onLabelEdit", "responsiveActionsWrapperProps", "loading", "loadingIconType", "skeleton", "errorBoundaryOptions", "floatingActions", "collapseTooltip", "expandTooltip", "closeTooltip", "accentPosition", "accentSize"]);
391
415
  // Resolved ONCE, here — the accent styles interpolate px and reserve padding,
392
416
  // so they must only ever see a number. Shared with ReqoreCallout.
393
417
  var accentSizePx = (0, react_2.useMemo)(function () { return (0, utils_1.resolveAccentSize)(accentSize); }, [accentSize]);
394
- var _y = (0, react_2.useState)(isCollapsed || false), _isCollapsed = _y[0], setIsCollapsed = _y[1];
418
+ var _5 = (0, react_2.useState)(isCollapsed || false), _isCollapsed = _5[0], setIsCollapsed = _5[1];
395
419
  var primaryContentGradient = (0, Effect_1.getPrimaryGradient)(contentEffect === null || contentEffect === void 0 ? void 0 : contentEffect.gradient);
396
420
  var primaryContentColors = primaryContentGradient && typeof primaryContentGradient.colors === 'object'
397
421
  ? primaryContentGradient.colors
@@ -409,8 +433,8 @@ exports.ReqorePanel = (0, react_2.forwardRef)(function (_a, ref) {
409
433
  }, []);
410
434
  var isMobile = (0, useReqoreContext_1.useReqoreProperty)('isMobile');
411
435
  var targetRef = (0, useCombinedRefs_1.useCombinedRefs)(ref).targetRef;
412
- var _z = (0, react_use_1.useMeasure)(), measureRef = _z[0], width = _z[1].width;
413
- var _0 = (0, react_2.useState)(false), _isHovered = _0[0], setIsHovered = _0[1];
436
+ var _6 = (0, react_use_1.useMeasure)(), measureRef = _6[0], width = _6[1].width;
437
+ var _7 = (0, react_2.useState)(false), _isHovered = _7[0], setIsHovered = _7[1];
414
438
  var floatingActionsRef = (0, react_2.useRef)(null);
415
439
  var panelRef = (0, react_2.useRef)(null);
416
440
  var hoverTimerRef = (0, react_2.useRef)(null);
@@ -428,8 +452,8 @@ exports.ReqorePanel = (0, react_2.forwardRef)(function (_a, ref) {
428
452
  // triggers it. Only wired when `stickyHeader` is on, so ordinary panels pay
429
453
  // nothing.
430
454
  var stickySentinelRef = (0, react_2.useRef)(null);
431
- var _1 = (0, react_2.useState)(false), isHeaderStuck = _1[0], setIsHeaderStuck = _1[1];
432
- var _2 = (0, react_2.useState)(0), stickyInset = _2[0], setStickyInset = _2[1];
455
+ var _8 = (0, react_2.useState)(false), isHeaderStuck = _8[0], setIsHeaderStuck = _8[1];
456
+ var _9 = (0, react_2.useState)(0), stickyInset = _9[0], setStickyInset = _9[1];
433
457
  (0, react_2.useEffect)(function () {
434
458
  var _a;
435
459
  if (!rest.stickyHeader) {
@@ -578,7 +602,49 @@ exports.ReqorePanel = (0, react_2.forwardRef)(function (_a, ref) {
578
602
  }, [label, collapsible, onClose, nonFloatingActions, badge, icon]);
579
603
  // Return true if the card has a title bar, otherwise return false.
580
604
  var hasTitleHeader = (0, react_2.useMemo)(function () { return !!label || !!badge || !!icon || !!breadcrumbs; }, [label, icon, badge, breadcrumbs]);
581
- var isSmall = (0, react_2.useMemo)(function () { return responsiveTitle && width < 480 && process.env.NODE_ENV !== 'test'; }, [width, responsiveTitle]);
605
+ /**
606
+ * `width` comes from `useMeasure`, which reports 0 until the element is actually measured —
607
+ * and in jsdom it stays 0 forever. `0 < 480` is true, so an unmeasured panel used to claim it
608
+ * was narrow; the guard against that was `NODE_ENV !== 'test'`, added in 4eb8ac1 ("Test
609
+ * fixes") back when the suite was jsdom-only.
610
+ *
611
+ * That proxy stopped holding when snapshots moved to a real browser under vitest: same
612
+ * NODE_ENV, real widths, and the narrow layout switched off in the one place it needed to be
613
+ * on. No snapshot has ever shown a stacked title bar, which is why the stack going three rows
614
+ * deep on a drawer went unnoticed for so long (#664).
615
+ *
616
+ * Asking whether the width was MEASURED says what the guard always meant. jsdom keeps its 0
617
+ * and stays wide, so the unit suite is unaffected; a browser measures and behaves.
618
+ */
619
+ var isSmall = (0, react_2.useMemo)(function () { return responsiveTitle && width > 0 && width < 480; }, [width, responsiveTitle]);
620
+ /**
621
+ * Narrow, from either trigger: the panel measuring under 480px, or the provider's
622
+ * viewport-level `isMobile`.
623
+ *
624
+ * A narrow title bar STAYS ON ONE ROW. The label ellipsizes (it already carries `noWrap`) and
625
+ * the responsive action group collapses into its overflow, which is what the "hidden when
626
+ * small" actions exist for. It used to stack instead — title on one row, actions on another,
627
+ * close/collapse on a third — and that cost more room than the title ever took: measured on a
628
+ * drawer at 375px, a 93px header for a title using 204px of the width, with a 359px action
629
+ * group holding a 106px button and 261px of nothing beside it.
630
+ *
631
+ * Stacking also broke the collapse it was supposed to help. Going to a column made the action
632
+ * group `fluid`, the group got a full-width row, and with that much space its own measurement
633
+ * decided fewer actions needed collapsing — so an action labelled "hidden when small" rendered
634
+ * in full on a small panel.
635
+ */
636
+ var isNarrow = isSmall || isMobile;
637
+ /**
638
+ * The tightest fallback, still opt-in: drop the title TEXT and leave the icon in its place.
639
+ * For a bar too narrow even to ellipsize into — a `[icon] [actions] [×]` header. Nothing
640
+ * changes without an icon to fall back to, and the label survives as that icon's tooltip.
641
+ */
642
+ /**
643
+ * The title gives up its space entirely and the icon stands in. Opt-in only: the automatic
644
+ * end of the cascade is the ellipsis, and dropping the title is a decision the caller makes,
645
+ * not something a width should take on their behalf. Needs an icon to fall back to.
646
+ */
647
+ var hideTitleForIcon = isNarrow && compactTitle;
582
648
  // If collapsible is true, toggle the isCollapsed state
583
649
  // If the isCollapsed state is true, the component is expanded
584
650
  // If the isCollapsed state is false, the component is collapsed
@@ -607,10 +673,23 @@ exports.ReqorePanel = (0, react_2.forwardRef)(function (_a, ref) {
607
673
  return function (action, index) {
608
674
  return renderActions(action, index, true, align);
609
675
  };
610
- }, [actions, showActionsWhenCollapsed, _isCollapsed]);
611
- var hasNonResponsiveActions = (0, react_2.useCallback)(function (data) {
612
- return (!responsiveActions && (0, lodash_1.size)(data)) ||
613
- data.some(function (action) { return action.responsive === false && action.show !== false; });
676
+ },
677
+ // `isNarrow` belongs here even though this callback does not name it: it wraps
678
+ // `renderActions`, which does. Without it the wrapper keeps whichever `renderActions`
679
+ // existed on the first render when `useMeasure` still reported 0 and the bar did not
680
+ // yet know it was narrow — so a width-dependent decision inside it could never take
681
+ // effect. That is what silently defeated dropping the action labels: the flag flipped and
682
+ // the closure did not. (`renderActions` itself cannot go here: it is declared below.)
683
+ [isNarrow, actions, showActionsWhenCollapsed, _isCollapsed]);
684
+ var hasNonResponsiveActions = (0, react_2.useCallback)(
685
+ // `show: false` has to be honoured on BOTH paths. The `responsiveActions: false` arm used
686
+ // to ask only whether the array had entries, so a panel whose every action is hidden still
687
+ // reported having some and rendered an empty control group. It went unnoticed while the
688
+ // prop defaulted to `true` and that arm was mostly dead.
689
+ function (data) {
690
+ return data.some(function (action) {
691
+ return (!responsiveActions || action.responsive === false) && action.show !== false;
692
+ });
614
693
  }, [actions, bottomActions, responsiveActions, showActionsWhenCollapsed, _isCollapsed]);
615
694
  var hasResponsiveActions = (0, react_2.useCallback)(function (data) {
616
695
  return responsiveActions &&
@@ -621,7 +700,14 @@ exports.ReqorePanel = (0, react_2.forwardRef)(function (_a, ref) {
621
700
  return function (action, index) {
622
701
  return renderActions(action, index, false, align);
623
702
  };
624
- }, [actions, bottomActions, responsiveActions, showActionsWhenCollapsed, _isCollapsed]);
703
+ }, [
704
+ isNarrow,
705
+ actions,
706
+ bottomActions,
707
+ responsiveActions,
708
+ showActionsWhenCollapsed,
709
+ _isCollapsed,
710
+ ]);
625
711
  var renderActions = (0, react_2.useCallback)(function (action, index, includeResponsive, align) {
626
712
  if (align === void 0) { align = 'flex-end'; }
627
713
  if (action.show === false ||
@@ -651,14 +737,23 @@ exports.ReqorePanel = (0, react_2.forwardRef)(function (_a, ref) {
651
737
  }
652
738
  : undefined })));
653
739
  }
654
- return ((0, react_1.createElement)(Button_1.default, __assign({ fixed: true }, rest, { id: id, key: index, className: className, customTheme: rest.customTheme || theme, intent: intent, onClick: rest.onClick
740
+ // FIRST thing to go when the bar is short of room: the action's LABEL, not the
741
+ // panel's title. An action is a verb the icon already carries, and the label moves
742
+ // to the tooltip rather than being lost; the title is the only thing naming what
743
+ // this panel IS. Needs an icon to fall back to — an unlabelled, iconless button is
744
+ // a blank box — and a caller can pin the label with `responsive: false`.
745
+ // `label` on an action is typed `string | number`; a tooltip is not, so the numeric
746
+ // case is stringified rather than cast away.
747
+ var actionLabelTooltip = typeof label === 'number' ? String(label) : label;
748
+ var dropActionLabel = isNarrow && !!rest.icon && !!label;
749
+ return ((0, react_1.createElement)(Button_1.default, __assign({ fixed: true }, rest, { id: id, key: index, className: className, customTheme: rest.customTheme || theme, intent: intent, tooltip: dropActionLabel ? rest.tooltip || actionLabelTooltip : rest.tooltip, onClick: rest.onClick
655
750
  ? function (e) {
656
751
  var _a;
657
752
  e.stopPropagation();
658
753
  (_a = rest.onClick) === null || _a === void 0 ? void 0 : _a.call(rest);
659
754
  }
660
- : undefined }), label));
661
- }, [actions, theme, showActionsWhenCollapsed, _isCollapsed]);
755
+ : undefined }), dropActionLabel ? undefined : label));
756
+ }, [actions, theme, showActionsWhenCollapsed, _isCollapsed, isNarrow]);
662
757
  var interactive = !!(rest.onClick ||
663
758
  rest.onMouseOver ||
664
759
  rest.onMouseEnter ||
@@ -679,9 +774,10 @@ exports.ReqorePanel = (0, react_2.forwardRef)(function (_a, ref) {
679
774
  var showNonResponsiveGroup = (0, react_2.useCallback)(function () {
680
775
  var show = false;
681
776
  // SHOULD THIS GROUP SHOW CONTROL BUTTONS?
682
- // This group should only show control buttons
683
- // if the panel is not small
684
- if (!isSmall && (onClose || collapsible)) {
777
+ // Always, now that a narrow bar stays on one row: there is no separate control row for them
778
+ // to move to. This used to read `!isSmall`, which withheld them here because a small panel
779
+ // rendered its own row below — and that row is what the one-row treatment removed.
780
+ if (onClose || collapsible) {
685
781
  show = true;
686
782
  }
687
783
  // OTHERWISE, ARE THERE ANY NON RESPONSIVE ACTIONS TO BE SHOWN?
@@ -691,7 +787,139 @@ exports.ReqorePanel = (0, react_2.forwardRef)(function (_a, ref) {
691
787
  show = true;
692
788
  }
693
789
  return show;
694
- }, [isSmall, collapsible, nonFloatingActions, hasNonResponsiveActions]);
790
+ }, [collapsible, onClose, nonFloatingActions, hasNonResponsiveActions]);
791
+ /**
792
+ * The title's natural size in px, from the heading level it renders at — the same
793
+ * `labelSize || HEADER_SIZE_TO_NUMBER[panelSize]` the icon is sized from.
794
+ */
795
+ var labelNaturalPx = (_b = sizes_1.HEADER_LEVEL_TO_PX[labelSize || sizes_1.HEADER_SIZE_TO_NUMBER[panelSize]]) !== null && _b !== void 0 ? _b : sizes_1.HEADER_LEVEL_TO_PX[3];
796
+ /**
797
+ * SECOND thing to give: the title's size. Once the actions are down to icons and the
798
+ * row is still short, the title shrinks toward a floor rather than dropping characters
799
+ * — the end of a name is often the part that distinguishes it. Only at the floor does
800
+ * the existing `noWrap` ellipsis take over.
801
+ *
802
+ * Off when the caller pins `labelEffect.textSize`: they have said what size they want.
803
+ */
804
+ /**
805
+ * The width the layout left for the title, observed on the box that claims the leftover
806
+ * space. Kept as state rather than read during render so the fit is calculated from a width
807
+ * that has actually been laid out.
808
+ */
809
+ /** Whole lines, at least one — a fractional or zero `labelMaxLines` is a caller slip, not
810
+ * a request for half a line of text. */
811
+ var clampLines = Math.max(1, Math.floor(labelMaxLines) || 1);
812
+ /** `compactTitle` drops the description with the title it belongs to, so a bar that has
813
+ * given up its title never grows a row to carry one. */
814
+ var descriptionBelow = descriptionPosition === 'below' && !!description && !(hideTitleForIcon && !!icon);
815
+ var descriptionClamp = Math.max(0, Math.floor(descriptionMaxLines || 0));
816
+ /**
817
+ * A clamped description opens on click so the whole of it can be read — on a phone there is
818
+ * no hover to reveal it with, and two lines of a long sentence are an invitation to tap.
819
+ *
820
+ * Interactive only while it is actually cut, or already open: a description that fits is
821
+ * left alone, so a click on it still reaches the bar and collapses a collapsible panel the
822
+ * way it always has. When it IS cut, that same click must not reach the bar — opening the
823
+ * text and folding the panel away in one gesture is the worst of both.
824
+ */
825
+ var _10 = (0, react_2.useState)(false), isDescriptionExpanded = _10[0], setIsDescriptionExpanded = _10[1];
826
+ var _11 = (0, react_2.useState)(false), isDescriptionTruncated = _11[0], setIsDescriptionTruncated = _11[1];
827
+ var descriptionRef = (0, react_2.useRef)(null);
828
+ var descriptionIsClamped = descriptionClamp > 0 && !isDescriptionExpanded;
829
+ (0, react_2.useLayoutEffect)(function () {
830
+ var el = descriptionRef.current;
831
+ // `scrollHeight` is what the text wants, `clientHeight` what the clamp left it. Re-read
832
+ // whenever the bar's width moves, because that is what changes how many lines it takes.
833
+ setIsDescriptionTruncated(descriptionIsClamped && !!el && el.scrollHeight > el.clientHeight + 1);
834
+ }, [description, descriptionIsClamped, width]);
835
+ var descriptionIsInteractive = isDescriptionTruncated || isDescriptionExpanded;
836
+ var handleDescriptionClick = (0, react_2.useCallback)(function (event) {
837
+ if (!descriptionIsInteractive) {
838
+ return;
839
+ }
840
+ event.stopPropagation();
841
+ setIsDescriptionExpanded(function (expanded) { return !expanded; });
842
+ }, [descriptionIsInteractive]);
843
+ /** Shared by both places the description can render — inline with the title, or on its
844
+ * own row below — so the two cannot drift apart. */
845
+ var descriptionProps = __assign({ ref: descriptionRef, className: 'reqore-panel-title-description', size: panelSize, effect: __assign({ opacity: 0.7 }, descriptionEffect), intent: descriptionIntent, onClick: handleDescriptionClick }, (descriptionIsInteractive
846
+ ? {
847
+ role: 'button',
848
+ tabIndex: 0,
849
+ 'aria-expanded': isDescriptionExpanded,
850
+ onKeyDown: function (event) {
851
+ if (event.key === 'Enter' || event.key === ' ') {
852
+ event.preventDefault();
853
+ handleDescriptionClick(event);
854
+ }
855
+ },
856
+ style: { cursor: 'pointer' },
857
+ }
858
+ : {}));
859
+ var _12 = (0, react_2.useState)(undefined), labelAvailable = _12[0], setLabelAvailable = _12[1];
860
+ var _13 = (0, useFitTextSize_1.useFitTextSize)({
861
+ text: typeof label === 'string' ? label : '',
862
+ available: labelAvailable,
863
+ max: labelNaturalPx,
864
+ min: labelMinTextSize,
865
+ lines: clampLines,
866
+ enabled: fitLabel !== false && typeof label === 'string' && !(labelEffect === null || labelEffect === void 0 ? void 0 : labelEffect.textSize),
867
+ }), labelFitRef = _13[0], labelFitPx = _13[1];
868
+ /** Only while the title is actually below its natural size, and never over a caller who
869
+ * pinned the description's own size. */
870
+ var descriptionFontPx = fitLabel && !(descriptionEffect === null || descriptionEffect === void 0 ? void 0 : descriptionEffect.textSize) && labelFitPx < labelNaturalPx
871
+ ? Math.max(useFitTextSize_1.FIT_TEXT_FLOOR_PX, Math.round(((_c = sizes_1.TEXT_FROM_SIZE[panelSize]) !== null && _c !== void 0 ? _c : sizes_1.TEXT_FROM_SIZE.normal) * (labelFitPx / labelNaturalPx)))
872
+ : 0;
873
+ /**
874
+ * How much room the title has, computed rather than measured off its own box.
875
+ *
876
+ * The box the title sits in is sized by its content, so measuring THAT is circular — the
877
+ * font shrinks, the box shrinks, and the size ratchets to the floor. Measuring the space it
878
+ * COULD have is not: take the bar, subtract everything competing with the title, and what
879
+ * is left does not move when the title's font does.
880
+ *
881
+ * Everything competing with it is text-independent: the action groups and control buttons
882
+ * (the bar's other children), and the icon and badge that share the title's row. The action
883
+ * group is `fluid` by default and would otherwise swallow the leftover, which is why this
884
+ * cannot be solved by giving the title column `flex-grow` — it competes with a group that
885
+ * is designed to take the rest, and loses.
886
+ *
887
+ * Re-run on `width`, which is the bar's own measured width: when the bar resizes, so does
888
+ * everything in it.
889
+ */
890
+ /**
891
+ * The title's available width is its CONTAINING BLOCK minus whatever shares it — measured,
892
+ * not reconstructed.
893
+ *
894
+ * This used to subtract the action group, the gaps and the icon from the bar's width. That
895
+ * arithmetic held only for the one layout it was written against: give the panel a
896
+ * `description` and the icon moves into an outer grid, so the sum over-reported by 30-80px
897
+ * and the fit under-shrank. The symptom was the worst of both worlds — a title both smaller
898
+ * AND ellipsized, which is the one outcome the feature exists to avoid.
899
+ *
900
+ * Measuring the parent is safe precisely where it looks circular. While the text overflows
901
+ * — the only regime in which anything shrinks — the parent is pinned by the row, not by the
902
+ * text: at a 300px bar it measures 128px at 19px, at 16px, and wrapped to two lines. When
903
+ * the text does fit, the parent has slack and the fit returns the natural size, which is
904
+ * the right answer either way.
905
+ */
906
+ (0, react_2.useLayoutEffect)(function () {
907
+ var node = labelFitRef.current;
908
+ var parent = node === null || node === void 0 ? void 0 : node.parentElement;
909
+ if (!fitLabel || !node || !parent) {
910
+ return;
911
+ }
912
+ var style = getComputedStyle(parent);
913
+ var padding = (parseFloat(style.paddingLeft) || 0) + (parseFloat(style.paddingRight) || 0);
914
+ var gap = parseFloat(style.columnGap) || parseFloat(style.gap) || 0;
915
+ // A badge sits beside the title in the same box and takes real width.
916
+ var siblings = Array.from(parent.children).reduce(function (total, child) {
917
+ return child === node ? total : total + child.getBoundingClientRect().width;
918
+ }, 0);
919
+ var gaps = gap * Math.max(0, parent.children.length - 1);
920
+ var next = Math.max(0, Math.round(parent.clientWidth - padding - siblings - gaps));
921
+ setLabelAvailable(function (current) { return (current === next ? current : next); });
922
+ }, [fitLabel, label, width, badge, actions, panelSize, description, clampLines]);
695
923
  var iconTooltip = (0, react_2.useMemo)(function () { return ({
696
924
  content: label,
697
925
  }); }, [label]);
@@ -710,8 +938,13 @@ exports.ReqorePanel = (0, react_2.forwardRef)(function (_a, ref) {
710
938
  panelRef.current = node;
711
939
  }, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [rest.stickyHeader ? ((0, jsx_runtime_1.jsx)("div", { ref: stickySentinelRef, "aria-hidden": 'true', style: { height: 0 } })) : null, _isHovered &&
712
940
  (0, lodash_1.size)(floatingActionsList) > 0 &&
713
- (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)(exports.StyledFloatingActions, { className: 'reqore-panel-floating-actions', theme: theme, size: panelSize, intent: intent, flat: flat, ref: floatingActionsRef, onMouseLeave: handleFloatingActionsMouseLeave, children: (0, jsx_runtime_1.jsx)(ControlGroup_1.default, { size: panelSize, gapSize: panelSize, children: floatingActionsList.map(function (action, index) { return renderActions(action, index, true); }) }) }), document.body), hasTitleBar && ((0, jsx_runtime_1.jsxs)(exports.StyledPanelTopBar, { flat: flat, isCollapsed: _isCollapsed, collapsible: collapsible, className: 'reqore-panel-title', onClick: handleCollapseClick, theme: theme, minimal: minimal || opacity === 0, size: contentSize || panelSize, opacity: minimal ? 0 : opacity !== null && opacity !== void 0 ? opacity : 1, noHorizontalPadding: noHorizontalPadding, responsive: responsiveTitle, isMobile: isMobile || isSmall, ref: measureRef, padded: padded, wrapperPadding: wrapperPadding, intent: intent, rounded: rounded, radiusSize: rest.radiusSize, stickyHeader: rest.stickyHeader, stickyHeaderOffset: rest.stickyHeaderOffset, stickyHeaderInset: stickyInset, isStuck: isHeaderStuck, children: [hasTitleHeader && ((0, jsx_runtime_1.jsxs)(exports.StyledPanelTitleHeader, { children: [breadcrumbs ? ((0, jsx_runtime_1.jsx)(Breadcrumbs_1.default, __assign({}, breadcrumbs, { padded: false, margin: 'none', flat: true, responsive: true }))) : icon || iconImage || label || badge ? ((function () {
941
+ (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)(exports.StyledFloatingActions, { className: 'reqore-panel-floating-actions', theme: theme, size: panelSize, intent: intent, flat: flat, ref: floatingActionsRef, onMouseLeave: handleFloatingActionsMouseLeave, children: (0, jsx_runtime_1.jsx)(ControlGroup_1.default, { size: panelSize, gapSize: panelSize, children: floatingActionsList.map(function (action, index) { return renderActions(action, index, true); }) }) }), document.body), hasTitleBar && ((0, jsx_runtime_1.jsxs)(exports.StyledPanelTopBar, { flat: flat, isCollapsed: _isCollapsed, collapsible: collapsible, className: 'reqore-panel-title', onClick: handleCollapseClick, theme: theme, minimal: minimal || opacity === 0, size: contentSize || panelSize, opacity: minimal ? 0 : opacity !== null && opacity !== void 0 ? opacity : 1, noHorizontalPadding: noHorizontalPadding, responsive: responsiveTitle, "$descriptionBelow": descriptionBelow, "$descriptionMaxLines": descriptionIsClamped ? descriptionClamp : 0, "$descriptionFontPx": descriptionFontPx, "data-narrow": isNarrow ? 'true' : 'false', ref: measureRef, padded: padded, wrapperPadding: wrapperPadding, intent: intent, rounded: rounded, radiusSize: rest.radiusSize, stickyHeader: rest.stickyHeader, stickyHeaderOffset: rest.stickyHeaderOffset, stickyHeaderInset: stickyInset, isStuck: isHeaderStuck, children: [hasTitleHeader && ((0, jsx_runtime_1.jsxs)(exports.StyledPanelTitleHeader, { className: 'reqore-panel-title-header', children: [breadcrumbs ? ((0, jsx_runtime_1.jsx)(Breadcrumbs_1.default, __assign({}, breadcrumbs, { padded: false, margin: 'none', flat: true, responsive: true }))) : icon || iconImage || label || badge ? ((function () {
714
942
  var hasPanelIcon = !!icon || !!iconImage || loading;
943
+ // The icon takes the label's place, so there has to BE an icon. Without one
944
+ // the label is the only thing identifying the panel and it stays put — a
945
+ // header with neither is not a compact header, it is an empty one. The label
946
+ // is not lost either way: it is already this icon's tooltip.
947
+ var hideTitleText = hideTitleForIcon && hasPanelIcon;
715
948
  // Layout decision:
716
949
  // - iconWithLabel=true → render the icon INSIDE the
717
950
  // label-and-badge row (no outer icon column). The
@@ -727,7 +960,7 @@ exports.ReqorePanel = (0, react_2.forwardRef)(function (_a, ref) {
727
960
  // the icon in row 1 (label), row 2 (description), or
728
961
  // spans both rows (center). The description always
729
962
  // indents past the icon column.
730
- var inlineWithLabel = hasPanelIcon && (iconWithLabel || !description);
963
+ var inlineWithLabel = hasPanelIcon && (iconWithLabel || !description || hideTitleText);
731
964
  var useOuterGrid = hasPanelIcon && !inlineWithLabel;
732
965
  // Outer grid → grid column-gap handles icon→label
733
966
  // spacing, so the icon itself takes no margin.
@@ -737,11 +970,28 @@ exports.ReqorePanel = (0, react_2.forwardRef)(function (_a, ref) {
737
970
  var panelIcon = hasPanelIcon ? ((0, jsx_runtime_1.jsx)(Icon_1.default, __assign({ size: "".concat(sizes_1.ICON_FROM_HEADER_SIZE[labelSize || sizes_1.HEADER_SIZE_TO_NUMBER[panelSize]], "px"), image: loading ? undefined : iconImage, margin: iconMargin, color: iconColor, tooltip: iconTooltip, effect: {
738
971
  opacity: colors_1.CONTROL_ICON_OPACITY,
739
972
  } }, iconProps, { animation: loading ? 'spin' : iconProps === null || iconProps === void 0 ? void 0 : iconProps.animation, icon: loading ? "Loader".concat(loadingIconType || '', "Line") : icon || (iconProps === null || iconProps === void 0 ? void 0 : iconProps.icon), className: "reqore-panel-title-icon ".concat((iconProps === null || iconProps === void 0 ? void 0 : iconProps.className) || '').trim() }))) : null;
740
- var labelRow = ((0, jsx_runtime_1.jsxs)(exports.StyledPanelTitleHeaderLabelAndBadge, { className: 'reqore-panel-title-label-row', children: [inlineWithLabel && panelIcon, typeof label === 'string' ? ((0, jsx_runtime_1.jsx)(LabelEditor_1.LabelEditor, { size: labelSize || panelSize, customTheme: theme, effect: __assign({ noWrap: true }, labelEffect), style: {
741
- display: 'inline-flex',
742
- alignItems: 'center',
743
- minWidth: 0,
744
- }, label: label, onSubmit: onLabelEdit, tooltip: showLabelTooltip ? customLabelTooltip || label : undefined })) : (label), badge || badge === 0 ? ((0, jsx_runtime_1.jsx)(Button_1.ButtonBadge, { size: (0, utils_1.getOneHigherSize)(panelSize), content: badge, wrapGroup: isSmall, margin: label ? 'left' : 'none' })) : null] }));
973
+ var labelRow = ((0, jsx_runtime_1.jsxs)(exports.StyledPanelTitleHeaderLabelAndBadge, { className: 'reqore-panel-title-label-row', children: [inlineWithLabel && panelIcon, hideTitleText ? null : typeof label === 'string' ? (
974
+ // The measured box is this wrapper, not the heading: as a
975
+ // `min-width: 0` flex child it reports the width the row actually
976
+ // left for the title, where the heading would report what the text
977
+ // wants. `overflow: hidden` is what makes it shrinkable at all.
978
+ // `display: flex` keeps the wrapper from opening a line box around
979
+ // the inline-flex heading: a block wrapper adds the row's leading on
980
+ // top of the heading's own box, which made a `tiny` panel 3px taller
981
+ // than it was before this wrapper existed.
982
+ (0, jsx_runtime_1.jsx)(StyledPanelTitleLabelBox, { ref: labelFitRef, className: 'reqore-panel-title-label-box', "$clampLines": clampLines, children: (0, jsx_runtime_1.jsx)(LabelEditor_1.LabelEditor, { size: labelSize || panelSize, customTheme: theme, effect: __assign({
983
+ // `noWrap` pins the heading to one line; a clamped title is
984
+ // allowed to wrap, and the clamp brings its own ellipsis.
985
+ noWrap: clampLines === 1 }, labelEffect), style: __assign(__assign(__assign({}, (clampLines > 1
986
+ ? {}
987
+ : { display: 'inline-flex', alignItems: 'center' })), { minWidth: 0,
988
+ // Capped to the measured wrapper so the heading's own
989
+ // `text-overflow: ellipsis` (from `noWrap`) has a box to overflow.
990
+ // An `inline-flex` heading otherwise sizes to its text, and the
991
+ // wrapper clips it mid-word with no ellipsis at all.
992
+ maxWidth: '100%' }), (fitLabel !== false && !(labelEffect === null || labelEffect === void 0 ? void 0 : labelEffect.textSize)
993
+ ? { fontSize: "".concat(labelFitPx, "px") }
994
+ : {})), label: label, onSubmit: onLabelEdit, tooltip: showLabelTooltip ? customLabelTooltip || label : undefined }) })) : (label), badge || badge === 0 ? ((0, jsx_runtime_1.jsx)(Button_1.ButtonBadge, { size: (0, utils_1.getOneHigherSize)(panelSize), content: badge, wrapGroup: isSmall, margin: label ? 'left' : 'none' })) : null] }));
745
995
  // Description size is driven by the panel size only —
746
996
  // explicitly NOT by `labelSize`. `NUMBER_TO_SIZE` maps
747
997
  // 1..6 → micro..huge, which means bumping `labelSize`
@@ -750,9 +1000,55 @@ exports.ReqorePanel = (0, react_2.forwardRef)(function (_a, ref) {
750
1000
  // pairing: a bigger label should not make supporting
751
1001
  // text smaller. Consumers that want to size the
752
1002
  // description explicitly pass `descriptionEffect.textSize`.
753
- var descriptionRow = description ? ((0, jsx_runtime_1.jsx)(Span_1.ReqoreSpan, { className: 'reqore-panel-title-description', size: panelSize, effect: __assign({ opacity: 0.7 }, descriptionEffect), intent: descriptionIntent, children: description })) : null;
754
- return ((0, jsx_runtime_1.jsx)(exports.StyledPanelTitleHeaderContent, __assign({ size: panelSize }, labelProps, { hasLabel: !!label, hasIcon: useOuterGrid, iconSize: sizes_1.ICON_FROM_HEADER_SIZE[labelSize || sizes_1.HEADER_SIZE_TO_NUMBER[panelSize]], "$hasOuterIcon": useOuterGrid, "$iconVerticalAlign": iconVerticalAlign, "$hasDescription": !!description, children: useOuterGrid ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [panelIcon, labelRow, descriptionRow] })) : ((0, jsx_runtime_1.jsxs)(exports.StyledPanelTitleHeaderLabelAndDescription, { children: [labelRow, descriptionRow] })) })));
755
- })()) : null, breadcrumbs && (badge || badge === 0) ? ((0, jsx_runtime_1.jsx)(Button_1.ButtonBadge, { size: (0, utils_1.getOneHigherSize)(panelSize), content: badge, wrapGroup: isSmall, margin: label ? 'left' : 'none' })) : null, (0, jsx_runtime_1.jsx)(NonResponsiveActions_1.ReqorePanelNonResponsiveActions, { show: isSmall && (!!onClose || collapsible), isSmall: isSmall, showControlButtons: true, size: panelSize, hasResponsiveActions: hasResponsiveActions(nonFloatingActions), customTheme: theme, isCollapsed: _isCollapsed, onCollapseClick: collapsible ? handleCollapseClick : undefined, onCloseClick: onClose, closeButtonProps: closeButtonProps, collapseButtonProps: collapseButtonProps, collapseTooltip: collapseTooltip, expandTooltip: expandTooltip, closeTooltip: closeTooltip, fluid: false, style: { marginLeft: 'auto' } })] })), hasResponsiveActions(nonFloatingActions) && ((0, jsx_runtime_1.jsx)(ControlGroup_1.default, __assign({ responsive: responsiveActions, fluid: responsiveActions || isSmall, horizontalAlign: 'flex-end', customTheme: theme, size: panelSize }, responsiveActionsWrapperProps, { children: nonFloatingActions.map(renderResponsiveActions()) }))), (0, jsx_runtime_1.jsx)(NonResponsiveActions_1.ReqorePanelNonResponsiveActions, { show: showNonResponsiveGroup(), isSmall: isSmall, showControlButtons: !isSmall, size: panelSize, hasResponsiveActions: hasResponsiveActions(nonFloatingActions), customTheme: theme, isCollapsed: _isCollapsed, onCollapseClick: collapsible ? handleCollapseClick : undefined, onCloseClick: onClose, closeButtonProps: closeButtonProps, collapseButtonProps: collapseButtonProps, collapseTooltip: collapseTooltip, expandTooltip: expandTooltip, closeTooltip: closeTooltip, fluid: !hasTitleHeader || isSmall, children: nonFloatingActions.map(renderNonResponsiveActions()) })] })), !_isCollapsed || (_isCollapsed && !unMountContentOnCollapse) ? ((0, jsx_runtime_1.jsx)(exports.StyledPanelContent, { as: 'div', className: 'reqore-panel-content', hasLabel: !!hasTitleBar, hasBottomActions: hasBottomActions, isCollapsed: _isCollapsed, style: contentStyle, padded: padded, minimal: minimal || opacity === 0, size: contentSize || panelSize, ref: getContentRef, noHorizontalPadding: noHorizontalPadding, children: children })) : null, hasBottomActions && !_isCollapsed ? ((0, jsx_runtime_1.jsxs)(exports.StyledPanelBottomActions, { flat: flat, className: 'reqore-panel-bottom-actions', theme: theme, padded: padded, intent: intent, minimal: minimal || opacity === 0, opacity: minimal ? 0 : opacity !== null && opacity !== void 0 ? opacity : 1, size: contentSize || panelSize, noHorizontalPadding: noHorizontalPadding, children: [hasNonResponsiveActions(leftBottomActions) ? ((0, jsx_runtime_1.jsx)(ControlGroup_1.default, { size: panelSize, style: { marginRight: 'auto' }, children: leftBottomActions.map(renderNonResponsiveActions('flex-start')) })) : null, hasResponsiveActions(leftBottomActions) && ((0, jsx_runtime_1.jsx)(ControlGroup_1.default, { fluid: responsiveActions, responsive: responsiveActions, customTheme: theme, size: panelSize, style: { marginRight: 'auto' }, children: leftBottomActions.map(renderResponsiveActions('flex-start')) })), hasResponsiveActions(rightBottomActions) && ((0, jsx_runtime_1.jsx)(ControlGroup_1.default, { fluid: responsiveActions, horizontalAlign: 'flex-end', responsive: responsiveActions, customTheme: theme, style: { marginLeft: 'auto' }, size: panelSize, children: rightBottomActions.map(renderResponsiveActions()) })), hasNonResponsiveActions(rightBottomActions) ? ((0, jsx_runtime_1.jsx)(ControlGroup_1.default, { horizontalAlign: 'flex-end', size: panelSize, style: { marginLeft: 'auto' }, children: rightBottomActions.map(renderNonResponsiveActions()) })) : null] })) : null] })) })));
1003
+ var descriptionRow = description && !hideTitleText && !descriptionBelow ? ((0, jsx_runtime_1.jsx)(Span_1.ReqoreSpan, __assign({}, descriptionProps, { children: description }))) : null;
1004
+ return ((0, jsx_runtime_1.jsx)(exports.StyledPanelTitleHeaderContent, __assign({ size: panelSize }, labelProps, { hasLabel: !!label && !hideTitleText, hasIcon: useOuterGrid, iconSize: sizes_1.ICON_FROM_HEADER_SIZE[labelSize || sizes_1.HEADER_SIZE_TO_NUMBER[panelSize]], "$hasOuterIcon": useOuterGrid, "$iconVerticalAlign": iconVerticalAlign, "$hasDescription": !!description && !hideTitleText, children: useOuterGrid ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [panelIcon, labelRow, descriptionRow] })) : ((0, jsx_runtime_1.jsxs)(exports.StyledPanelTitleHeaderLabelAndDescription, { children: [labelRow, descriptionRow] })) })));
1005
+ })()) : null, breadcrumbs && (badge || badge === 0) ? ((0, jsx_runtime_1.jsx)(Button_1.ButtonBadge, { size: (0, utils_1.getOneHigherSize)(panelSize), content: badge, wrapGroup: isSmall, margin: label ? 'left' : 'none' })) : null, (0, jsx_runtime_1.jsx)(NonResponsiveActions_1.ReqorePanelNonResponsiveActions
1006
+ // The narrow bar keeps its controls in the trailing group, so this row —
1007
+ // which existed only for the stacked layout — never shows.
1008
+ , {
1009
+ // The narrow bar keeps its controls in the trailing group, so this row —
1010
+ // which existed only for the stacked layout — never shows.
1011
+ show: false, isSmall: false, showControlButtons: true, size: panelSize, hasResponsiveActions: hasResponsiveActions(nonFloatingActions), customTheme: theme, isCollapsed: _isCollapsed, onCollapseClick: collapsible ? handleCollapseClick : undefined, onCloseClick: onClose, closeButtonProps: closeButtonProps, collapseButtonProps: collapseButtonProps, collapseTooltip: collapseTooltip, expandTooltip: expandTooltip, closeTooltip: closeTooltip, fluid: false, style: { marginLeft: 'auto' } })] })), hasResponsiveActions(nonFloatingActions) && ((0, jsx_runtime_1.jsx)(ControlGroup_1.default, __assign({ responsive: responsiveActions,
1012
+ // Not fluid by default. `fluid` emits `width: 100%`, so the group's flex basis
1013
+ // becomes the whole bar and the title — the only shrinkable thing on the other
1014
+ // side — collapses to nothing: measured at 0px of title on a 400px panel, and
1015
+ // 142px of a 518px bar where the buttons needed 90.
1016
+ //
1017
+ // A caller whose actions include something with no useful width of its own —
1018
+ // Collection puts a search input in here — opts back in through
1019
+ // `responsiveActionsWrapperProps`, because `fluid` is also what ControlGroup
1020
+ // propagates to its children, and that input has nothing to fill without it.
1021
+ fluid: false, horizontalAlign: 'flex-end', customTheme: theme, size: panelSize }, responsiveActionsWrapperProps, {
1022
+ // The cap is the whole fix. Half the bar guarantees the title the other half,
1023
+ // and the moment the buttons need more than their share the group overflows —
1024
+ // which is what `responsive` collapse watches (`scrollWidth > clientWidth`), so
1025
+ // the fold into the `…` menu still fires. Floored at 40px because shrinking to
1026
+ // nothing clips the buttons rather than folding them, and ControlGroup ignores
1027
+ // its own overflow below that width, which would strand them clipped.
1028
+ style: __assign({
1029
+ // Pushed to the trailing edge. A `fluid` group used to span the bar and its
1030
+ // own `horizontalAlign` put the buttons on the right; a content-sized one is
1031
+ // only as wide as its buttons, so with no title header beside it — Tree has
1032
+ // no label — it would sit at the LEFT of an otherwise empty bar. `auto`
1033
+ // margin restores the edge without giving the group any width back.
1034
+ marginLeft: 'auto',
1035
+ // Content basis that may still shrink. `fluid={false}` alone compiles to
1036
+ // `flex: 0 0 auto`, which pins the group at its content width so it can never
1037
+ // overflow — and `responsive` collapse watches `scrollWidth > clientWidth`,
1038
+ // so the fold into the `…` menu would simply stop happening.
1039
+ flex: '0 1 auto',
1040
+ // Floored, because shrinking to nothing clips the buttons instead of folding
1041
+ // them, and ControlGroup ignores its own overflow below 40px.
1042
+ minWidth: 40,
1043
+ // Capped, so a group that IS opted back into growing cannot take the row —
1044
+ // but only while there is a title header to take it FROM. With no label,
1045
+ // badge, icon or breadcrumbs the bar is the group's alone, and holding a
1046
+ // Collection's search input to half of an empty bar guards nothing.
1047
+ maxWidth: hasTitleHeader ? '50%' : undefined }, responsiveActionsWrapperProps === null || responsiveActionsWrapperProps === void 0 ? void 0 : responsiveActionsWrapperProps.style), children: nonFloatingActions.map(renderResponsiveActions()) }))), (0, jsx_runtime_1.jsx)(NonResponsiveActions_1.ReqorePanelNonResponsiveActions, { show: showNonResponsiveGroup(), isSmall: false, showControlButtons: true, size: panelSize, hasResponsiveActions: hasResponsiveActions(nonFloatingActions), customTheme: theme, isCollapsed: _isCollapsed, onCollapseClick: collapsible ? handleCollapseClick : undefined, onCloseClick: onClose, closeButtonProps: closeButtonProps, collapseButtonProps: collapseButtonProps, collapseTooltip: collapseTooltip, expandTooltip: expandTooltip, closeTooltip: closeTooltip, fluid: !hasTitleHeader, children: nonFloatingActions.map(renderNonResponsiveActions()) }), descriptionBelow ? (
1048
+ // `flex-basis: 100%` is what puts it on its own line — the bar is a wrapping
1049
+ // flex row, so a full-width item cannot share one with anything before it.
1050
+ // `min-width: 0` so a long sentence wraps inside the bar instead of widening it.
1051
+ (0, jsx_runtime_1.jsx)("div", { className: 'reqore-panel-title-description-row', style: { flex: '0 0 100%', minWidth: 0 }, children: (0, jsx_runtime_1.jsx)(Span_1.ReqoreSpan, __assign({}, descriptionProps, { children: description })) })) : null] })), !_isCollapsed || (_isCollapsed && !unMountContentOnCollapse) ? ((0, jsx_runtime_1.jsx)(exports.StyledPanelContent, { as: 'div', className: 'reqore-panel-content', hasLabel: !!hasTitleBar, hasBottomActions: hasBottomActions, isCollapsed: _isCollapsed, style: contentStyle, padded: padded, minimal: minimal || opacity === 0, size: contentSize || panelSize, ref: getContentRef, noHorizontalPadding: noHorizontalPadding, children: children })) : null, hasBottomActions && !_isCollapsed ? ((0, jsx_runtime_1.jsxs)(exports.StyledPanelBottomActions, { flat: flat, className: 'reqore-panel-bottom-actions', theme: theme, padded: padded, intent: intent, minimal: minimal || opacity === 0, opacity: minimal ? 0 : opacity !== null && opacity !== void 0 ? opacity : 1, size: contentSize || panelSize, noHorizontalPadding: noHorizontalPadding, children: [hasNonResponsiveActions(leftBottomActions) ? ((0, jsx_runtime_1.jsx)(ControlGroup_1.default, { size: panelSize, style: { marginRight: 'auto' }, children: leftBottomActions.map(renderNonResponsiveActions('flex-start')) })) : null, hasResponsiveActions(leftBottomActions) && ((0, jsx_runtime_1.jsx)(ControlGroup_1.default, { fluid: responsiveActions, responsive: responsiveActions, customTheme: theme, size: panelSize, style: { marginRight: 'auto' }, children: leftBottomActions.map(renderResponsiveActions('flex-start')) })), hasResponsiveActions(rightBottomActions) && ((0, jsx_runtime_1.jsx)(ControlGroup_1.default, { fluid: responsiveActions, horizontalAlign: 'flex-end', responsive: responsiveActions, customTheme: theme, style: { marginLeft: 'auto' }, size: panelSize, children: rightBottomActions.map(renderResponsiveActions()) })), hasNonResponsiveActions(rightBottomActions) ? ((0, jsx_runtime_1.jsx)(ControlGroup_1.default, { horizontalAlign: 'flex-end', size: panelSize, style: { marginLeft: 'auto' }, children: rightBottomActions.map(renderNonResponsiveActions()) })) : null] })) : null] })) })));
756
1052
  });
757
- var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10, templateObject_11, templateObject_12, templateObject_13, templateObject_14, templateObject_15, templateObject_16, templateObject_17, templateObject_18, templateObject_19, templateObject_20, templateObject_21, templateObject_22, templateObject_23, templateObject_24, templateObject_25;
1053
+ var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10, templateObject_11, templateObject_12, templateObject_13, templateObject_14, templateObject_15, templateObject_16, templateObject_17, templateObject_18, templateObject_19, templateObject_20, templateObject_21, templateObject_22, templateObject_23, templateObject_24, templateObject_25, templateObject_26, templateObject_27, templateObject_28, templateObject_29, templateObject_30;
758
1054
  //# sourceMappingURL=index.js.map