react-ui-suite 1.1.3 → 1.1.5

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.
@@ -1,12 +1,30 @@
1
- .rui-tab-group {
2
- display: flex;
3
- width: 100%;
4
- height: 100%;
5
- --rui-tab-border: 1px;
6
- --rui-tab-panel-radius: 15px;
7
- --rui-tab-radius: 10px;
8
- --rui-tab-min-main: 32px;
9
- }
1
+ .rui-tab-group {
2
+ display: flex;
3
+ width: 100%;
4
+ height: 100%;
5
+ position: relative;
6
+ --rui-tab-border: 1px;
7
+ --rui-tab-panel-radius: 15px;
8
+ --rui-tab-radius: 10px;
9
+ --rui-tab-min-main: 32px;
10
+ }
11
+
12
+ .rui-tab-group__measure {
13
+ position: fixed;
14
+ left: 0;
15
+ top: 0;
16
+ visibility: hidden;
17
+ pointer-events: none;
18
+ z-index: -1;
19
+ display: inline-flex;
20
+ gap: 0;
21
+ }
22
+
23
+ .rui-tab-group__measure .rui-tab-group__tab {
24
+ flex: 0 0 auto !important;
25
+ width: auto !important;
26
+ height: auto !important;
27
+ }
10
28
 
11
29
  .rui-tab-group[data-position="top"],
12
30
  .rui-tab-group[data-position="bottom"] {
@@ -70,20 +88,21 @@
70
88
  justify-content: flex-end;
71
89
  }
72
90
 
73
- .rui-tab-group__tab {
74
- border: var(--rui-tab-border) solid var(--rui-color-border);
75
- background-color: var(--rui-color-surface-muted);
76
- position: relative;
91
+ .rui-tab-group__tab {
92
+ border: var(--rui-tab-border) solid var(--rui-color-border);
93
+ background-color: var(--rui-color-surface-muted);
94
+ position: relative;
77
95
  padding: 5px;
78
96
  font-weight: 500;
79
97
  display: inline-flex;
80
98
  align-items: center;
81
99
  justify-content: center;
82
100
  transform: none;
83
- min-width: 0;
84
- min-height: 0;
85
- flex: 0 0 auto;
86
- }
101
+ min-width: 0;
102
+ min-height: 0;
103
+ flex: 0 0 auto;
104
+ overflow: hidden;
105
+ }
87
106
 
88
107
  .rui-tab-group__scroll {
89
108
  border: var(--rui-tab-border) solid var(--rui-color-border);
@@ -108,12 +127,19 @@
108
127
  line-height: 1;
109
128
  }
110
129
 
111
- .rui-tab-group__label {
112
- display: inline-flex;
113
- align-items: center;
114
- justify-content: center;
115
- line-height: 1;
116
- }
130
+ .rui-tab-group__label {
131
+ display: inline-flex;
132
+ align-items: center;
133
+ justify-content: center;
134
+ line-height: 1;
135
+ white-space: normal;
136
+ overflow: hidden;
137
+ overflow-wrap: normal;
138
+ word-break: normal;
139
+ hyphens: none;
140
+ max-width: 100%;
141
+ max-height: 100%;
142
+ }
117
143
 
118
144
  .rui-tab-group__tab.is-active {
119
145
  background-color: var(--rui-color-surface);
@@ -205,10 +231,10 @@
205
231
  border-bottom-right-radius: var(--rui-tab-radius);
206
232
  }
207
233
 
208
- .rui-tab-group[data-rotation="vertical"] .rui-tab-group__label {
209
- writing-mode: vertical-rl;
210
- text-orientation: mixed;
211
- }
234
+ .rui-tab-group[data-rotation="vertical"] .rui-tab-group__label {
235
+ writing-mode: vertical-rl;
236
+ text-orientation: mixed;
237
+ }
212
238
 
