-
Notifications
You must be signed in to change notification settings - Fork 2.9k
feat(react-positioning): simplify maxSize options #28649
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
YuanboXue-Amber
merged 14 commits into
microsoft:master
from
YuanboXue-Amber:maxsize-simple
Jul 27, 2023
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
f687bb2
wip
YuanboXue-Amber 2f8edb4
comments
YuanboXue-Amber 7f86bb8
try to make it better
YuanboXue-Amber 793b2ef
chg
YuanboXue-Amber c80a839
use middleware
YuanboXue-Amber 7cbc32c
update flag
YuanboXue-Amber 2295a56
test inline overflow
YuanboXue-Amber 5d74325
comment
YuanboXue-Amber 5502783
use clip to test overflow
YuanboXue-Amber 55d8f24
normalize autosize once
YuanboXue-Amber f2af801
nit fix in test
YuanboXue-Amber 7378dc9
rename autoSize to rawAutoSize, and normalizeAutoSize to autoSize
YuanboXue-Amber f522053
apply suggestions
YuanboXue-Amber a32e6b5
fix test
YuanboXue-Amber File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
change/@fluentui-react-positioning-bc570315-c0a5-4a0f-a762-5fb18e58b4e8.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "type": "minor", | ||
| "comment": "feat: simplify autoSize options to make 'always'/'height-always'/'width-always' equivalent to true/'height'/'width'.", | ||
| "packageName": "@fluentui/react-positioning", | ||
| "email": "yuanboxue@microsoft.com", | ||
| "dependentChangeType": "patch" | ||
| } |
79 changes: 53 additions & 26 deletions
79
packages/react-components/react-positioning/src/middleware/maxSize.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,41 +1,68 @@ | ||
| import { size } from '@floating-ui/dom'; | ||
| import type { Middleware } from '@floating-ui/dom'; | ||
| import type { PositioningOptions } from '../types'; | ||
| import type { NormalizedAutoSize, PositioningOptions } from '../types'; | ||
| import { getBoundary } from '../utils/getBoundary'; | ||
| export interface MaxSizeMiddlewareOptions extends Pick<PositioningOptions, 'overflowBoundary'> { | ||
| container: HTMLElement | null; | ||
| } | ||
|
|
||
| export function maxSize(autoSize: PositioningOptions['autoSize'], options: MaxSizeMiddlewareOptions): Middleware { | ||
| /** | ||
| * floating-ui `size` middleware uses floating element's height/width to calculate available height/width. | ||
| * This middleware only runs once per lifecycle, resetting styles applied by maxSize from previous lifecycle. | ||
| * Then floating element's original size is restored and `size` middleware can calculate available height/width correctly. | ||
| */ | ||
| export const resetMaxSize = (autoSize: NormalizedAutoSize): Middleware => ({ | ||
| name: 'resetMaxSize', | ||
| fn({ middlewareData: { maxSizeAlreadyReset }, elements }) { | ||
| if (maxSizeAlreadyReset) { | ||
| return {}; | ||
| } | ||
|
|
||
| const { applyMaxWidth, applyMaxHeight } = autoSize; | ||
| if (applyMaxWidth) { | ||
| elements.floating.style.removeProperty('box-sizing'); | ||
| elements.floating.style.removeProperty('max-width'); | ||
| elements.floating.style.removeProperty('width'); | ||
| } | ||
| if (applyMaxHeight) { | ||
| elements.floating.style.removeProperty('box-sizing'); | ||
| elements.floating.style.removeProperty('max-height'); | ||
| elements.floating.style.removeProperty('height'); | ||
| } | ||
|
|
||
| return { | ||
| data: { maxSizeAlreadyReset: true }, | ||
| reset: { rects: true }, | ||
| }; | ||
| }, | ||
| }); | ||
|
|
||
| export function maxSize(autoSize: NormalizedAutoSize, options: MaxSizeMiddlewareOptions): Middleware { | ||
| const { container, overflowBoundary } = options; | ||
| return size({ | ||
| ...(overflowBoundary && { altBoundary: true, boundary: getBoundary(container, overflowBoundary) }), | ||
| apply({ availableHeight, availableWidth, elements, rects }) { | ||
| if (autoSize) { | ||
| const applyMaxSizeStyles = (apply: boolean, dimension: 'width' | 'height', availableSize: number) => { | ||
| if (!apply) { | ||
| return; | ||
| } | ||
|
|
||
| elements.floating.style.setProperty('box-sizing', 'border-box'); | ||
| } | ||
|
|
||
| const applyMaxWidth = autoSize === 'always' || autoSize === 'width-always'; | ||
| const widthOverflow = rects.floating.width > availableWidth && (autoSize === true || autoSize === 'width'); | ||
|
|
||
| const applyMaxHeight = autoSize === 'always' || autoSize === 'height-always'; | ||
| const heightOverflow = rects.floating.height > availableHeight && (autoSize === true || autoSize === 'height'); | ||
|
|
||
| if (applyMaxHeight || heightOverflow) { | ||
| elements.floating.style.setProperty('max-height', `${availableHeight}px`); | ||
| } | ||
| if (heightOverflow) { | ||
| elements.floating.style.setProperty('height', `${availableHeight}px`); | ||
| elements.floating.style.setProperty('overflow-y', 'auto'); | ||
| } | ||
|
|
||
| if (applyMaxWidth || widthOverflow) { | ||
| elements.floating.style.setProperty('max-width', `${availableWidth}px`); | ||
| } | ||
| if (widthOverflow) { | ||
| elements.floating.style.setProperty('width', `${availableWidth}px`); | ||
| elements.floating.style.setProperty('overflow-x', 'auto'); | ||
| } | ||
| elements.floating.style.setProperty(`max-${dimension}`, `${availableSize}px`); | ||
|
|
||
| if (rects.floating[dimension] > availableSize) { | ||
| elements.floating.style.setProperty(dimension, `${availableSize}px`); | ||
|
|
||
| const axis = dimension === 'width' ? 'x' : 'y'; | ||
| if (!elements.floating.style.getPropertyValue(`overflow-${axis}`)) { | ||
| elements.floating.style.setProperty(`overflow-${axis}`, 'auto'); | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| const { applyMaxWidth, applyMaxHeight } = autoSize; | ||
| applyMaxSizeStyles(applyMaxWidth, 'width', availableWidth); | ||
| applyMaxSizeStyles(applyMaxHeight, 'height', availableHeight); | ||
| }, | ||
| }); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
packages/react-components/react-positioning/src/utils/normalizeAutoSize.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| import { normalizeAutoSize } from './normalizeAutoSize'; | ||
|
|
||
| describe('normalizeAutoSize', () => { | ||
| const cases = [ | ||
| [ | ||
| 'always', | ||
| { | ||
| applyMaxWidth: true, | ||
| applyMaxHeight: true, | ||
| }, | ||
| ], | ||
| [ | ||
| true, | ||
| { | ||
| applyMaxWidth: true, | ||
| applyMaxHeight: true, | ||
| }, | ||
| ], | ||
| [ | ||
| 'width-always', | ||
| { | ||
| applyMaxWidth: true, | ||
| applyMaxHeight: false, | ||
| }, | ||
| ], | ||
| [ | ||
| 'width', | ||
| { | ||
| applyMaxWidth: true, | ||
| applyMaxHeight: false, | ||
| }, | ||
| ], | ||
| [ | ||
| 'height-always', | ||
| { | ||
| applyMaxWidth: false, | ||
| applyMaxHeight: true, | ||
| }, | ||
| ], | ||
| [ | ||
| 'height', | ||
| { | ||
| applyMaxWidth: false, | ||
| applyMaxHeight: true, | ||
| }, | ||
| ], | ||
| [false, false], | ||
| ] as const; | ||
|
|
||
| it.each(cases)('should normalize autoSize', (rawAutoSize, normalizedAutoSize) => { | ||
| expect(normalizeAutoSize(rawAutoSize)).toEqual(normalizedAutoSize); | ||
| }); | ||
| }); |
34 changes: 34 additions & 0 deletions
34
packages/react-components/react-positioning/src/utils/normalizeAutoSize.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import type { NormalizedAutoSize, PositioningOptions } from '../types'; | ||
|
|
||
| /** | ||
| * AutoSizes contains many options from historic implementation. | ||
| * Now options 'always'/'height-always'/'width-always' are obsolete. | ||
| * This function maps them to true/'height'/'width' | ||
| */ | ||
| export const normalizeAutoSize = (autoSize?: PositioningOptions['autoSize']): NormalizedAutoSize | false => { | ||
| switch (autoSize) { | ||
| case 'always': | ||
|
YuanboXue-Amber marked this conversation as resolved.
|
||
| case true: | ||
| return { | ||
| applyMaxWidth: true, | ||
| applyMaxHeight: true, | ||
| }; | ||
|
|
||
| case 'width-always': | ||
| case 'width': | ||
| return { | ||
| applyMaxWidth: true, | ||
| applyMaxHeight: false, | ||
| }; | ||
|
|
||
| case 'height-always': | ||
| case 'height': | ||
| return { | ||
| applyMaxWidth: false, | ||
| applyMaxHeight: true, | ||
| }; | ||
|
|
||
| default: | ||
| return false; | ||
| } | ||
| }; | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.