diff --git a/packages/eslint-plugin/__tests__/stylex-valid-styles-test.js b/packages/eslint-plugin/__tests__/stylex-valid-styles-test.js index 767dd179..e71a1210 100644 --- a/packages/eslint-plugin/__tests__/stylex-valid-styles-test.js +++ b/packages/eslint-plugin/__tests__/stylex-valid-styles-test.js @@ -354,6 +354,53 @@ eslintTester.run('stylex-valid-styles', rule.default, { 'width': '30vw', }, })`, + `import stylex from "stylex"; + stylex.create({ + default: { + 'contain': '300px', + }, + })`, + `import stylex from "stylex"; + stylex.create({ + default: { + 'containIntrinsicSize': '300px', + }, + })`, + `import stylex from "stylex"; + stylex.create({ + default: { + 'containIntrinsicSize': 'auto 300px', + }, + })`, + `import stylex from "stylex"; + stylex.create({ + default: { + 'containIntrinsicInlineSize': '300px', + 'containIntrinsicBlockSize': '200px', + }, + })`, + `import stylex from "stylex"; + stylex.create({ + default: { + 'containIntrinsicInlineSize': 'auto 300px', + 'containIntrinsicBlockSize': 'auto 200px', + }, + })`, + `import stylex from "stylex"; + stylex.create({ + default: { + 'containIntrinsicWidth': '300px', + 'containIntrinsicHeight': '200px', + }, + })`, + `import stylex from "stylex"; + stylex.create({ + default: { + 'containIntrinsicWidth': 'auto 300px', + 'containIntrinsicHeight': 'auto 200px', + }, + })`, + // test for absolute width `import stylex from "stylex"; stylex.create({ diff --git a/packages/eslint-plugin/src/stylex-valid-styles.js b/packages/eslint-plugin/src/stylex-valid-styles.js index fc710134..0e0b47ef 100644 --- a/packages/eslint-plugin/src/stylex-valid-styles.js +++ b/packages/eslint-plugin/src/stylex-valid-styles.js @@ -712,6 +712,7 @@ const display = makeUnionRule( makeLiteralRule('none'), makeLiteralRule('inline'), makeLiteralRule('block'), + makeLiteralRule('flow-root'), makeLiteralRule('list-item'), makeLiteralRule('inline-list-item'), makeLiteralRule('inline-block'), @@ -1793,6 +1794,11 @@ const CSSProperties = { columnWidth: columnWidth, columns: columns, contain: contain, + containIntrinsicSize: makeUnionRule(isNumber, isString), + containIntrinsicBlockSize: makeUnionRule(isNumber, isString), + containIntrinsicInlineSize: makeUnionRule(isNumber, isString), + containIntrinsicHeight: makeUnionRule(isNumber, isString), + containIntrinsicWidth: makeUnionRule(isNumber, isString), containerType: makeUnionRule('normal', 'size', 'inline-size'), containerName: isString, content: content, @@ -2356,8 +2362,6 @@ const stylexValidStyles = { const legacyProps: PropLimits = { 'grid*': { limit: null, reason: legacyReason }, - rowGap: { limit: null, reason: legacyReason }, - columnGap: { limit: null, reason: legacyReason }, 'mask+([a-zA-Z])': { limit: null, reason: legacyReason }, blockOverflow: { limit: null, reason: legacyReason }, inlineOverflow: { limit: null, reason: legacyReason }, diff --git a/packages/shared/__tests__/flatten-raw-style-objects/legacy-shorthand-expansion-test.js b/packages/shared/__tests__/flatten-raw-style-objects/legacy-shorthand-expansion-test.js index 113f254d..f69ba81d 100644 --- a/packages/shared/__tests__/flatten-raw-style-objects/legacy-shorthand-expansion-test.js +++ b/packages/shared/__tests__/flatten-raw-style-objects/legacy-shorthand-expansion-test.js @@ -42,6 +42,34 @@ describe('Flatten Style Object with legacy shorthand expansion', () => { ]); }); + test('should expand simple gap values', () => { + expect( + flattenRawStyleObject( + { + gap: 10, + }, + options, + ), + ).toEqual([ + ['rowGap', new PreRule('rowGap', 10)], + ['columnGap', new PreRule('columnGap', 10)], + ]); + }); + + test('should expand simple containIntrinsicSize values', () => { + expect( + flattenRawStyleObject( + { + containIntrinsicSize: 10, + }, + options, + ), + ).toEqual([ + ['containIntrinsicWidth', new PreRule('containIntrinsicWidth', 10)], + ['containIntrinsicHeight', new PreRule('containIntrinsicHeight', 10)], + ]); + }); + test('should expand simple shorthands', () => { expect(flattenRawStyleObject({ margin: 10 }, options)).toEqual([ ['marginTop', new PreRule('marginTop', 10)], @@ -79,6 +107,69 @@ describe('Flatten Style Object with legacy shorthand expansion', () => { ]); }); + test('should expand simple gap with space-separated values', () => { + expect( + flattenRawStyleObject( + { + gap: '10px 20px', + }, + options, + ), + ).toEqual([ + ['rowGap', new PreRule('rowGap', '10px')], + ['columnGap', new PreRule('columnGap', '20px')], + ]); + }); + + test('should expand simple containIntrinsicSize with space-separated values', () => { + const w = 'containIntrinsicWidth'; + const h = 'containIntrinsicHeight'; + expect( + flattenRawStyleObject( + { + containIntrinsicSize: '10px 20px', + }, + options, + ), + ).toEqual([ + [w, new PreRule(w, '10px')], + [h, new PreRule(h, '20px')], + ]); + expect( + flattenRawStyleObject( + { + containIntrinsicSize: 'auto 10px 20px', + }, + options, + ), + ).toEqual([ + [w, new PreRule(w, 'auto 10px')], + [h, new PreRule(h, '20px')], + ]); + expect( + flattenRawStyleObject( + { + containIntrinsicSize: '10px auto 20px', + }, + options, + ), + ).toEqual([ + [w, new PreRule(w, '10px')], + [h, new PreRule(h, 'auto 20px')], + ]); + expect( + flattenRawStyleObject( + { + containIntrinsicSize: 'auto 10px auto 20px', + }, + options, + ), + ).toEqual([ + [w, new PreRule(w, 'auto 10px')], + [h, new PreRule(h, 'auto 20px')], + ]); + }); + test('should expand shorthands with fallbacks', () => { expect( flattenRawStyleObject({ margin: ['10vh 20px', '10dvh 20px'] }, options), diff --git a/packages/shared/src/preprocess-rules/legacy-expand-shorthands.js b/packages/shared/src/preprocess-rules/legacy-expand-shorthands.js index f8432e0e..0f677007 100644 --- a/packages/shared/src/preprocess-rules/legacy-expand-shorthands.js +++ b/packages/shared/src/preprocess-rules/legacy-expand-shorthands.js @@ -172,6 +172,31 @@ const shorthands: $ReadOnly<{ [key: string]: (TStyleValue) => TReturn }> = { ]; }, + containIntrinsicSize: (rawValue: TStyleValue): TReturn => { + const parts = splitValue(rawValue); + + // combine any part which is "auto" with the subsequent part + // ['auto', 'x', 'auto', 'y'] => ['auto x', 'auto y'] + // ['auto', 'x', 'y'] => ['auto x', 'y'] + // ['x', 'auto', 'y'] => ['x', 'auto y'] + // ['x', 'y'] => ['x', 'y'] + const [width, height = width] = parts.reduce( + (coll: Array, part: number | string | null) => { + const lastElement = coll[coll.length - 1]; + if (lastElement === 'auto' && part != null) { + return [...coll.slice(0, -1), `auto ${part}`]; + } + return [...coll, part]; + }, + [], + ); + + return [ + ['containIntrinsicWidth', width], + ['containIntrinsicHeight', height], + ]; + }, + inset: (rawValue: TStyleValue): TReturn => [ ['top', rawValue], ['end', rawValue], diff --git a/packages/stylex/src/StyleXCSSTypes.js b/packages/stylex/src/StyleXCSSTypes.js index 60909039..00425c4e 100644 --- a/packages/stylex/src/StyleXCSSTypes.js +++ b/packages/stylex/src/StyleXCSSTypes.js @@ -115,7 +115,7 @@ type backfaceVisibility = 'visible' | 'hidden'; // type background = string | finalBgLayer; type backgroundAttachment = attachment; type backgroundBlendMode = blendMode; -type backgroundClip = box; +type backgroundClip = box | 'text'; type backgroundColor = color; type backgroundImage = bgImage; type backgroundOrigin = box; @@ -250,6 +250,7 @@ type display = | 'inherit' | 'inline' | 'block' + | 'flow-root' | 'list-item' | 'inline-list-item' | 'inline-block' @@ -544,7 +545,7 @@ type outlineStyle = 'auto' | brStyle; type outlineWidth = borderWidth; type overflow = 'visible' | 'hidden' | 'clip' | 'scroll' | 'auto'; type overflowAnchor = 'auto' | 'none'; -type overflowWrap = 'normal' | 'break-word'; +type overflowWrap = 'normal' | 'break-word' | 'anywhere'; type overflowX = overflow; type overflowY = overflow; type overscrollBehavior = 'none' | 'contain' | 'auto'; @@ -583,7 +584,23 @@ type rubyMerge = 'separate' | 'collapse' | 'auto'; type rubyPosition = 'over' | 'under' | 'inter-character'; type scrollBehavior = 'auto' | 'smooth'; type scrollSnapAlign = 'none' | 'start' | 'end' | 'center'; -type scrollSnapType = 'none' | 'x mandatory' | 'y mandatory'; +type scrollSnapType = + | 'none' + | 'block mandatory' + | 'block proximity' + | 'block' + | 'both mandatory' + | 'both proximity' + | 'both' + | 'inline mandatory' + | 'inline proximity' + | 'inline' + | 'x' + | 'x mandatory' + | 'x proximity' + | 'y' + | 'y mandatory' + | 'y proximity'; type shapeImageThreshold = number | string; type shapeMargin = lengthPercentage; type shapeOutside = 'none' | shapeBox | string; @@ -1119,8 +1136,8 @@ export type CSSProperties = $ReadOnly<{ containIntrinsicSize?: all | number | string, containIntrinsicBlockSize?: all | number | string, containIntrinsicInlineSize?: all | number | string, - containIntrinsicHeightSize?: all | number | string, - containIntrinsicWidthSize?: all | number | string, + containIntrinsicHeight?: all | number | string, + containIntrinsicWidth?: all | number | string, container?: all | string, containerName?: all | string,