213
239
  .rui-tab-group[data-position="top"][data-rotation="vertical"] .rui-tab-group__label {
214
240
  transform: rotate(180deg);
package/dist/index.d.ts CHANGED
@@ -197,13 +197,22 @@ type DropdownProps = {
197
197
  declare const Dropdown: React.ForwardRefExoticComponent<DropdownProps & React.RefAttributes<HTMLDivElement>>;
198
198
 
199
199
  type NativeInputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "type">;
200
+ type FilePickerMode = "path" | "content" | "both";
201
+ type FileSelection = {
202
+ file: File;
203
+ path?: string;
204
+ text?: string;
205
+ bytes?: Uint8Array;
206
+ };
200
207
  type FilePickerProps = NativeInputProps & {
201
208
  label?: string;
202
209
  description?: string;
203
210
  error?: string;
204
211
  dropzoneLabel?: string;
205
212
  maxFiles?: number;
206
- onFilesChange?: (files: File[]) => void;
213
+ mode?: FilePickerMode;
214
+ resolvePath?: (file: File) => string | undefined | Promise<string | undefined>;
215
+ onFilesChange?: (files: FileSelection[]) => void;
207
216
  };
208
217
  declare const FilePicker: React.ForwardRefExoticComponent<NativeInputProps & {
209
218
  label?: string;
@@ -211,7 +220,9 @@ declare const FilePicker: React.ForwardRefExoticComponent<NativeInputProps & {
211
220
  error?: string;
212
221
  dropzoneLabel?: string;
213
222
  maxFiles?: number;
214
- onFilesChange?: (files: File[]) => void;
223
+ mode?: FilePickerMode;
224
+ resolvePath?: (file: File) => string | undefined | Promise<string | undefined>;
225
+ onFilesChange?: (files: FileSelection[]) => void;
215
226
  } & React.RefAttributes<HTMLInputElement>>;
216
227
 
217
228
  type InputFieldProps = React.InputHTMLAttributes<HTMLInputElement> & {
@@ -530,4 +541,4 @@ declare const Toggle: React.ForwardRefExoticComponent<Omit<React.ButtonHTMLAttri
530
541
  onChange?: (checked: boolean) => void;
531
542
  } & React.RefAttributes<HTMLButtonElement>>;
532
543
 
533
- export { Alert, type AlertProps, type AlertVariant, Badge, type BadgeProps, type BadgeVariant, Button, type ButtonProps, Card, type CardProps, Checkbox, type CheckboxProps, ColorPicker, type ColorPickerProps, Combobox, type ComboboxOption, type ComboboxProps, type ComboboxRenderState, DatalistInput, type DatalistInputProps, DatePicker, type DatePickerProps, Dialog, type DialogProps, Disclosure, type DisclosureProps, Dropdown, type DropdownProps, FilePicker, type FilePickerProps, InputField, type InputFieldProps, Meter, type MeterProps, NumberInput, type NumberInputProps, OutputChip, type OutputChipProps, Popover, type PopoverProps, Progress, type ProgressProps, Radio, type RadioColor, type RadioProps, ResizableContainer, type ResizableContainerProps, Select, type SelectOption, type SelectProps, Slider, type SliderProps, StackedList, type StackedListItem, type StackedListProps, TabGroup, TabGroupAlign, TabGroupFill, TabGroupPosition, type TabGroupProps, TabGroupRotation, type TabGroupTab, Table, type TableColumn, type TableProps, Textarea, type TextareaProps, Toggle, type ToggleProps };
544
+ export { Alert, type AlertProps, type AlertVariant, Badge, type BadgeProps, type BadgeVariant, Button, type ButtonProps, Card, type CardProps, Checkbox, type CheckboxProps, ColorPicker, type ColorPickerProps, Combobox, type ComboboxOption, type ComboboxProps, type ComboboxRenderState, DatalistInput, type DatalistInputProps, DatePicker, type DatePickerProps, Dialog, type DialogProps, Disclosure, type DisclosureProps, Dropdown, type DropdownProps, FilePicker, type FilePickerMode, type FilePickerProps, type FileSelection, InputField, type InputFieldProps, Meter, type MeterProps, NumberInput, type NumberInputProps, OutputChip, type OutputChipProps, Popover, type PopoverProps, Progress, type ProgressProps, Radio, type RadioColor, type RadioProps, ResizableContainer, type ResizableContainerProps, Select, type SelectOption, type SelectProps, Slider, type SliderProps, StackedList, type StackedListItem, type StackedListProps, TabGroup, TabGroupAlign, TabGroupFill, TabGroupPosition, type TabGroupProps, TabGroupRotation, type TabGroupTab, Table, type TableColumn, type TableProps, Textarea, type TextareaProps, Toggle, type ToggleProps };
package/dist/index.js CHANGED
@@ -1016,7 +1016,16 @@ var Dropdown = React6.forwardRef(
1016
1016
  ref: chevronRef,
1017
1017
  type: "button",
1018
1018
  "aria-label": isOpen ? "Close" : "Open",
1019
- onClick: onChevronClick,
1019
+ onPointerDown: (event) => {
1020
+ if (!onChevronClick) return;
1021
+ if (event.button !== 0) return;
1022
+ event.preventDefault();
1023
+ onChevronClick();
1024
+ },
1025
+ onClick: (event) => {
1026
+ if (!onChevronClick || event.detail !== 0) return;
1027
+ onChevronClick();
1028
+ },
1020
1029
  className: buttonClasses,
1021
1030
  disabled: !!disabled,
1022
1031
  children: /* @__PURE__ */ jsx8(
@@ -1635,10 +1644,7 @@ function InnerCombobox({
1635
1644
  openList();
1636
1645
  return;
1637
1646
  }
1638
- requestAnimationFrame(() => {
1639
- var _a2;
1640
- return (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
1641
- });
1647
+ setOpen(false);
1642
1648
  },
1643
1649
  children: isEffectivelyOpen && /* @__PURE__ */ jsx11(
1644
1650
  Popover,
@@ -2820,12 +2826,55 @@ function formatBytes(bytes) {
2820
2826
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
2821
2827
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
2822
2828
  }
2829
+ function decodeUtf8IfPossible(bytes) {
2830
+ try {
2831
+ const decoder = new TextDecoder("utf-8", { fatal: true });
2832
+ return decoder.decode(bytes);
2833
+ } catch {
2834
+ return void 0;
2835
+ }
2836
+ }
2837
+ async function derivePath(file, resolvePath) {
2838
+ const resolved = await (resolvePath == null ? void 0 : resolvePath(file));
2839
+ if (resolved) return resolved;
2840
+ const fileWithPath = file;
2841
+ if (typeof fileWithPath.path === "string" && fileWithPath.path.length > 0) {
2842
+ return fileWithPath.path;
2843
+ }
2844
+ if (typeof fileWithPath.webkitRelativePath === "string" && fileWithPath.webkitRelativePath.length > 0) {
2845
+ return fileWithPath.webkitRelativePath;
2846
+ }
2847
+ return void 0;
2848
+ }
2849
+ async function readFileBytes(file) {
2850
+ const fileWithArrayBuffer = file;
2851
+ if (typeof fileWithArrayBuffer.arrayBuffer === "function") {
2852
+ return new Uint8Array(await fileWithArrayBuffer.arrayBuffer());
2853
+ }
2854
+ if (typeof Blob !== "undefined" && typeof Blob.prototype.arrayBuffer === "function") {
2855
+ return new Uint8Array(await Blob.prototype.arrayBuffer.call(file));
2856
+ }
2857
+ if (typeof FileReader !== "undefined") {
2858
+ return await new Promise((resolve) => {
2859
+ const reader = new FileReader();
2860
+ reader.onload = () => {
2861
+ const result = reader.result;
2862
+ resolve(result instanceof ArrayBuffer ? new Uint8Array(result) : void 0);
2863
+ };
2864
+ reader.onerror = () => resolve(void 0);
2865
+ reader.readAsArrayBuffer(file);
2866
+ });
2867
+ }
2868
+ return void 0;
2869
+ }
2823
2870
  var FilePicker = React15.forwardRef(function FilePicker2({
2824
2871
  label,
2825
2872
  description,
2826
2873
  error,
2827
2874
  dropzoneLabel = "Drop files here or click to browse",
2828
2875
  maxFiles,
2876
+ mode = "path",
2877
+ resolvePath,
2829
2878
  id,
2830
2879
  className,
2831
2880
  accept,
@@ -2843,6 +2892,7 @@ var FilePicker = React15.forwardRef(function FilePicker2({
2843
2892
  const [selectedFiles, setSelectedFiles] = React15.useState([]);
2844
2893
  const [restrictedCount, setRestrictedCount] = React15.useState(0);
2845
2894
  const inputRef = React15.useRef(null);
2895
+ const selectionRequestIdRef = React15.useRef(0);
2846
2896
  const setRefs = React15.useCallback(
2847
2897
  (node) => {
2848
2898
  inputRef.current = node;
@@ -2861,22 +2911,43 @@ var FilePicker = React15.forwardRef(function FilePicker2({
2861
2911
  return Math.max(1, Math.floor(maxFiles));
2862
2912
  }, [maxFiles]);
2863
2913
  const applySelectedFiles = React15.useCallback(
2864
- (files) => {
2914
+ async (files) => {
2865
2915
  const acceptedFiles = filterFilesByAccept(files, accept);
2866
2916
  const selectionLimit = multiple ? resolvedMaxFiles != null ? resolvedMaxFiles : Infinity : 1;
2867
2917
  const nextFiles = acceptedFiles.slice(0, selectionLimit);
2868
2918
  const nextRestrictedCount = files.length - nextFiles.length;
2869
- setSelectedFiles(nextFiles);
2919
+ const requestId = selectionRequestIdRef.current + 1;
2920
+ selectionRequestIdRef.current = requestId;
2921
+ const nextSelections = await Promise.all(
2922
+ nextFiles.map(async (file) => {
2923
+ const selection = { file };
2924
+ if (mode === "path" || mode === "both") {
2925
+ selection.path = await derivePath(file, resolvePath);
2926
+ }
2927
+ if (mode === "content" || mode === "both") {
2928
+ const bytes = await readFileBytes(file);
2929
+ if (bytes) {
2930
+ selection.bytes = bytes;
2931
+ selection.text = decodeUtf8IfPossible(bytes);
2932
+ }
2933
+ }
2934
+ return selection;
2935
+ })
2936
+ );
2937
+ if (selectionRequestIdRef.current !== requestId) {
2938
+ return [];
2939
+ }
2940
+ setSelectedFiles(nextSelections);
2870
2941
  setRestrictedCount(nextRestrictedCount);
2871
- onFilesChange == null ? void 0 : onFilesChange(nextFiles);
2872
- return nextFiles;
2942
+ onFilesChange == null ? void 0 : onFilesChange(nextSelections);
2943
+ return nextSelections;
2873
2944
  },
2874
- [accept, multiple, onFilesChange, resolvedMaxFiles]
2945
+ [accept, mode, multiple, onFilesChange, resolvePath, resolvedMaxFiles]
2875
2946
  );
2876
2947
  const handleInputChange = (event) => {
2877
2948
  var _a;
2878
2949
  const incomingFiles = Array.from((_a = event.target.files) != null ? _a : []);
2879
- applySelectedFiles(incomingFiles);
2950
+ void applySelectedFiles(incomingFiles);
2880
2951
  onChange == null ? void 0 : onChange(event);
2881
2952
  };
2882
2953
  const openFileDialog = () => {
@@ -2892,7 +2963,7 @@ var FilePicker = React15.forwardRef(function FilePicker2({
2892
2963
  if (disabled) return;
2893
2964
  setIsDragActive(false);
2894
2965
  const files = Array.from((_a = event.dataTransfer.files) != null ? _a : []);
2895
- applySelectedFiles(files);
2966
+ void applySelectedFiles(files);
2896
2967
  };
2897
2968
  const hasSelection = selectedFiles.length > 0;
2898
2969
  return /* @__PURE__ */ jsxs15("div", { className: "rui-file-picker rui-root", children: [
@@ -2954,10 +3025,17 @@ var FilePicker = React15.forwardRef(function FilePicker2({
2954
3025
  "Maximum files: ",
2955
3026
  resolvedMaxFiles
2956
3027
  ] }) : null,
2957
- hasSelection ? /* @__PURE__ */ jsx17("ul", { className: "rui-file-picker__list", "aria-label": "Selected files", children: selectedFiles.map((file) => /* @__PURE__ */ jsxs15("li", { className: "rui-file-picker__item", children: [
2958
- /* @__PURE__ */ jsx17("span", { className: "rui-file-picker__file-name rui-text-wrap", children: file.name }),
2959
- /* @__PURE__ */ jsx17("span", { className: "rui-file-picker__file-meta", children: formatBytes(file.size) })
2960
- ] }, `${file.name}-${file.size}-${file.lastModified}`)) }) : null
3028
+ hasSelection ? /* @__PURE__ */ jsx17("ul", { className: "rui-file-picker__list", "aria-label": "Selected files", children: selectedFiles.map((selection) => /* @__PURE__ */ jsxs15(
3029
+ "li",
3030
+ {
3031
+ className: "rui-file-picker__item",
3032
+ children: [
3033
+ /* @__PURE__ */ jsx17("span", { className: "rui-file-picker__file-name rui-text-wrap", children: selection.file.name }),
3034
+ /* @__PURE__ */ jsx17("span", { className: "rui-file-picker__file-meta", children: formatBytes(selection.file.size) })
3035
+ ]
3036
+ },
3037
+ `${selection.file.name}-${selection.file.size}-${selection.file.lastModified}`
3038
+ )) }) : null
2961
3039
  ]
2962
3040
  }
2963
3041
  ),
@@ -3788,7 +3866,7 @@ function StackedList({ items, dense, className, ...rest }) {
3788
3866
 
3789
3867
  // components/TabGroup/TabGroup.tsx
3790
3868
  import React21 from "react";
3791
- import "./TabGroup-CV2AC3EO.css";
3869
+ import "./TabGroup-3NH74LET.css";
3792
3870
  import { Fragment as Fragment2, jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
3793
3871
  function TabGroup({
3794
3872
  align = "start",
@@ -3804,11 +3882,16 @@ function TabGroup({
3804
3882
  var _a, _b;
3805
3883
  const rootRef = React21.useRef(null);
3806
3884
  const tabStripRef = React21.useRef(null);
3885
+ const measureRef = React21.useRef(null);
3807
3886
  const idBase = React21.useId();
3808
3887
  const [effectiveFill, setEffectiveFill] = React21.useState(fill);
3809
3888
  const [availableMain, setAvailableMain] = React21.useState(0);
3810
- const [minMain, setMinMain] = React21.useState(32);
3889
+ const [cssMinMain, setCssMinMain] = React21.useState(32);
3890
+ const [contentMinMain, setContentMinMain] = React21.useState(0);
3811
3891
  const count = tabs.length;
3892
+ const isVertical = position === "left" || position === "right";
3893
+ const minMain = Math.max(cssMinMain, contentMinMain);
3894
+ const partialMainSize = Math.max(Number.isFinite(size) ? size : 0, minMain);
3812
3895
  const clampIndex = React21.useCallback(
3813
3896
  (i) => {
3814
3897
  if (count <= 0) {
@@ -3851,14 +3934,16 @@ function TabGroup({
3851
3934
  const radius = parseFloat(computed.getPropertyValue("--rui-tab-panel-radius")) || 0;
3852
3935
  const border = parseFloat(computed.getPropertyValue("--rui-tab-border")) || 0;
3853
3936
  const minMainValue = parseFloat(computed.getPropertyValue("--rui-tab-min-main")) || 32;
3937
+ const effectiveMinMain = Math.max(minMainValue, contentMinMain);
3854
3938
  const wiggle = border * 2 + 1;
3855
3939
  const available = position === "top" || position === "bottom" ? rect.width : rect.height;
3856
- const required = (size != null ? size : 0) * tabs.length;
3857
- const slots2 = minMainValue > 0 ? Math.floor(available / minMainValue) : tabs.length;
3940
+ const requiredPerTab = Math.max(size != null ? size : 0, effectiveMinMain);
3941
+ const required = requiredPerTab * tabs.length;
3942
+ const slots2 = effectiveMinMain > 0 ? Math.floor(available / effectiveMinMain) : tabs.length;
3858
3943
  const hasOverflowControls = slots2 < tabs.length;
3859
3944
  const shouldFill = available - 2 * radius - wiggle <= required;
3860
3945
  setEffectiveFill(shouldFill || hasOverflowControls ? "full" : "partial");
3861
- }, [fill, position, size, tabs.length]);
3946
+ }, [contentMinMain, fill, position, size, tabs.length]);
3862
3947
  React21.useLayoutEffect(() => {
3863
3948
  if (fill === "full") {
3864
3949
  setEffectiveFill("full");
@@ -3873,14 +3958,43 @@ function TabGroup({
3873
3958
  observer.observe(node);
3874
3959
  return () => observer.disconnect();
3875
3960
  }, [fill, updateEffectiveFill]);
3876
- const isVertical = position === "left" || position === "right";
3877
3961
  React21.useLayoutEffect(() => {
3878
3962
  const root = rootRef.current;
3879
3963
  if (!root) return;
3880
3964
  const computed = getComputedStyle(root);
3881
3965
  const cssMin = parseFloat(computed.getPropertyValue("--rui-tab-min-main"));
3882
- setMinMain(Number.isFinite(cssMin) && cssMin > 0 ? cssMin : 32);
3966
+ setCssMinMain(Number.isFinite(cssMin) && cssMin > 0 ? cssMin : 32);
3883
3967
  }, [position]);
3968
+ React21.useLayoutEffect(() => {
3969
+ const node = measureRef.current;
3970
+ if (!node) return;
3971
+ const measure = () => {
3972
+ const sampleTab = node.querySelector(".rui-tab-group__tab");
3973
+ const labels = Array.from(node.querySelectorAll(".rui-tab-group__label"));
3974
+ if (!sampleTab || labels.length === 0) {
3975
+ setContentMinMain(0);
3976
+ return;
3977
+ }
3978
+ const tabStyle = getComputedStyle(sampleTab);
3979
+ const paddingMain = isVertical ? (parseFloat(tabStyle.paddingTop) || 0) + (parseFloat(tabStyle.paddingBottom) || 0) : (parseFloat(tabStyle.paddingLeft) || 0) + (parseFloat(tabStyle.paddingRight) || 0);
3980
+ const borderMain = isVertical ? (parseFloat(tabStyle.borderTopWidth) || 0) + (parseFloat(tabStyle.borderBottomWidth) || 0) : (parseFloat(tabStyle.borderLeftWidth) || 0) + (parseFloat(tabStyle.borderRightWidth) || 0);
3981
+ let largestLabelMain = 0;
3982
+ for (const label of labels) {
3983
+ const rect = label.getBoundingClientRect();
3984
+ const labelMain = isVertical ? rect.height : rect.width;
3985
+ if (labelMain > largestLabelMain) {
3986
+ largestLabelMain = labelMain;
3987
+ }
3988
+ }
3989
+ const next = Math.ceil(largestLabelMain + paddingMain + borderMain);
3990
+ setContentMinMain((prev) => prev === next ? prev : next);
3991
+ };
3992
+ measure();
3993
+ if (typeof ResizeObserver === "undefined") return;
3994
+ const observer = new ResizeObserver(() => measure());
3995
+ observer.observe(node);
3996
+ return () => observer.disconnect();
3997
+ }, [isVertical, position, rotation, tabs]);
3884
3998
  React21.useLayoutEffect(() => {
3885
3999
  const node = tabStripRef.current;
3886
4000
  if (!node) return;
@@ -3896,7 +4010,8 @@ function TabGroup({
3896
4010
  }, [isVertical]);
3897
4011
  const slots = availableMain > 0 && minMain > 0 ? Math.floor(availableMain / minMain) : count;
3898
4012
  const overflow = slots < count;
3899
- const windowSize = overflow ? Math.max(1, slots - 2) : count;
4013
+ const layoutSlots = overflow ? Math.max(3, slots) : Math.max(1, slots);
4014
+ const windowSize = overflow ? Math.max(1, layoutSlots - 2) : count;
3900
4015
  const maxStart = Math.max(0, count - windowSize);
3901
4016
  const [startIndex, setStartIndex] = React21.useState(0);
3902
4017
  React21.useEffect(() => {
@@ -3916,9 +4031,9 @@ function TabGroup({
3916
4031
  });
3917
4032
  }, [currentActive, overflow, windowSize]);
3918
4033
  const visibleTabs = overflow ? tabs.slice(startIndex, startIndex + windowSize) : tabs;
3919
- const slotSize = overflow && slots > 0 ? availableMain / slots : 0;
4034
+ const slotSize = overflow && layoutSlots > 0 ? availableMain / layoutSlots : 0;
3920
4035
  const overflowMainStyle = overflow && slotSize > 0 ? isVertical ? { height: slotSize } : { width: slotSize } : void 0;
3921
- const mainStyle = overflow ? overflowMainStyle : effectiveFill === "partial" ? isVertical ? { height: size } : { width: size } : void 0;
4036
+ const mainStyle = overflow ? overflowMainStyle : effectiveFill === "partial" ? isVertical ? { height: partialMainSize } : { width: partialMainSize } : void 0;
3922
4037
  const scrollLabels = isVertical ? { back: "Scroll tabs up", forward: "Scroll tabs down" } : { back: "Scroll tabs left", forward: "Scroll tabs right" };
3923
4038
  const scrollMainStyle = overflowMainStyle;
3924
4039
  const panelId = `${idBase}-panel`;
@@ -4053,7 +4168,7 @@ function TabGroup({
4053
4168
  children: (_b = (_a = tabs[currentActive]) == null ? void 0 : _a.content) != null ? _b : null
4054
4169
  }
4055
4170
  );
4056
- return /* @__PURE__ */ jsx25(
4171
+ return /* @__PURE__ */ jsxs23(
4057
4172
  "div",
4058
4173
  {
4059
4174
  ref: rootRef,
@@ -4064,13 +4179,16 @@ function TabGroup({
4064
4179
  "data-requested-fill": fill,
4065
4180
  "data-rotation": rotation,
4066
4181
  "data-overflow": overflow ? "true" : "false",
4067
- children: tabsFirst ? /* @__PURE__ */ jsxs23(Fragment2, { children: [
4068
- tabList,
4069
- panel
4070
- ] }) : /* @__PURE__ */ jsxs23(Fragment2, { children: [
4071
- panel,
4072
- tabList
4073
- ] })
4182
+ children: [
4183
+ /* @__PURE__ */ jsx25("div", { ref: measureRef, className: "rui-tab-group__measure", "aria-hidden": "true", children: tabs.map((tab, index) => /* @__PURE__ */ jsx25("button", { type: "button", className: "rui-tab-group__tab", children: /* @__PURE__ */ jsx25("span", { className: "rui-tab-group__label", children: tab.label }) }, index)) }),
4184
+ tabsFirst ? /* @__PURE__ */ jsxs23(Fragment2, { children: [
4185
+ tabList,
4186
+ panel
4187
+ ] }) : /* @__PURE__ */ jsxs23(Fragment2, { children: [
4188
+ panel,
4189
+ tabList
4190
+ ] })
4191
+ ]
4074
4192
  }
4075
4193
  );
4076
4194
  }