reshaped 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/CHANGELOG.md +19 -12
  2. package/LICENSE-SOURCE.md +40 -0
  3. package/LICENSE.md +21 -37
  4. package/bin/clean.sh +1 -0
  5. package/bin/cli.js +1 -11
  6. package/bin/release-source.sh +7 -0
  7. package/bundle.css +1 -1
  8. package/bundle.js +10 -10
  9. package/cli/theming/definitions/base.d.ts +1 -1
  10. package/cli/theming/definitions/figma.d.ts +1 -1
  11. package/cli/theming/definitions/reshaped.d.ts +1 -1
  12. package/cli/theming/definitions/slate.d.ts +1 -1
  13. package/cli/theming/index.d.ts +4 -4
  14. package/cli/theming/index.js +7 -107
  15. package/components/Actionable/Actionable.js +14 -3
  16. package/components/Actionable/Actionable.module.css +1 -1
  17. package/components/Autocomplete/tests/Autocomplete.stories.js +27 -1
  18. package/components/Button/Button.js +2 -0
  19. package/components/Button/Button.module.css +1 -1
  20. package/components/Button/Button.types.d.ts +6 -0
  21. package/components/Button/ButtonGroup.d.ts +4 -0
  22. package/components/Button/ButtonGroup.js +9 -0
  23. package/components/Button/tests/Button.stories.d.ts +1 -0
  24. package/components/Button/tests/Button.stories.js +63 -0
  25. package/components/Checkbox/Checkbox.module.css +1 -1
  26. package/components/DropdownMenu/DropdownMenu.js +1 -1
  27. package/components/DropdownMenu/tests/DropdownMenu.stories.js +1 -0
  28. package/components/Overlay/Overlay.js +4 -4
  29. package/components/Radio/Radio.module.css +1 -1
  30. package/components/Select/Select.js +1 -1
  31. package/components/Slider/Slider.module.css +1 -1
  32. package/components/Switch/Switch.module.css +1 -1
  33. package/components/Tabs/Tabs.d.ts +1 -8
  34. package/components/Tabs/Tabs.module.css +1 -1
  35. package/components/Tabs/Tabs.types.d.ts +6 -7
  36. package/components/Tabs/TabsContext.d.ts +4 -0
  37. package/components/Tabs/TabsControlled.js +24 -1
  38. package/components/Tabs/TabsItem.d.ts +1 -8
  39. package/components/Tabs/TabsItem.js +22 -4
  40. package/components/Tabs/TabsList.js +30 -32
  41. package/components/Tabs/tests/Tabs.stories.d.ts +1 -0
  42. package/components/Tabs/tests/Tabs.stories.js +17 -0
  43. package/components/Toast/ToastContainer.js +1 -0
  44. package/components/Toast/ToastProvider.js +4 -0
  45. package/components/Toast/tests/Toast.stories.js +1 -0
  46. package/components/_private/Flyout/Flyout.types.d.ts +2 -0
  47. package/components/_private/Flyout/FlyoutContent.js +7 -3
  48. package/components/_private/Flyout/FlyoutControlled.js +8 -1
  49. package/components/_private/Flyout/tests/Flyout.stories.d.ts +1 -0
  50. package/components/_private/Flyout/tests/Flyout.stories.js +25 -0
  51. package/components/_private/Portal/Portal.d.ts +8 -4
  52. package/components/_private/Portal/Portal.js +23 -11
  53. package/components/_private/Portal/Portal.types.d.ts +7 -2
  54. package/components/_private/Portal/index.d.ts +1 -1
  55. package/components/_private/Portal/index.js +1 -1
  56. package/components/_private/Portal/tests/Portal.stories.js +11 -12
  57. package/config/next.d.ts +4 -5
  58. package/config/next.js +21 -7
  59. package/config/tailwind.d.ts +1 -1
  60. package/config/tailwind.js +3 -3
  61. package/hooks/_private/useFlyout.js +16 -13
  62. package/package.json +39 -31
  63. package/themes/_generator/tests/themes.stories.d.ts +6 -0
  64. package/themes/_generator/tests/themes.stories.js +32 -0
  65. package/{cli/theming → themes/_generator}/tokens/color/color.transforms.d.ts +1 -1
  66. package/{cli/theming → themes/_generator}/tokens/duration/duration.transforms.d.ts +1 -1
  67. package/{cli/theming → themes/_generator}/tokens/easing/easing.transforms.d.ts +1 -1
  68. package/{cli/theming → themes/_generator}/tokens/font/font.transforms.d.ts +1 -1
  69. package/{cli/theming → themes/_generator}/tokens/fontFamily/fontFamily.transforms.d.ts +1 -1
  70. package/{cli/theming → themes/_generator}/tokens/fontWeight/fontWeight.transforms.d.ts +1 -1
  71. package/{cli/theming → themes/_generator}/tokens/shadow/shadow.transforms.d.ts +1 -1
  72. package/{cli/theming → themes/_generator}/tokens/shadow/shadow.transforms.js +1 -1
  73. package/{cli/theming → themes/_generator}/tokens/unit/unit.transforms.d.ts +1 -1
  74. package/{cli/theming → themes/_generator}/tokens/viewport/viewport.transforms.d.ts +1 -1
  75. package/themes/_generator/transform.d.ts +7 -0
  76. package/themes/_generator/transform.js +57 -0
  77. package/{cli/theming → themes/_generator}/types.d.ts +3 -1
  78. package/{cli/theming → themes/_generator}/utilities/css.js +3 -1
  79. package/themes/_generator/utilities/generateBackgroundColors.d.ts +4 -0
  80. package/themes/_generator/utilities/generateBackgroundColors.js +54 -0
  81. package/themes/_generator/utilities/generateUnits.d.ts +4 -0
  82. package/themes/_generator/utilities/generateUnits.js +17 -0
  83. package/{cli/theming → themes/_generator}/utilities/mergeDeep.js +1 -3
  84. package/{cli/theming → themes/_generator}/utilities/resolveTokenReference.js +1 -3
  85. package/themes/index.d.ts +3 -0
  86. package/themes/index.js +5 -0
  87. package/types/config.d.ts +1 -1
  88. package/utilities/a11y.js +12 -3
  89. package/{cli/utilities → utilities}/color.d.ts +1 -1
  90. package/utilities/dom.d.ts +1 -0
  91. package/utilities/dom.js +9 -0
  92. package/cli/theming/definitions/minimal.d.ts +0 -3
  93. package/cli/theming/definitions/minimal.js +0 -80
  94. package/cli/utilities/tests/color.test.d.ts +0 -1
  95. package/cli/utilities/tests/color.test.js +0 -63
  96. package/styles/aspectRatio/index.test.d.ts +0 -1
  97. package/styles/aspectRatio/index.test.js +0 -24
  98. package/styles/bleed/index.test.d.ts +0 -1
  99. package/styles/bleed/index.test.js +0 -24
  100. package/styles/height/index.test.d.ts +0 -1
  101. package/styles/height/index.test.js +0 -27
  102. package/styles/inset/index.test.d.ts +0 -1
  103. package/styles/inset/index.test.js +0 -27
  104. package/styles/maxHeight/index.test.d.ts +0 -1
  105. package/styles/maxHeight/index.test.js +0 -27
  106. package/styles/maxWidth/index.test.d.ts +0 -1
  107. package/styles/maxWidth/index.test.js +0 -27
  108. package/styles/padding/index.test.d.ts +0 -1
  109. package/styles/padding/index.test.js +0 -24
  110. package/styles/position/index.test.d.ts +0 -1
  111. package/styles/position/index.test.js +0 -21
  112. package/styles/radius/index.test.d.ts +0 -1
  113. package/styles/radius/index.test.js +0 -24
  114. package/styles/width/index.test.d.ts +0 -1
  115. package/styles/width/index.test.js +0 -27
  116. package/themes/minimal/theme.css +0 -1
  117. package/utilities/testPresets.d.ts +0 -25
  118. package/utilities/testPresets.js +0 -76
  119. package/utilities/tests/Chain.test.d.ts +0 -1
  120. package/utilities/tests/Chain.test.js +0 -45
  121. /package/bin/{copy-release.sh → release-copy.sh} +0 -0
  122. /package/{cli/theming → themes/_generator}/tokens/color/color.transforms.js +0 -0
  123. /package/{cli/theming → themes/_generator}/tokens/color/color.types.d.ts +0 -0
  124. /package/{cli/theming → themes/_generator}/tokens/color/color.types.js +0 -0
  125. /package/{cli/theming → themes/_generator}/tokens/duration/duration.transforms.js +0 -0
  126. /package/{cli/theming → themes/_generator}/tokens/duration/duration.types.d.ts +0 -0
  127. /package/{cli/theming → themes/_generator}/tokens/duration/duration.types.js +0 -0
  128. /package/{cli/theming → themes/_generator}/tokens/easing/easing.transforms.js +0 -0
  129. /package/{cli/theming → themes/_generator}/tokens/easing/easing.types.d.ts +0 -0
  130. /package/{cli/theming → themes/_generator}/tokens/easing/easing.types.js +0 -0
  131. /package/{cli/theming → themes/_generator}/tokens/font/font.transforms.js +0 -0
  132. /package/{cli/theming → themes/_generator}/tokens/font/font.types.d.ts +0 -0
  133. /package/{cli/theming → themes/_generator}/tokens/font/font.types.js +0 -0
  134. /package/{cli/theming → themes/_generator}/tokens/fontFamily/fontFamily.transforms.js +0 -0
  135. /package/{cli/theming → themes/_generator}/tokens/fontFamily/fontFamily.types.d.ts +0 -0
  136. /package/{cli/theming → themes/_generator}/tokens/fontFamily/fontFamily.types.js +0 -0
  137. /package/{cli/theming → themes/_generator}/tokens/fontWeight/fontWeight.transforms.js +0 -0
  138. /package/{cli/theming → themes/_generator}/tokens/fontWeight/fontWeight.types.d.ts +0 -0
  139. /package/{cli/theming → themes/_generator}/tokens/fontWeight/fontWeight.types.js +0 -0
  140. /package/{cli/theming → themes/_generator}/tokens/shadow/shadow.types.d.ts +0 -0
  141. /package/{cli/theming → themes/_generator}/tokens/shadow/shadow.types.js +0 -0
  142. /package/{cli/theming → themes/_generator}/tokens/transforms.d.ts +0 -0
  143. /package/{cli/theming → themes/_generator}/tokens/transforms.js +0 -0
  144. /package/{cli/theming → themes/_generator}/tokens/types.d.ts +0 -0
  145. /package/{cli/theming → themes/_generator}/tokens/types.js +0 -0
  146. /package/{cli/theming → themes/_generator}/tokens/unit/unit.transforms.js +0 -0
  147. /package/{cli/theming → themes/_generator}/tokens/unit/unit.types.d.ts +0 -0
  148. /package/{cli/theming → themes/_generator}/tokens/unit/unit.types.js +0 -0
  149. /package/{cli/theming → themes/_generator}/tokens/viewport/viewport.transforms.js +0 -0
  150. /package/{cli/theming → themes/_generator}/tokens/viewport/viewport.types.d.ts +0 -0
  151. /package/{cli/theming → themes/_generator}/tokens/viewport/viewport.types.js +0 -0
  152. /package/{cli/theming → themes/_generator}/types.js +0 -0
  153. /package/{cli/theming → themes/_generator}/utilities/css.d.ts +0 -0
  154. /package/{cli/theming → themes/_generator}/utilities/mergeDeep.d.ts +0 -0
  155. /package/{cli/theming → themes/_generator}/utilities/mergeDefinitions.d.ts +0 -0
  156. /package/{cli/theming → themes/_generator}/utilities/mergeDefinitions.js +0 -0
  157. /package/{cli/theming → themes/_generator}/utilities/resolveTokenReference.d.ts +0 -0
  158. /package/{cli/utilities → utilities}/color.js +0 -0
  159. /package/{cli/utilities → utilities}/string.d.ts +0 -0
  160. /package/{cli/utilities → utilities}/string.js +0 -0
