Skip to content
This repository was archived by the owner on Jan 6, 2025. It is now read-only.

Commit c28dfc7

Browse files
ThomasBurlesontinayuangao
authored andcommitted
fix(fxFlex): improve support for 'auto' and flex-basis variations (#212)
1 parent 2340a19 commit c28dfc7

File tree

3 files changed

+48
-93
lines changed

3 files changed

+48
-93
lines changed

src/lib/flexbox/api/flex.ts

Lines changed: 33 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,9 @@ export type FlexBasisAlias = 'grow' | 'initial' | 'auto' | 'none' | 'nogrow' | '
4040
* @see https://css-tricks.com/snippets/css/a-guide-to-flexbox/
4141
*/
4242
@Directive({selector: `
43-
[fxFlex],
44-
[fxFlex.xs],
45-
[fxFlex.gt-xs],
46-
[fxFlex.sm],
47-
[fxFlex.gt-sm],
48-
[fxFlex.md],
49-
[fxFlex.gt-md],
50-
[fxFlex.lg],
51-
[fxFlex.gt-lg],
52-
[fxFlex.xl]
43+
[fxFlex],
44+
[fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl],
45+
[fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]
5346
`
5447
})
5548
export class FlexDirective extends BaseFxDirective implements OnInit, OnChanges, OnDestroy {
@@ -63,55 +56,23 @@ export class FlexDirective extends BaseFxDirective implements OnInit, OnChanges,
6356
*/
6457
protected _layoutWatcher: Subscription;
6558

66-
@Input('fxFlex') set flex(val) {
67-
this._cacheInput("flex", val);
68-
}
69-
70-
@Input('fxShrink') set shrink(val) {
71-
this._cacheInput("shrink", val);
72-
}
73-
74-
@Input('fxGrow') set grow(val) {
75-
this._cacheInput("grow", val);
76-
}
77-
78-
@Input('fxFlex.xs') set flexXs(val) {
79-
this._cacheInput('flexXs', val);
80-
}
81-
82-
@Input('fxFlex.gt-xs') set flexGtXs(val) {
83-
this._cacheInput('flexGtXs', val);
84-
};
85-
86-
@Input('fxFlex.sm') set flexSm(val) {
87-
this._cacheInput('flexSm', val);
88-
};
89-
90-
@Input('fxFlex.gt-sm') set flexGtSm(val) {
91-
this._cacheInput('flexGtSm', val);
92-
};
59+
/* tslint:disable */
60+
@Input('fxShrink') set shrink(val) { this._cacheInput("shrink", val); };
61+
@Input('fxGrow') set grow(val) { this._cacheInput("grow", val); };
9362

94-
@Input('fxFlex.md') set flexMd(val) {
95-
this._cacheInput('flexMd', val);
96-
};
97-
98-
@Input('fxFlex.gt-md') set flexGtMd(val) {
99-
this._cacheInput('flexGtMd', val);
100-
};
101-
102-
@Input('fxFlex.lg') set flexLg(val) {
103-
this._cacheInput('flexLg', val);
104-
};
105-
106-
@Input('fxFlex.gt-lg') set flexGtLg(val) {
107-
this._cacheInput('flexGtLg', val);
108-
};
109-
110-
@Input('fxFlex.xl') set flexXl(val) {
111-
this._cacheInput('flexXl', val);
112-
};
63+
@Input('fxFlex') set flex(val) { this._cacheInput("flex", val); };
64+
@Input('fxFlex.xs') set flexXs(val) { this._cacheInput('flexXs', val); };
65+
@Input('fxFlex.sm') set flexSm(val) { this._cacheInput('flexSm', val); };
66+
@Input('fxFlex.md') set flexMd(val) { this._cacheInput('flexMd', val); };
67+
@Input('fxFlex.lg') set flexLg(val) { this._cacheInput('flexLg', val); };
68+
@Input('fxFlex.xl') set flexXl(val) { this._cacheInput('flexXl', val); };
11369

70+
@Input('fxFlex.gt-xs') set flexGtXs(val) { this._cacheInput('flexGtXs', val); };
71+
@Input('fxFlex.gt-sm') set flexGtSm(val) { this._cacheInput('flexGtSm', val); };
72+
@Input('fxFlex.gt-md') set flexGtMd(val) { this._cacheInput('flexGtMd', val); };
73+
@Input('fxFlex.gt-lg') set flexGtLg(val) { this._cacheInput('flexGtLg', val); };
11474

75+
/* tslint:enable */
11576
// Explicitly @SkipSelf on LayoutDirective and LayoutWrapDirective because we want the
11677
// parent flex container for this flex item.
11778
constructor(monitor: MediaMonitor,
@@ -215,13 +176,14 @@ export class FlexDirective extends BaseFxDirective implements OnInit, OnChanges,
215176
// ≥2 (integer n): Stretch. Will be n times the size of other elements
216177
// with 'flex-grow: 1' on the same row.
217178

218-
// Use `null` to clear existing styles.
219-
let clearStyles = {
179+
let hasCalc = String(basis).indexOf('calc') > -1;
180+
let clearStyles = { // Use `null` to clear existing styles.
220181
'max-width': null,
221182
'max-height': null,
222183
'min-width': null,
223184
'min-height': null
224185
};
186+
225187
switch (basis || '') {
226188
case '':
227189
css = extendObject(clearStyles, {'flex': '1 1 0.000000001px'});
@@ -247,7 +209,6 @@ export class FlexDirective extends BaseFxDirective implements OnInit, OnChanges,
247209
css = extendObject(clearStyles, {'flex': '0 0 auto'});
248210
break;
249211
default:
250-
let hasCalc = String(basis).indexOf('calc') > -1;
251212
let isPercent = String(basis).indexOf('%') > -1 && !hasCalc;
252213

253214
isValue = hasCalc ||
@@ -267,27 +228,26 @@ export class FlexDirective extends BaseFxDirective implements OnInit, OnChanges,
267228

268229
// Set max-width = basis if using layout-wrap
269230
// tslint:disable-next-line:max-line-length
270-
// @see https://github.com/philipwalton/flexbugs#11-min-and-max-size-declarations-are-ignored-when-wrappifl-flex-items
231+
// @see http://bit.ly/2m5pZVI
271232

272233
css = extendObject(clearStyles, { // fix issue #5345
273234
'flex': `${grow} ${shrink} ${(isValue || this._wrap) ? basis : '100%'}`,
274235
});
275236
break;
276237
}
277238

278-
let max = (direction === 'row') ? 'max-width' : 'max-height';
279-
let min = (direction === 'row') ? 'min-width' : 'min-height';
280-
281-
let usingCalc = (String(basis).indexOf('calc') > -1) || (basis == 'auto');
282-
let isPx = String(basis).indexOf('px') > -1 || usingCalc;
283-
284-
285-
// make box inflexible when shrink and grow are both zero
286-
// should not set a min when the grow is zero
287-
// should not set a max when the shrink is zero
288-
let isFixed = !grow && !shrink;
289-
css[min] = (basis == '0%') ? 0 : isFixed || (isPx && grow) ? basis : null;
290-
css[max] = (basis == '0%') ? 0 : isFixed || (!usingCalc && shrink) ? basis : null;
239+
if (basis !== 'auto') {
240+
let max = (direction === 'row') ? 'max-width' : 'max-height';
241+
let min = (direction === 'row') ? 'min-width' : 'min-height';
242+
let isPx = String(basis).indexOf('px') > -1 || hasCalc;
243+
244+
// make box inflexible when shrink and grow are both zero
245+
// * do not set a min when the grow is zero
246+
// * do not set a max when the shrink is zero
247+
let isFixed = !grow && !shrink;
248+
css[min] = (basis == '0%') ? 0 : isFixed || (isPx && grow) ? basis : null;
249+
css[max] = (basis == '0%') ? 0 : isFixed || (!hasCalc && shrink) ? basis : null;
250+
}
291251

292252
return extendObject(css, {'box-sizing': 'border-box'});
293253
}

src/lib/utils/basis-validator.spec.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ describe('validateBasis', () => {
3030
expect( result ).toEqual('3 3 calc(15em + 20px)');
3131
});
3232

33+
it('should validate calc() expression with multiple operators', () => {
34+
let result = validateBasis('calc(100% / 7 * 2)').join(" ");
35+
expect( result ).toEqual('1 1 calc(100% / 7 * 2)');
36+
});
37+
3338
it('should validate with complex value that includes a bad calc() expression', () => {
3439
let result = validateBasis('3 3 calc(15em +20px)').join(" ");
3540
expect( result ).toEqual('3 3 calc(15em + 20px)');

src/lib/utils/basis-validator.ts

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,6 @@
22
* The flex API permits 3 or 1 parts of the value:
33
* - `flex-grow flex-shrink flex-basis`, or
44
* - `flex-basis`
5-
* Flex-Basis values can be complicated short-hand versions such as:
6-
* - "3 3 calc(15em + 20px)"
7-
* - "calc(15em + 20px)"
8-
* - "calc(15em+20px)"
9-
* - "37px"
10-
* = "43%"
115
*/
126
export function validateBasis(basis: string, grow = "1", shrink = "1"): string[] {
137
let parts = [grow, shrink, basis];
@@ -25,28 +19,24 @@ export function validateBasis(basis: string, grow = "1", shrink = "1"): string[]
2519
} else {
2620
let matches = basis.split(" ");
2721
parts = (matches.length === 3) ? matches : [
28-
grow, shrink, basis
29-
];
22+
grow, shrink, basis
23+
];
3024
}
3125

3226
return parts;
3327
}
3428

3529

3630
/**
37-
* Calc expressions require whitespace before & after the operator
31+
* Calc expressions require whitespace before & after any expression operators
3832
* This is a simple, crude whitespace padding solution.
33+
* - "3 3 calc(15em + 20px)"
34+
* - calc(100% / 7 * 2)
35+
* - "calc(15em + 20px)"
36+
* - "calc(15em+20px)"
37+
* - "37px"
38+
* = "43%"
3939
*/
4040
function _validateCalcValue(calc: string): string {
41-
let operators = ["+", "-", "*", "/"];
42-
let findOperator = () => operators.reduce((index, operator) => {
43-
return index || (calc.indexOf(operator) + 1);
44-
}, 0);
45-
46-
if (findOperator() > 0) {
47-
calc = calc.replace(/[\s]/g, "");
48-
let offset = findOperator() - 1;
49-
calc = calc.substr(0, offset) + " " + calc.charAt(offset) + " " + calc.substr(offset + 1);
50-
}
51-
return calc;
41+
return calc.replace(/[\s]/g, "").replace(/[\/\*\+\-]/g, " $& ");
5242
}

0 commit comments

Comments
 (0)