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.
- package/CHANGELOG.md +19 -12
- package/LICENSE-SOURCE.md +40 -0
- package/LICENSE.md +21 -37
- package/bin/clean.sh +1 -0
- package/bin/cli.js +1 -11
- package/bin/release-source.sh +7 -0
- package/bundle.css +1 -1
- package/bundle.js +10 -10
- package/cli/theming/definitions/base.d.ts +1 -1
- package/cli/theming/definitions/figma.d.ts +1 -1
- package/cli/theming/definitions/reshaped.d.ts +1 -1
- package/cli/theming/definitions/slate.d.ts +1 -1
- package/cli/theming/index.d.ts +4 -4
- package/cli/theming/index.js +7 -107
- package/components/Actionable/Actionable.js +14 -3
- package/components/Actionable/Actionable.module.css +1 -1
- package/components/Autocomplete/tests/Autocomplete.stories.js +27 -1
- package/components/Button/Button.js +2 -0
- package/components/Button/Button.module.css +1 -1
- package/components/Button/Button.types.d.ts +6 -0
- package/components/Button/ButtonGroup.d.ts +4 -0
- package/components/Button/ButtonGroup.js +9 -0
- package/components/Button/tests/Button.stories.d.ts +1 -0
- package/components/Button/tests/Button.stories.js +63 -0
- package/components/Checkbox/Checkbox.module.css +1 -1
- package/components/DropdownMenu/DropdownMenu.js +1 -1
- package/components/DropdownMenu/tests/DropdownMenu.stories.js +1 -0
- package/components/Overlay/Overlay.js +4 -4
- package/components/Radio/Radio.module.css +1 -1
- package/components/Select/Select.js +1 -1
- package/components/Slider/Slider.module.css +1 -1
- package/components/Switch/Switch.module.css +1 -1
- package/components/Tabs/Tabs.d.ts +1 -8
- package/components/Tabs/Tabs.module.css +1 -1
- package/components/Tabs/Tabs.types.d.ts +6 -7
- package/components/Tabs/TabsContext.d.ts +4 -0
- package/components/Tabs/TabsControlled.js +24 -1
- package/components/Tabs/TabsItem.d.ts +1 -8
- package/components/Tabs/TabsItem.js +22 -4
- package/components/Tabs/TabsList.js +30 -32
- package/components/Tabs/tests/Tabs.stories.d.ts +1 -0
- package/components/Tabs/tests/Tabs.stories.js +17 -0
- package/components/Toast/ToastContainer.js +1 -0
- package/components/Toast/ToastProvider.js +4 -0
- package/components/Toast/tests/Toast.stories.js +1 -0
- package/components/_private/Flyout/Flyout.types.d.ts +2 -0
- package/components/_private/Flyout/FlyoutContent.js +7 -3
- package/components/_private/Flyout/FlyoutControlled.js +8 -1
- package/components/_private/Flyout/tests/Flyout.stories.d.ts +1 -0
- package/components/_private/Flyout/tests/Flyout.stories.js +25 -0
- package/components/_private/Portal/Portal.d.ts +8 -4
- package/components/_private/Portal/Portal.js +23 -11
- package/components/_private/Portal/Portal.types.d.ts +7 -2
- package/components/_private/Portal/index.d.ts +1 -1
- package/components/_private/Portal/index.js +1 -1
- package/components/_private/Portal/tests/Portal.stories.js +11 -12
- package/config/next.d.ts +4 -5
- package/config/next.js +21 -7
- package/config/tailwind.d.ts +1 -1
- package/config/tailwind.js +3 -3
- package/hooks/_private/useFlyout.js +16 -13
- package/package.json +39 -31
- package/themes/_generator/tests/themes.stories.d.ts +6 -0
- package/themes/_generator/tests/themes.stories.js +32 -0
- package/{cli/theming → themes/_generator}/tokens/color/color.transforms.d.ts +1 -1
- package/{cli/theming → themes/_generator}/tokens/duration/duration.transforms.d.ts +1 -1
- package/{cli/theming → themes/_generator}/tokens/easing/easing.transforms.d.ts +1 -1
- package/{cli/theming → themes/_generator}/tokens/font/font.transforms.d.ts +1 -1
- package/{cli/theming → themes/_generator}/tokens/fontFamily/fontFamily.transforms.d.ts +1 -1
- package/{cli/theming → themes/_generator}/tokens/fontWeight/fontWeight.transforms.d.ts +1 -1
- package/{cli/theming → themes/_generator}/tokens/shadow/shadow.transforms.d.ts +1 -1
- package/{cli/theming → themes/_generator}/tokens/shadow/shadow.transforms.js +1 -1
- package/{cli/theming → themes/_generator}/tokens/unit/unit.transforms.d.ts +1 -1
- package/{cli/theming → themes/_generator}/tokens/viewport/viewport.transforms.d.ts +1 -1
- package/themes/_generator/transform.d.ts +7 -0
- package/themes/_generator/transform.js +57 -0
- package/{cli/theming → themes/_generator}/types.d.ts +3 -1
- package/{cli/theming → themes/_generator}/utilities/css.js +3 -1
- package/themes/_generator/utilities/generateBackgroundColors.d.ts +4 -0
- package/themes/_generator/utilities/generateBackgroundColors.js +54 -0
- package/themes/_generator/utilities/generateUnits.d.ts +4 -0
- package/themes/_generator/utilities/generateUnits.js +17 -0
- package/{cli/theming → themes/_generator}/utilities/mergeDeep.js +1 -3
- package/{cli/theming → themes/_generator}/utilities/resolveTokenReference.js +1 -3
- package/themes/index.d.ts +3 -0
- package/themes/index.js +5 -0
- package/types/config.d.ts +1 -1
- package/utilities/a11y.js +12 -3
- package/{cli/utilities → utilities}/color.d.ts +1 -1
- package/utilities/dom.d.ts +1 -0
- package/utilities/dom.js +9 -0
- package/cli/theming/definitions/minimal.d.ts +0 -3
- package/cli/theming/definitions/minimal.js +0 -80
- package/cli/utilities/tests/color.test.d.ts +0 -1
- package/cli/utilities/tests/color.test.js +0 -63
- package/styles/aspectRatio/index.test.d.ts +0 -1
- package/styles/aspectRatio/index.test.js +0 -24
- package/styles/bleed/index.test.d.ts +0 -1
- package/styles/bleed/index.test.js +0 -24
- package/styles/height/index.test.d.ts +0 -1
- package/styles/height/index.test.js +0 -27
- package/styles/inset/index.test.d.ts +0 -1
- package/styles/inset/index.test.js +0 -27
- package/styles/maxHeight/index.test.d.ts +0 -1
- package/styles/maxHeight/index.test.js +0 -27
- package/styles/maxWidth/index.test.d.ts +0 -1
- package/styles/maxWidth/index.test.js +0 -27
- package/styles/padding/index.test.d.ts +0 -1
- package/styles/padding/index.test.js +0 -24
- package/styles/position/index.test.d.ts +0 -1
- package/styles/position/index.test.js +0 -21
- package/styles/radius/index.test.d.ts +0 -1
- package/styles/radius/index.test.js +0 -24
- package/styles/width/index.test.d.ts +0 -1
- package/styles/width/index.test.js +0 -27
- package/themes/minimal/theme.css +0 -1
- package/utilities/testPresets.d.ts +0 -25
- package/utilities/testPresets.js +0 -76
- package/utilities/tests/Chain.test.d.ts +0 -1
- package/utilities/tests/Chain.test.js +0 -45
- /package/bin/{copy-release.sh → release-copy.sh} +0 -0
- /package/{cli/theming → themes/_generator}/tokens/color/color.transforms.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/color/color.types.d.ts +0 -0
- /package/{cli/theming → themes/_generator}/tokens/color/color.types.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/duration/duration.transforms.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/duration/duration.types.d.ts +0 -0
- /package/{cli/theming → themes/_generator}/tokens/duration/duration.types.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/easing/easing.transforms.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/easing/easing.types.d.ts +0 -0
- /package/{cli/theming → themes/_generator}/tokens/easing/easing.types.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/font/font.transforms.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/font/font.types.d.ts +0 -0
- /package/{cli/theming → themes/_generator}/tokens/font/font.types.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/fontFamily/fontFamily.transforms.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/fontFamily/fontFamily.types.d.ts +0 -0
- /package/{cli/theming → themes/_generator}/tokens/fontFamily/fontFamily.types.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/fontWeight/fontWeight.transforms.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/fontWeight/fontWeight.types.d.ts +0 -0
- /package/{cli/theming → themes/_generator}/tokens/fontWeight/fontWeight.types.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/shadow/shadow.types.d.ts +0 -0
- /package/{cli/theming → themes/_generator}/tokens/shadow/shadow.types.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/transforms.d.ts +0 -0
- /package/{cli/theming → themes/_generator}/tokens/transforms.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/types.d.ts +0 -0
- /package/{cli/theming → themes/_generator}/tokens/types.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/unit/unit.transforms.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/unit/unit.types.d.ts +0 -0
- /package/{cli/theming → themes/_generator}/tokens/unit/unit.types.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/viewport/viewport.transforms.js +0 -0
- /package/{cli/theming → themes/_generator}/tokens/viewport/viewport.types.d.ts +0 -0
- /package/{cli/theming → themes/_generator}/tokens/viewport/viewport.types.js +0 -0
- /package/{cli/theming → themes/_generator}/types.js +0 -0
- /package/{cli/theming → themes/_generator}/utilities/css.d.ts +0 -0
- /package/{cli/theming → themes/_generator}/utilities/mergeDeep.d.ts +0 -0
- /package/{cli/theming → themes/_generator}/utilities/mergeDefinitions.d.ts +0 -0
- /package/{cli/theming → themes/_generator}/utilities/mergeDefinitions.js +0 -0
- /package/{cli/theming → themes/_generator}/utilities/resolveTokenReference.d.ts +0 -0
- /package/{cli/utilities → utilities}/color.js +0 -0
- /package/{cli/utilities → utilities}/string.d.ts +0 -0
- /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<
|
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}.
|
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
|
-
|
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: {
|
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<
|
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,
|
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
|
-
|
25
|
-
|
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:
|
51
|
-
scaleY:
|
52
|
-
top:
|
53
|
-
left:
|
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 (
|
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
|
99
|
-
|
100
|
-
|
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
|
140
|
-
return
|
141
|
-
|
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>
|
@@ -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) => {
|
@@ -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 = (
|
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
|
-
|
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
|
-
|
1
|
+
import React from "react";
|
2
2
|
import type * as T from "./Portal.types";
|
3
|
-
export declare const
|
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
|
9
|
-
|
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
|
6
|
-
export const
|
7
|
-
return React.useContext(
|
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
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
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
|
-
|
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
|
1
|
+
export { default } from "./Portal";
|
2
2
|
export type { Props as PortalProps } from "./Portal.types";
|
@@ -1 +1 @@
|
|
1
|
-
export { default
|
1
|
+
export { default } from "./Portal.js";
|