@@ -2,14 +2,7 @@ import React from "react";
2
2
  import type * as T from "./Tabs.types";
3
3
  declare const Tabs: {
4
4
  (props: T.Props): React.JSX.Element;
5
- Item: React.ForwardRefExoticComponent<Partial<T.ItemProps> & {
6
- value: string;
7
- active?: boolean | undefined;
8
- visuallySelected?: boolean | undefined;
9
- attributes?: (Omit<import("../../types/global").Attributes<"button", void>, "ref"> & Omit<React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, `data-${string}` | "form" | "slot" | "style" | "title" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "accessKey" | "autoFocus" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "nonce" | "placeholder" | "spellCheck" | "translate" | "radioGroup" | "about" | "content" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "resource" | "rev" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "disabled" | "color" | "suppressHydrationWarning" | "id" | "lang" | "tabIndex" | "role" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "children" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onResize" | "onResizeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "value" | "type" | keyof React.ClassAttributes<HTMLButtonElement> | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "name"> & {
10
- ref?: React.RefObject<HTMLAnchorElement | HTMLButtonElement> | undefined;
11
- }) | undefined;
12
- } & React.RefAttributes<HTMLDivElement>>;
5
+ Item: React.ForwardRefExoticComponent<T.ItemProps & React.RefAttributes<HTMLAnchorElement | HTMLButtonElement>>;
13
6
  List: (props: T.ListProps) => React.JSX.Element;
14
7
  Panel: (props: T.PanelProps) => React.JSX.Element;
15
8
  };
@@ -1 +1 @@
1
- .root{box-sizing:initial;max-width:100%}.list,.root{position:relative}.inner:after{background-color:var(--rs-color-border-neutral-faded);content:"";position:absolute;z-index:2}.item{--rs-tabs-gap:var(--rs-unit-x4);flex-shrink:0;position:relative}.button{-webkit-tap-highlight-color:transparent;overflow:hidden;position:relative;z-index:1}.button,.buttonContent{border-radius:var(--rs-unit-radius-medium);width:100%}.buttonContent{align-items:center;box-sizing:border-box;display:flex}.buttonContent:hover{color:var(--rs-color-foreground-neutral-faded)}.buttonContent,.icon{color:inherit;transition:color var(--rs-duration-fast) var(--rs-easing-standard)}[data-rs-keyboard] .radio:focus+.buttonContent{box-shadow:var(--rs-focus-inset-shadow)}.icon:not(:last-child){margin-inline-end:var(--rs-unit-x2)}.--item-active:after{content:""}.--item-active:after,.selector{background:var(--rs-color-border-primary);border-radius:calc(var(--rs-unit-radius-medium) - 1px);position:absolute;z-index:var(--rs-z-index-raised)}.selector{--rs-tab-selection-x:0;--rs-tab-selection-y:0;--rs-tab-selection-scale-x:0;--rs-tab-selection-scale-y:0;transform:translate(calc(var(--rs-tab-selection-x) * 1px),calc(var(--rs-tab-selection-y) * 1px)) translateZ(0);transform-origin:0 0}.--selector-hidden{visibility:hidden}.--selector-animated{transition:var(--rs-duration-medium) var(--rs-easing-decelerate);transition-property:transform,width,height}.next,.prev{align-items:center;display:flex;inset-block:0;position:absolute;z-index:var(--rs-z-index-raised)}[dir=rtl] .next,[dir=rtl] .prev{transform:scaleX(-1)}.next{inset-inline-end:var(--rs-unit-x1)}.prev{inset-inline-start:var(--rs-unit-x1)}.panel{outline:none}[data-rs-keyboard] .panel:focus{box-shadow:var(--rs-focus-shadow)}.--panel-hidden{display:none}.--direction-row{margin:0 calc(var(--rs-unit-x2) * -1);overflow:hidden;padding:0 var(--rs-unit-x2)}.--direction-row .inner{-ms-overflow-style:none;margin:0 calc(var(--rs-unit-x2) * -1) -40px;overflow:auto;overflow:-moz-scrollbars-none;padding:0 var(--rs-unit-x2) 40px;scrollbar-width:none;white-space:nowrap}.--direction-row .inner::-webkit-scrollbar{display:none}.--direction-row .inner:after{height:1px;inset-inline:var(--rs-unit-x2);bottom:0}.--direction-row .list{align-items:center;display:inline-flex;flex-wrap:nowrap;vertical-align:top}.--direction-row .item+.item{margin-inline-start:var(--rs-tabs-gap)}.--direction-row .--item-active:after{height:2px;inset-inline:0;bottom:0}.--direction-row .selector{bottom:0;height:2px;left:0;width:calc(var(--rs-tab-selection-scale-x) * 1px)}.--direction-row .button{box-sizing:initial;margin:var(--rs-unit-x1) calc(var(--rs-unit-x2) * -1);padding:0 var(--rs-unit-x2)}.--direction-row .buttonContent{justify-content:center;padding:var(--rs-tabs-item-p-v) 0}.--direction-column .inner:after{bottom:0;height:100%;inset-inline-end:0;top:0;width:1px}.--direction-column .list{display:flex;flex-direction:column}.--direction-column .item{--rs-tabs-gap:var(--rs-unit-x1);padding-inline-end:var(--rs-unit-x1)}.--direction-column .item+.item{margin-top:var(--rs-tabs-gap)}.--direction-column .--item-active:after{bottom:0}.--direction-column .--item-active:after,.--direction-column .selector{height:100%;inset-inline-end:0;width:2px}.--direction-column .selector{height:calc(var(--rs-tab-selection-scale-y) * 1px);top:0}.--direction-column .button{margin-inline-start:calc(var(--rs-unit-x2) * -1);padding:var(--rs-unit-x2);width:calc(100% + var(--rs-unit-x1))}.--direction-column .buttonContent{justify-content:flex-start}.--variant-borderless .inner:after,.--variant-pills .inner:after,.--variant-pills-elevated .inner:after{content:none}.--variant-pills .button,.--variant-pills-elevated .button{margin:0;padding:0}.--variant-pills .buttonContent,.--variant-pills-elevated .buttonContent{margin:0;padding:var(--rs-tabs-item-p-v) var(--rs-tabs-item-p-h)}.--variant-pills .buttonContent:hover,.--variant-pills-elevated .buttonContent:hover{background:none}.--variant-pills .item,.--variant-pills-elevated .item{--rs-tabs-gap:var(--rs-unit-x1)}.--variant-pills .selector,.--variant-pills-elevated .selector{background-color:var(--rs-color-background-neutral);height:calc(var(--rs-tab-selection-scale-y) * 1px);opacity:.6;width:calc(var(--rs-tab-selection-scale-x) * 1px);z-index:0}.--direction-column.--variant-pills .selector,.--direction-column.--variant-pills-elevated .selector{left:0}.--direction-row.--variant-pills .selector,.--direction-row.--variant-pills-elevated .selector{top:0}.--variant-pills .--item-active:after,.--variant-pills-elevated .--item-active:after{background-color:var(--rs-color-background-neutral);opacity:.6;z-index:0}.--direction-column.--variant-pills .--item-active:after,.--direction-column.--variant-pills-elevated .--item-active:after{width:100%}.--direction-row.--variant-pills .--item-active:after,.--direction-row.--variant-pills-elevated .--item-active:after{height:100%}.--variant-pills-elevated .list{background:var(--rs-color-background-neutral-faded);border:2px solid transparent;border-radius:var(--rs-unit-radius-medium)}.--variant-pills-elevated .--item-active:after,.--variant-pills-elevated .selector{background:var(--rs-color-background-elevation-raised);box-shadow:var(--rs-shadow-raised);box-sizing:border-box;opacity:1}.--size-medium{--rs-tabs-item-p-v:var(--rs-unit-x2);--rs-tabs-item-p-h:var(--rs-unit-x3)}.--size-large{--rs-tabs-item-p-v:var(--rs-unit-x3);--rs-tabs-item-p-h:var(--rs-unit-x4)}.--item-width-equal{max-width:none}.--item-width-equal .inner{flex-wrap:wrap;overflow:hidden}.--item-width-equal .list{display:flex}.--item-width-equal .item{flex-basis:0;flex-grow:1;margin:0}.--cut-off-end .inner,[dir=rtl] .--cut-off-start .inner{-webkit-mask-image:linear-gradient(to right,rgba(var(--rs-color-rgb-black),100%) 0,rgba(var(--rs-color-rgb-black),100%) 80%,rgba(var(--rs-color-rgb-black),10%) 95%,rgba(var(--rs-color-rgb-black),0) 100%);mask-image:linear-gradient(to right,rgba(var(--rs-color-rgb-black),100%) 0,rgba(var(--rs-color-rgb-black),100%) 80%,rgba(var(--rs-color-rgb-black),10%) 95%,rgba(var(--rs-color-rgb-black),0) 100%)}.--cut-off-start .inner,[dir=rtl] .--cut-off-end .inner{-webkit-mask-image:linear-gradient(to left,rgba(var(--rs-color-rgb-black),100%) 0,rgba(var(--rs-color-rgb-black),100%) 80%,rgba(var(--rs-color-rgb-black),10%) 95%,rgba(var(--rs-color-rgb-black),0) 100%);mask-image:linear-gradient(to left,rgba(var(--rs-color-rgb-black),100%) 0,rgba(var(--rs-color-rgb-black),100%) 80%,rgba(var(--rs-color-rgb-black),10%) 95%,rgba(var(--rs-color-rgb-black),0) 100%)}.--cut-off-both .inner{-webkit-mask-image:linear-gradient(to right,rgba(var(--rs-color-rgb-black),0) 0,rgba(var(--rs-color-rgb-black),10%) 5%,rgba(var(--rs-color-rgb-black),100%) 20%,rgba(var(--rs-color-rgb-black),100%) 80%,rgba(var(--rs-color-rgb-black),10%) 95%,rgba(var(--rs-color-rgb-black),0) 100%);mask-image:linear-gradient(to right,rgba(var(--rs-color-rgb-black),0) 0,rgba(var(--rs-color-rgb-black),10%) 5%,rgba(var(--rs-color-rgb-black),100%) 20%,rgba(var(--rs-color-rgb-black),100%) 80%,rgba(var(--rs-color-rgb-black),10%) 95%,rgba(var(--rs-color-rgb-black),0) 100%)}@media (max-width:659px){.next,.prev{display:none}}
1
+ .root{box-sizing:initial;max-width:100%}.list,.root{position:relative}.inner:after{background-color:var(--rs-color-border-neutral-faded);content:"";position:absolute;z-index:2}.listItem{--rs-tabs-gap:var(--rs-unit-x4);flex-shrink:0;position:relative}.button{-webkit-tap-highlight-color:transparent;overflow:hidden;position:relative;z-index:1}.button,.buttonContent{border-radius:var(--rs-unit-radius-medium);width:100%}.buttonContent{align-items:center;box-sizing:border-box;display:flex}.buttonContent:hover{color:var(--rs-color-foreground-neutral-faded)}.buttonContent,.icon{color:inherit;transition:color var(--rs-duration-fast) var(--rs-easing-standard)}[data-rs-keyboard] .radio:focus+.buttonContent{box-shadow:var(--rs-focus-inset-shadow)}.icon:not(:last-child){margin-inline-end:var(--rs-unit-x2)}.--item-active:after{content:""}.--item-active:after,.selector{background:var(--rs-color-border-primary);border-radius:calc(var(--rs-unit-radius-medium) - 1px);position:absolute;z-index:var(--rs-z-index-raised)}.selector{--rs-tab-selection-x:0;--rs-tab-selection-y:0;--rs-tab-selection-scale-x:0;--rs-tab-selection-scale-y:0;transform:translate(calc(var(--rs-tab-selection-x) * 1px),calc(var(--rs-tab-selection-y) * 1px)) translateZ(0);transform-origin:0 0}.--selector-hidden{visibility:hidden}.--selector-animated{transition:var(--rs-duration-medium) var(--rs-easing-decelerate);transition-property:transform,height}.next,.prev{align-items:center;display:flex;inset-block:0;position:absolute;z-index:var(--rs-z-index-raised)}[dir=rtl] .next,[dir=rtl] .prev{transform:scaleX(-1)}.next{inset-inline-end:var(--rs-unit-x1)}.prev{inset-inline-start:var(--rs-unit-x1)}.panel{outline:none}[data-rs-keyboard] .panel:focus{box-shadow:var(--rs-focus-shadow)}.--panel-hidden{display:none}.--direction-row{margin:0 calc(var(--rs-unit-x2) * -1);overflow:hidden;padding:0 var(--rs-unit-x2)}.--direction-row .inner{-ms-overflow-style:none;margin:0 calc(var(--rs-unit-x2) * -1) -40px;overflow:auto;overflow:-moz-scrollbars-none;padding:0 var(--rs-unit-x2) 40px;scrollbar-width:none;white-space:nowrap}.--direction-row .inner::-webkit-scrollbar{display:none}.--direction-row .inner:after{height:1px;inset-inline:var(--rs-unit-x2);bottom:0}.--direction-row .list{align-items:center;display:inline-flex;flex-wrap:nowrap;vertical-align:top}.--direction-row .listItem+.listItem{margin-inline-start:var(--rs-tabs-gap)}.--direction-row .--item-active:after{height:2px;inset-inline:0;bottom:0}.--direction-row .selector{bottom:0;height:2px;left:0;width:calc(var(--rs-tab-selection-scale-x) * 1px)}.--direction-row .button{box-sizing:initial;margin:var(--rs-unit-x1) calc(var(--rs-unit-x2) * -1);padding:0 var(--rs-unit-x2)}.--direction-row .buttonContent{justify-content:center;padding:var(--rs-tabs-item-p-v) 0}.--direction-column .inner:after{bottom:0;height:100%;inset-inline-end:0;top:0;width:1px}.--direction-column .list{display:flex;flex-direction:column}.--direction-column .listItem{--rs-tabs-gap:var(--rs-unit-x1)}.--direction-column .item{padding-inline-end:var(--rs-unit-x1)}.--direction-column .listItem+.listItem{margin-top:var(--rs-tabs-gap)}.--direction-column .--item-active:after{bottom:0}.--direction-column .--item-active:after,.--direction-column .selector{height:100%;inset-inline-end:0;width:2px}.--direction-column .selector{height:calc(var(--rs-tab-selection-scale-y) * 1px);top:0}.--direction-column .button{margin-inline-start:calc(var(--rs-unit-x2) * -1);padding:var(--rs-unit-x2);width:calc(100% + var(--rs-unit-x1))}.--direction-column .buttonContent{justify-content:flex-start}.--variant-borderless .inner:after,.--variant-pills .inner:after,.--variant-pills-elevated .inner:after{content:none}.--variant-pills .button,.--variant-pills-elevated .button{margin:0;padding:0}.--variant-pills .buttonContent,.--variant-pills-elevated .buttonContent{margin:0;padding:var(--rs-tabs-item-p-v) var(--rs-tabs-item-p-h)}.--variant-pills .buttonContent:hover,.--variant-pills-elevated .buttonContent:hover{background:none}.--variant-pills .listItem,.--variant-pills-elevated .listItem{--rs-tabs-gap:var(--rs-unit-x1)}.--variant-pills .selector,.--variant-pills-elevated .selector{background-color:var(--rs-color-background-neutral);height:calc(var(--rs-tab-selection-scale-y) * 1px);opacity:.6;width:calc(var(--rs-tab-selection-scale-x) * 1px);z-index:0}.--direction-column.--variant-pills .selector,.--direction-column.--variant-pills-elevated .selector{left:0}.--direction-row.--variant-pills .selector,.--direction-row.--variant-pills-elevated .selector{top:0}.--variant-pills .--item-active:after,.--variant-pills-elevated .--item-active:after{background-color:var(--rs-color-background-neutral);opacity:.6;z-index:0}.--direction-column.--variant-pills .--item-active:after,.--direction-column.--variant-pills-elevated .--item-active:after{width:100%}.--direction-row.--variant-pills .--item-active:after,.--direction-row.--variant-pills-elevated .--item-active:after{height:100%}.--variant-pills-elevated .list{background:var(--rs-color-background-neutral-faded);border:2px solid transparent;border-radius:var(--rs-unit-radius-medium)}.--variant-pills-elevated .--item-active:after,.--variant-pills-elevated .selector{background:var(--rs-color-background-elevation-raised);box-shadow:var(--rs-shadow-raised);box-sizing:border-box;opacity:1}.--size-medium{--rs-tabs-item-p-v:var(--rs-unit-x2);--rs-tabs-item-p-h:var(--rs-unit-x3)}.--size-large{--rs-tabs-item-p-v:var(--rs-unit-x3);--rs-tabs-item-p-h:var(--rs-unit-x4)}.--item-width-equal{max-width:none}.--item-width-equal .inner{flex-wrap:wrap;overflow:hidden}.--item-width-equal .list{display:flex}.--item-width-equal .listItem{flex-basis:0;flex-grow:1;margin:0}.--cut-off-end .inner,[dir=rtl] .--cut-off-start .inner{-webkit-mask-image:linear-gradient(to right,rgba(var(--rs-color-rgb-black),100%) 0,rgba(var(--rs-color-rgb-black),100%) 80%,rgba(var(--rs-color-rgb-black),10%) 95%,rgba(var(--rs-color-rgb-black),0) 100%);mask-image:linear-gradient(to right,rgba(var(--rs-color-rgb-black),100%) 0,rgba(var(--rs-color-rgb-black),100%) 80%,rgba(var(--rs-color-rgb-black),10%) 95%,rgba(var(--rs-color-rgb-black),0) 100%)}.--cut-off-start .inner,[dir=rtl] .--cut-off-end .inner{-webkit-mask-image:linear-gradient(to left,rgba(var(--rs-color-rgb-black),100%) 0,rgba(var(--rs-color-rgb-black),100%) 80%,rgba(var(--rs-color-rgb-black),10%) 95%,rgba(var(--rs-color-rgb-black),0) 100%);mask-image:linear-gradient(to left,rgba(var(--rs-color-rgb-black),100%) 0,rgba(var(--rs-color-rgb-black),100%) 80%,rgba(var(--rs-color-rgb-black),10%) 95%,rgba(var(--rs-color-rgb-black),0) 100%)}.--cut-off-both .inner{-webkit-mask-image:linear-gradient(to right,rgba(var(--rs-color-rgb-black),0) 0,rgba(var(--rs-color-rgb-black),10%) 5%,rgba(var(--rs-color-rgb-black),100%) 20%,rgba(var(--rs-color-rgb-black),100%) 80%,rgba(var(--rs-color-rgb-black),10%) 95%,rgba(var(--rs-color-rgb-black),0) 100%);mask-image:linear-gradient(to right,rgba(var(--rs-color-rgb-black),0) 0,rgba(var(--rs-color-rgb-black),10%) 5%,rgba(var(--rs-color-rgb-black),100%) 20%,rgba(var(--rs-color-rgb-black),100%) 80%,rgba(var(--rs-color-rgb-black),10%) 95%,rgba(var(--rs-color-rgb-black),0) 100%)}@media (max-width:659px){.next,.prev{display:none}}
@@ -1,5 +1,4 @@
1
1
  import React from "react";
2
- import { ActionableProps } from "../Actionable";
3
2
  import { IconProps } from "../Icon";
4
3
  import type * as G from "../../types/global";
5
4
  export type SelectionState = {
@@ -13,12 +12,8 @@ export type ItemProps = {
13
12
  value: string;
14
13
  children?: React.ReactNode;
15
14
  icon?: IconProps["svg"];
16
- };
17
- export type PrivateItemProps = Partial<ItemProps> & {
18
- value: string;
19
- active?: boolean;
20
- visuallySelected?: boolean;
21
- attributes?: ActionableProps["attributes"];
15
+ href?: string;
16
+ attributes?: G.Attributes<"div", Props>;
22
17
  };
23
18
  export type ListProps = {
24
19
  children?: React.ReactNode;
@@ -58,4 +53,8 @@ export type Context = Pick<BaseProps, "itemWidth" | "onChange" | "variant" | "na
58
53
  value?: string;
59
54
  setDefaultValue: (value: string) => void;
60
55
  id: string;
56
+ elActiveRef: React.MutableRefObject<HTMLDivElement | null>;
57
+ elPrevActiveRef: React.MutableRefObject<HTMLDivElement | null>;
58
+ selection: SelectionState;
59
+ setSelection: React.Dispatch<React.SetStateAction<SelectionState>>;
61
60
  };
@@ -15,4 +15,8 @@ export declare const useTabs: (value?: string) => {
15
15
  size: NonNullable<"medium" | "large" | undefined>;
16
16
  value?: string | undefined;
17
17
  setDefaultValue: (value: string) => void;
18
+ elActiveRef: React.MutableRefObject<HTMLDivElement | null>;
19
+ elPrevActiveRef: React.MutableRefObject<HTMLDivElement | null>;
20
+ selection: T.SelectionState;
21
+ setSelection: React.Dispatch<React.SetStateAction<T.SelectionState>>;
18
22
  };
@@ -5,12 +5,35 @@ import { TabsProvider } from "./TabsContext.js";
5
5
  const TabsControlled = (props) => {
6
6
  const { children, value, onChange, onSilentChange, itemWidth, variant, name, direction = "row", size = "medium", } = props;
7
7
  const id = useElementId();
8
+ const elActiveRef = React.useRef(null);
9
+ const elPrevActiveRef = React.useRef(elActiveRef.current);
10
+ const [selection, setSelection] = React.useState({
11
+ scaleX: 0,
12
+ scaleY: 0,
13
+ left: 0,
14
+ top: 0,
15
+ status: "idle",
16
+ });
8
17
  const setDefaultValue = (value) => {
9
18
  if (value === undefined)
10
19
  return;
11
20
  if (onSilentChange)
12
21
  onSilentChange({ value, name });
13
22
  };
14
- return (React.createElement(TabsProvider, { value: { value, name, size, direction, itemWidth, variant, onChange, id, setDefaultValue } }, children));
23
+ return (React.createElement(TabsProvider, { value: {
24
+ value,
25
+ name,
26
+ size,
27
+ direction,
28
+ itemWidth,
29
+ variant,
30
+ onChange,
31
+ id,
32
+ setDefaultValue,
33
+ elActiveRef,
34
+ elPrevActiveRef,
35
+ selection,
36
+ setSelection,
37
+ } }, children));
15
38
  };
16
39
  export default TabsControlled;
@@ -1,11 +1,4 @@
1
1
  import React from "react";
2
2
  import type * as T from "./Tabs.types";
3
- declare const _default: React.ForwardRefExoticComponent<Partial<T.ItemProps> & {
4
- value: string;
5
- active?: boolean | undefined;
6
- visuallySelected?: boolean | undefined;
7
- attributes?: (Omit<import("../../types/global").Attributes<"button", void>, "ref"> & Omit<React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, `data-${string}` | "form" | "slot" | "style" | "title" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "accessKey" | "autoFocus" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "nonce" | "placeholder" | "spellCheck" | "translate" | "radioGroup" | "about" | "content" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "resource" | "rev" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "disabled" | "color" | "suppressHydrationWarning" | "id" | "lang" | "tabIndex" | "role" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "children" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onResize" | "onResizeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "value" | "type" | keyof React.ClassAttributes<HTMLButtonElement> | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "name"> & {
8
- ref?: React.RefObject<HTMLAnchorElement | HTMLButtonElement> | undefined;
9
- }) | undefined;
10
- } & React.RefAttributes<HTMLDivElement>>;
3
+ declare const _default: React.ForwardRefExoticComponent<T.ItemProps & React.RefAttributes<HTMLAnchorElement | HTMLButtonElement>>;
11
4
  export default _default;
@@ -8,8 +8,11 @@ import Text from "../Text/index.js";
8
8
  import { useTabs } from "./TabsContext.js";
9
9
  import s from "./Tabs.module.css";
10
10
  const TabsItem = (props, ref) => {
11
- const { value, children, icon, active, visuallySelected, attributes } = props;
12
- const { onChange, panelId, name, size } = useTabs(value);
11
+ const { value, children, icon, href, attributes } = props;
12
+ const { onChange, panelId, name, size, value: tabsValue, selection, elActiveRef, elPrevActiveRef, } = useTabs(value);
13
+ const itemRef = React.useRef(null);
14
+ const active = tabsValue === value;
15
+ const visuallySelected = active && selection.status === "idle";
13
16
  const itemClassNames = classNames(s.item, visuallySelected && s["--item-active"]);
14
17
  const isFormControl = !!name;
15
18
  const tabAttributes = {
@@ -17,12 +20,27 @@ const TabsItem = (props, ref) => {
17
20
  tabIndex: active ? 0 : -1,
18
21
  "aria-selected": active,
19
22
  };
23
+ const updateRefs = React.useCallback(() => {
24
+ if (!("current" in itemRef)) {
25
+ throw new Error("Reshaped, Tabs: TabItem is expecting an object ref format but received a function ref");
26
+ }
27
+ elPrevActiveRef.current = elActiveRef.current;
28
+ elActiveRef.current = itemRef.current;
29
+ }, [elActiveRef, elPrevActiveRef]);
20
30
  const handleChange = () => {
31
+ if (href && !onChange)
32
+ return;
33
+ updateRefs();
21
34
  if (onChange)
22
35
  onChange({ value, name });
23
36
  };
24
- return (React.createElement("div", { className: itemClassNames, ref: ref, role: "presentation" },
25
- React.createElement(Actionable, { insetFocus: true, onClick: !name ? handleChange : undefined, className: s.button, as: name ? "label" : undefined, attributes: Object.assign(Object.assign(Object.assign({}, attributes), (!isFormControl && tabAttributes)), { "aria-controls": panelId }) },
37
+ React.useEffect(() => {
38
+ if (!active)
39
+ return;
40
+ updateRefs();
41
+ }, [active, updateRefs]);
42
+ return (React.createElement("div", Object.assign({}, attributes, { className: itemClassNames, ref: itemRef, role: "presentation" }),
43
+ React.createElement(Actionable, { ref: ref, href: href, insetFocus: true, onClick: !name ? handleChange : undefined, className: s.button, as: name ? "label" : undefined, attributes: Object.assign(Object.assign({}, (!isFormControl && tabAttributes)), { "aria-controls": panelId }) },
26
44
  name && (React.createElement(HiddenInput, { type: "radio", name: name, value: value, checked: visuallySelected, onChange: handleChange, className: s.radio })),
27
45
  React.createElement("span", { className: s.buttonContent },
28
46
  icon && React.createElement(Icon, { svg: icon, className: s.icon, size: 4 }),
@@ -11,20 +11,18 @@ import IconChevronLeft from "../../icons/ChevronLeft.js";
11
11
  import TabsItem from "./TabsItem.js";
12
12
  import { useTabs } from "./TabsContext.js";
13
13
  import s from "./Tabs.module.css";
14
+ const findParentItem = (el, rootEl) => {
15
+ if (el === rootEl || !el)
16
+ return null;
17
+ if (el.classList.contains(s.listItem))
18
+ return el;
19
+ return findParentItem(el.parentElement, rootEl);
20
+ };
14
21
  const TabsList = (props) => {
15
22
  const { children, className, attributes } = props;
16
- const { value, setDefaultValue, itemWidth, variant, name, direction, size } = useTabs();
23
+ const { value, setDefaultValue, itemWidth, variant, name, direction, size, selection, setSelection, elActiveRef, elPrevActiveRef, } = useTabs();
17
24
  const [rtl] = useRTL();
18
25
  const elScrollableRef = React.useRef(null);
19
- const elActiveRef = React.useRef(null);
20
- const elPrevActiveRef = React.useRef(elActiveRef.current);
21
- const [selection, setSelection] = React.useState({
22
- scaleX: 0,
23
- scaleY: 0,
24
- left: 0,
25
- top: 0,
26
- status: "idle",
27
- });
28
26
  const [cutOffSide, setCutOffSide] = React.useState(null);
29
27
  const rootClassNames = classNames(s.root, size && s[`--size-${size}`], direction && s[`--direction-${direction}`], itemWidth && s[`--item-width-${itemWidth}`], variant && s[`--variant-${variant}`], cutOffSide && s[`--cut-off-${cutOffSide}`], className);
30
28
  const selectorClassNames = classNames(s.selector, selection.status === "idle" && s["--selector-hidden"], selection.status === "animated" && s["--selector-animated"]);
@@ -46,11 +44,16 @@ const TabsList = (props) => {
46
44
  setSelection((selectionStyle) => (Object.assign(Object.assign({}, selectionStyle), { status: "idle" })));
47
45
  };
48
46
  const getElementSelectionStyle = React.useCallback((el) => {
47
+ if (!elScrollableRef.current)
48
+ return null;
49
+ const itemEl = findParentItem(el, elScrollableRef.current);
50
+ if (!itemEl)
51
+ return null;
49
52
  return {
50
- scaleX: el.clientWidth,
51
- scaleY: el.clientHeight,
52
- top: el.offsetTop,
53
- left: el.offsetLeft,
53
+ scaleX: itemEl.clientWidth,
54
+ scaleY: itemEl.clientHeight,
55
+ top: itemEl.offsetTop,
56
+ left: itemEl.offsetLeft,
54
57
  };
55
58
  }, []);
56
59
  const { ref: hotkeysRef } = useHotkeys({
@@ -89,16 +92,20 @@ const TabsList = (props) => {
89
92
  }, [value]);
90
93
  useIsomorphicLayoutEffect(() => {
91
94
  // Do not update selection on mount, until we receive new activeId
92
- if (elActiveRef.current === elPrevActiveRef.current)
95
+ if (!elPrevActiveRef.current || elPrevActiveRef.current === elActiveRef.current)
93
96
  return;
94
97
  const selectionStyle = getElementSelectionStyle(elPrevActiveRef.current);
98
+ if (!selectionStyle)
99
+ return;
95
100
  setSelection(Object.assign(Object.assign({}, selectionStyle), { status: "prepared" }));
96
101
  }, [value, getElementSelectionStyle]);
97
102
  useIsomorphicLayoutEffect(() => {
98
- if (selection.status === "prepared") {
99
- const selectionStyle = getElementSelectionStyle(elActiveRef.current);
100
- setSelection(Object.assign(Object.assign({}, selectionStyle), { status: "animated" }));
101
- }
103
+ if (selection.status !== "prepared" || !elActiveRef.current)
104
+ return;
105
+ const selectionStyle = getElementSelectionStyle(elActiveRef.current);
106
+ if (!selectionStyle)
107
+ return;
108
+ setSelection(Object.assign(Object.assign({}, selectionStyle), { status: "animated" }));
102
109
  }, [selection]);
103
110
  useIsomorphicLayoutEffect(() => {
104
111
  const elScrollable = elScrollableRef.current;
@@ -135,19 +142,10 @@ const TabsList = (props) => {
135
142
  return (React.createElement("div", Object.assign({}, attributes, { className: rootClassNames }),
136
143
  React.createElement("div", { className: s.inner, ref: elScrollableRef },
137
144
  React.createElement("div", { className: s.list, role: "tablist", ref: hotkeysRef },
138
- React.Children.map(children, (child) => {
139
- if (!child || child.type !== TabsItem)
140
- return React.createElement("div", { className: s.item }, child);
141
- const childValue = child.props.value;
142
- const isActive = childValue === value;
143
- return (React.createElement(TabsItem, Object.assign({}, child.props, { ref: (node) => {
144
- if (!node)
145
- return;
146
- if (isActive) {
147
- elPrevActiveRef.current = elActiveRef.current || node;
148
- elActiveRef.current = node;
149
- }
150
- }, value: childValue, key: childValue, active: isActive, visuallySelected: isActive && selection.status === "idle" })));
145
+ React.Children.map(children, (child, index) => {
146
+ if (!child)
147
+ return null;
148
+ return (React.createElement("div", { className: s.listItem, key: child.props.value || child.key || index }, child));
151
149
  }),
152
150
  React.createElement("div", { onTransitionEnd: handleTransitionEnd, className: selectorClassNames, style: {
153
151
  "--rs-tab-selection-x": selection.left,
@@ -10,4 +10,5 @@ export declare const composition: () => React.JSX.Element;
10
10
  export declare const icon: () => React.JSX.Element;
11
11
  export declare const equalWidth: () => React.JSX.Element;
12
12
  export declare const selection: () => React.JSX.Element;
13
+ export declare const navigation: () => React.JSX.Element;
13
14
  export declare const edgeCases: () => React.JSX.Element;
@@ -211,6 +211,23 @@ export const selection = () => (<Example>
211
211
  </Tabs>
212
212
  </Example.Item>
213
213
  </Example>);
214
+ export const navigation = () => (<Example>
215
+ <Example.Item title="href, no onChange">
216
+ <Tabs value="2">
217
+ <Tabs.List>
218
+ <Tabs.Item value="1" href="#item-1" icon={IconZap}>
219
+ Item 1
220
+ </Tabs.Item>
221
+ <Tabs.Item value="2" href="#item-2" icon={IconZap}>
222
+ Long item 2
223
+ </Tabs.Item>
224
+ <Tabs.Item value="3" href="#item-3" icon={IconZap}>
225
+ Very long item 3
226
+ </Tabs.Item>
227
+ </Tabs.List>
228
+ </Tabs>
229
+ </Example.Item>
230
+ </Example>);
214
231
  export const edgeCases = () => (<Example>
215
232
  <Example.Item title="Viewport overflow">
216
233
  <Tabs>
@@ -53,6 +53,7 @@ const ToastContainer = (props) => {
53
53
  if (wrapperRef.current) {
54
54
  setToastHeight(wrapperRef.current.clientHeight);
55
55
  }
56
+ console.log("show");
56
57
  show(id);
57
58
  startTimer();
58
59
  }, [show, id, startTimer]);
@@ -27,6 +27,8 @@ const toastReducer = (state, action) => {
27
27
  nextState = Object.assign({}, state);
28
28
  positions.forEach((position) => {
29
29
  nextState[position] = nextState[position].map((item) => {
30
+ if (item.status !== "entering")
31
+ return item;
30
32
  return item.id === showId ? Object.assign(Object.assign({}, item), { status: "entered" }) : item;
31
33
  });
32
34
  });
@@ -52,6 +54,7 @@ const ToastProvider = (props) => {
52
54
  const [data, dispatch] = React.useReducer(toastReducer, defaultContextData.queues);
53
55
  const add = React.useCallback((toastProps) => {
54
56
  const id = generateId();
57
+ console.log("add");
55
58
  dispatch({ type: "add", payload: { toastProps, id } });
56
59
  return id;
57
60
  }, []);
@@ -59,6 +62,7 @@ const ToastProvider = (props) => {
59
62
  dispatch({ type: "show", payload: { id } });
60
63
  }, []);
61
64
  const hide = React.useCallback((id) => {
65
+ console.log("hide");
62
66
  dispatch({ type: "hide", payload: { id } });
63
67
  }, []);
64
68
  const remove = React.useCallback((id) => {
@@ -20,6 +20,7 @@ const Base = () => {
20
20
  <Button onClick={() => toast.hide(id)}>Show</Button>,
21
21
  ],
22
22
  });
23
+ toast.hide(id);
23
24
  }}>
24
25
  Show toast
25
26
  </Button>);
@@ -73,5 +73,7 @@ export type ContextProps = {
73
73
  handleClick: () => void;
74
74
  handleBlur: (e: React.FocusEvent) => void;
75
75
  handleFocus: () => void;
76
+ handleContentMouseDown: () => void;
77
+ handleContentMouseUp: () => void;
76
78
  } & Pick<Props, "triggerType" | "contentClassName" | "contentAttributes" | "trapFocusMode" | "contentGap">;
77
79
  export {};
@@ -3,11 +3,12 @@ import React from "react";
3
3
  import { classNames } from "../../../utilities/helpers.js";
4
4
  import useIsomorphicLayoutEffect from "../../../hooks/useIsomorphicLayoutEffect.js";
5
5
  import Portal from "../Portal/index.js";
6
+ import { getClosestScrollableParent } from "../../../utilities/dom.js";
6
7
  import { useFlyoutContext } from "./Flyout.context.js";
7
8
  import s from "./Flyout.module.css";
8
9
  const FlyoutContent = (props) => {
9
10
  const { children, className, attributes } = props;
10
- const { flyout, id, flyoutElRef, handleTransitionEnd, triggerType, handleMouseEnter, handleMouseLeave, contentGap, contentClassName, contentAttributes, trapFocusMode, } = useFlyoutContext();
11
+ const { flyout, id, flyoutElRef, triggerElRef, handleTransitionEnd, triggerType, handleMouseEnter, handleMouseLeave, handleContentMouseDown, handleContentMouseUp, contentGap, contentClassName, contentAttributes, trapFocusMode, } = useFlyoutContext();
11
12
  const { styles, status, position } = flyout;
12
13
  const [mounted, setMounted] = React.useState(false);
13
14
  useIsomorphicLayoutEffect(() => {
@@ -33,8 +34,11 @@ const FlyoutContent = (props) => {
33
34
  else if (trapFocusMode === "action-menu") {
34
35
  role = "menu";
35
36
  }
36
- const content = (React.createElement("div", { className: contentClassNames, style: Object.assign(Object.assign({}, styles), { "--rs-flyout-gap": contentGap }), ref: flyoutElRef, onTransitionEnd: handleTransitionEnd, onMouseEnter: triggerType === "hover" ? handleMouseEnter : undefined, onMouseLeave: triggerType === "hover" ? handleMouseLeave : undefined },
37
+ const content = (
38
+ // eslint-disable-next-line jsx-a11y/no-static-element-interactions
39
+ React.createElement("div", { className: contentClassNames, style: Object.assign(Object.assign({}, styles), { "--rs-flyout-gap": contentGap }), ref: flyoutElRef, onTransitionEnd: handleTransitionEnd, onMouseEnter: triggerType === "hover" ? handleMouseEnter : undefined, onMouseLeave: triggerType === "hover" ? handleMouseLeave : undefined, onMouseDown: handleContentMouseDown, onTouchStart: handleContentMouseDown, onMouseUp: handleContentMouseUp, onTouchEnd: handleContentMouseUp },
37
40
  React.createElement("div", Object.assign({ role: role }, attributes, { id: id, "aria-modal": triggerType === "click", style: contentAttributes === null || contentAttributes === void 0 ? void 0 : contentAttributes.style, className: innerClassNames }), children)));
38
- return React.createElement(Portal, null, content);
41
+ const closestScrollable = getClosestScrollableParent(triggerElRef.current);
42
+ return (React.createElement(Portal, { targetRef: closestScrollable === document.body ? undefined : { current: closestScrollable } }, content));
39
43
  };
40
44
  export default FlyoutContent;
@@ -21,6 +21,7 @@ const FlyoutRoot = (props) => {
21
21
  const timerRef = React.useRef();
22
22
  const releaseFocusRef = React.useRef(null);
23
23
  const lockedRef = React.useRef(false);
24
+ const lockedBlurEffects = React.useRef(false);
24
25
  const shouldReturnFocusRef = React.useRef(true);
25
26
  const flyout = useFlyout(triggerElRef, flyoutElRef, {
26
27
  width,
@@ -70,7 +71,9 @@ const FlyoutRoot = (props) => {
70
71
  // Empty flyouts don't move the focus so they have to be closed on blur
71
72
  focusedContent ||
72
73
  // Content menu keeps the focus on the original trigger so moving the focus away from it shouldn't close it
73
- (triggerType === "hover" && trapFocusMode === "content-menu")) {
74
+ (triggerType === "hover" && trapFocusMode === "content-menu") ||
75
+ // Prevent from closing in case user interacts with items inside content
76
+ lockedBlurEffects.current) {
74
77
  return;
75
78
  }
76
79
  handleClose();
@@ -94,6 +97,8 @@ const FlyoutRoot = (props) => {
94
97
  handleClose();
95
98
  }
96
99
  }, [status, handleOpen, handleClose]);
100
+ const handleContentMouseDown = () => (lockedBlurEffects.current = true);
101
+ const handleContentMouseUp = () => (lockedBlurEffects.current = false);
97
102
  /**
98
103
  * Control the display based on the props
99
104
  */
@@ -204,6 +209,8 @@ const FlyoutRoot = (props) => {
204
209
  handleMouseLeave,
205
210
  handleTransitionEnd,
206
211
  handleClick: handleTriggerClick,
212
+ handleContentMouseDown,
213
+ handleContentMouseUp,
207
214
  triggerType,
208
215
  trapFocusMode,
209
216
  contentGap,
@@ -12,5 +12,6 @@ export declare const modeDialogHover: () => React.JSX.Element;
12
12
  export declare const modeActionMenuHover: () => React.JSX.Element;
13
13
  export declare const modeContentMenuHover: () => React.JSX.Element;
14
14
  export declare const testWidthOverflowOnMobile: () => React.JSX.Element;
15
+ export declare const testInsideScrollArea: () => React.JSX.Element;
15
16
  export declare const widthTrigger: () => React.JSX.Element;
16
17
  export declare const scopedTheming: () => React.JSX.Element;
@@ -10,6 +10,7 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import React from "react";
13
+ import { Example } from "../../../../utilities/storybook/index.js";
13
14
  import View from "../../../View/index.js";
14
15
  import Theme from "../../../Theme/index.js";
15
16
  import Button from "../../../Button/index.js";
@@ -92,6 +93,30 @@ export const testWidthOverflowOnMobile = () => (<Demo position="bottom-start" wi
92
93
  <button type="button">Item 2</button>
93
94
  <button type="button">Close</button>
94
95
  </Demo>);
96
+ export const testInsideScrollArea = () => (<Example>
97
+ <Example.Item title="should move the content on area scroll">
98
+ <div style={{ overflow: "scroll", height: 200, margin: 40, position: "relative" }}>
99
+ <Flyout triggerType="click" position="bottom-start">
100
+ <Flyout.Trigger>{(attributes) => <button {...attributes}>Foo</button>}</Flyout.Trigger>
101
+ <Flyout.Content>
102
+ <div style={{
103
+ background: "var(--rs-color-background-elevation-overlay)",
104
+ padding: "var(--rs-unit-x4)",
105
+ height: 100,
106
+ width: 160,
107
+ borderRadius: "var(--rs-unit-radius-medium)",
108
+ border: "1px solid var(--rs-color-border-neutral-faded)",
109
+ boxSizing: "border-box",
110
+ }}>
111
+ {"Content"}
112
+ </div>
113
+ </Flyout.Content>
114
+ </Flyout>
115
+ <View height="300px" backgroundColor="neutral-faded"/>
116
+ </div>
117
+ <div style={{ height: 2000 }}/>
118
+ </Example.Item>
119
+ </Example>);
95
120
  export const widthTrigger = () => (<Flyout triggerType="click" width="trigger" position="bottom">
96
121
  <Flyout.Trigger>
97
122
  {(attributes) => <button {...attributes}>Trigger with long text</button>}
@@ -1,9 +1,13 @@
1
- /// <reference types="react" />
1
+ import React from "react";
2
2
  import type * as T from "./Portal.types";
3
- export declare const usePortal: () => T.Context;
3
+ export declare const usePortalScope: () => T.Context;
4
4
  /**
5
5
  * Disclaimer: Works only for components that don't show the portal immediately
6
6
  * That gives Portal time to receive scope on first render
7
7
  */
8
- declare const PortalProvider: (props: T.Props) => JSX.Element;
9
- export default PortalProvider;
8
+ declare const Portal: {
9
+ (props: T.Props): JSX.Element;
10
+ Scope: typeof PortalScope;
11
+ };
12
+ declare function PortalScope<T extends HTMLElement>(props: T.ScopeProps<T>): React.JSX.Element;
13
+ export default Portal;
@@ -2,20 +2,32 @@
2
2
  import React from "react";
3
3
  import ReactDOM from "react-dom";
4
4
  import Theme from "../../Theme/index.js";
5
- const PortalContext = React.createContext({ scopeRef: undefined });
6
- export const usePortal = () => {
7
- return React.useContext(PortalContext);
5
+ const PortalScopeContext = React.createContext({});
6
+ export const usePortalScope = () => {
7
+ return React.useContext(PortalScopeContext);
8
8
  };
9
9
  /**
10
10
  * Disclaimer: Works only for components that don't show the portal immediately
11
11
  * That gives Portal time to receive scope on first render
12
12
  */
13
- const PortalProvider = (props) => {
14
- var _a;
15
- const { children, scopeRef } = props;
16
- const portal = usePortal();
17
- const nextScopeRef = scopeRef || portal.scopeRef;
18
- return ReactDOM.createPortal(React.createElement(PortalContext.Provider, { value: { scopeRef: nextScopeRef } },
19
- React.createElement(Theme, null, children)), ((_a = portal.scopeRef) === null || _a === void 0 ? void 0 : _a.current) || document.body);
13
+ const Portal = (props) => {
14
+ const { children, targetRef } = props;
15
+ /**
16
+ * Check for parent portal to render inside it
17
+ * To avoid z-iondex issues
18
+ * Example:
19
+ * Dropdown rendered on the page should render under the modal
20
+ * Dropdown inside the modal should render above it
21
+ */
22
+ const portal = usePortalScope();
23
+ const nextScopeRef = targetRef || portal.scopeRef;
24
+ /* Preserve the current theme when rendered in body */
25
+ return ReactDOM.createPortal(React.createElement(Theme, null, children), (nextScopeRef === null || nextScopeRef === void 0 ? void 0 : nextScopeRef.current) || document.body);
20
26
  };
21
- export default PortalProvider;
27
+ function PortalScope(props) {
28
+ const { children } = props;
29
+ const ref = React.useRef(null);
30
+ return (React.createElement(PortalScopeContext.Provider, { value: { scopeRef: ref } }, children(ref)));
31
+ }
32
+ Portal.Scope = PortalScope;
33
+ export default Portal;
@@ -1,6 +1,11 @@
1
1
  import React from "react";
2
2
  export type Props = {
3
3
  children?: React.ReactNode;
4
- scopeRef?: React.RefObject<HTMLElement | null>;
4
+ targetRef?: React.RefObject<HTMLElement | null>;
5
+ };
6
+ export type ScopeProps<T extends HTMLElement> = {
7
+ children: (ref: React.RefObject<T>) => React.ReactNode;
8
+ };
9
+ export type Context = {
10
+ scopeRef: React.RefObject<HTMLElement | null>;
5
11
  };
6
- export type Context = Pick<Props, "scopeRef">;
@@ -1,2 +1,2 @@
1
- export { default, usePortal } from "./Portal";
1
+ export { default } from "./Portal";
2
2
  export type { Props as PortalProps } from "./Portal.types";
@@ -1 +1 @@
1
- export { default, usePortal } from "./Portal.js";
1
+ export { default } from "./Portal.js";