diff --git a/packages/spark_css/CHANGELOG.md b/packages/spark_css/CHANGELOG.md index 80a5209..a7fb5c1 100644 --- a/packages/spark_css/CHANGELOG.md +++ b/packages/spark_css/CHANGELOG.md @@ -31,6 +31,11 @@ - **Feat**: Added `CssIsolation` sealed class for `isolation` property with `.auto`, `.isolate` keywords, plus `.variable()`, `.raw()`, and `.global()` escape hatches. - **Feat**: Added `CssMixBlendMode` sealed class for `mix-blend-mode` property with `.normal`, `.multiply`, `.screen`, `.overlay`, `.darken`, `.lighten`, `.colorDodge`, `.colorBurn`, `.hardLight`, `.softLight`, `.difference`, `.exclusion`, `.hue`, `.saturation`, `.color`, `.luminosity` keywords, plus `.variable()`, `.raw()`, and `.global()` escape hatches. - **Feat**: Added `CssBackgroundBlendMode` sealed class for `background-blend-mode` property with `.normal`, `.multiply`, `.screen`, `.overlay`, `.darken`, `.lighten`, `.colorDodge`, `.colorBurn`, `.hardLight`, `.softLight`, `.difference`, `.exclusion`, `.hue`, `.saturation`, `.color`, `.luminosity` keywords, plus `.variable()`, `.raw()`, and `.global()` escape hatches. +- **Feat**: Added `CssContain` sealed class for `contain` property with `.none`, `.strict`, `.content` keyword shortcuts, `.size`, `.layout`, `.style`, `.paint` individual keyword constants, and `.flags()` factory for composing individual containment values, plus `.variable()`, `.raw()`, and `.global()` escape hatches. +- **Feat**: Added `CssWillChange` sealed class for `will-change` property with `.auto`, `.scrollPosition`, `.contents` keywords and `.properties()` factory for arbitrary CSS property names, plus `.variable()`, `.raw()`, and `.global()` escape hatches. +- **Feat**: Added `CssTouchAction` sealed class for `touch-action` property with `.auto`, `.none`, `.manipulation` standalone keywords, `.panX`, `.panLeft`, `.panRight`, `.panY`, `.panUp`, `.panDown`, `.pinchZoom` combinable keywords, and `.combine()` factory, plus `.variable()`, `.raw()`, and `.global()` escape hatches. +- **Feat**: Added `CssUserSelect` sealed class for `user-select` property with `.none`, `.auto`, `.text`, `.all`, `.contain` keywords, plus `.variable()`, `.raw()`, and `.global()` escape hatches. +- **Feat**: Added `CssHyphens` sealed class for `hyphens` property with `.none`, `.manual`, `.auto` keywords, plus `.variable()`, `.raw()`, and `.global()` escape hatches. ### Changed diff --git a/packages/spark_css/lib/src/css_types/css_contain.dart b/packages/spark_css/lib/src/css_types/css_contain.dart new file mode 100644 index 0000000..4c146e4 --- /dev/null +++ b/packages/spark_css/lib/src/css_types/css_contain.dart @@ -0,0 +1,86 @@ +import 'css_value.dart'; + +/// CSS contain property values. +sealed class CssContain implements CssValue { + const CssContain._(); + + static const CssContain none = _CssContainKeyword('none'); + static const CssContain strict = _CssContainKeyword('strict'); + static const CssContain content = _CssContainKeyword('content'); + static const CssContain size = _CssContainKeyword('size'); + static const CssContain layout = _CssContainKeyword('layout'); + static const CssContain style = _CssContainKeyword('style'); + static const CssContain paint = _CssContainKeyword('paint'); + + /// Constructs a `contain` value from boolean flags. + /// + /// Active flags are joined with spaces in the order: size, layout, style, + /// paint. Returns `none` if no flags are true. + factory CssContain.flags({bool size, bool layout, bool style, bool paint}) = + _CssContainFlags; + + /// CSS variable reference. + factory CssContain.variable(String varName) = _CssContainVariable; + + /// Raw CSS value escape hatch. + factory CssContain.raw(String value) = _CssContainRaw; + + /// Global keyword (inherit, initial, unset, revert). + factory CssContain.global(CssGlobal global) = _CssContainGlobal; +} + +final class _CssContainKeyword extends CssContain { + final String keyword; + const _CssContainKeyword(this.keyword) : super._(); + + @override + String toCss() => keyword; +} + +final class _CssContainFlags extends CssContain { + final bool size; + final bool layout; + final bool style; + final bool paint; + + const _CssContainFlags({ + this.size = false, + this.layout = false, + this.style = false, + this.paint = false, + }) : super._(); + + @override + String toCss() { + final parts = []; + if (size) parts.add('size'); + if (layout) parts.add('layout'); + if (style) parts.add('style'); + if (paint) parts.add('paint'); + return parts.isEmpty ? 'none' : parts.join(' '); + } +} + +final class _CssContainVariable extends CssContain { + final String varName; + const _CssContainVariable(this.varName) : super._(); + + @override + String toCss() => 'var(--$varName)'; +} + +final class _CssContainRaw extends CssContain { + final String value; + const _CssContainRaw(this.value) : super._(); + + @override + String toCss() => value; +} + +final class _CssContainGlobal extends CssContain { + final CssGlobal global; + const _CssContainGlobal(this.global) : super._(); + + @override + String toCss() => global.toCss(); +} diff --git a/packages/spark_css/lib/src/css_types/css_hyphens.dart b/packages/spark_css/lib/src/css_types/css_hyphens.dart new file mode 100644 index 0000000..d6bcf8f --- /dev/null +++ b/packages/spark_css/lib/src/css_types/css_hyphens.dart @@ -0,0 +1,51 @@ +import 'css_value.dart'; + +/// CSS hyphens property values. +sealed class CssHyphens implements CssValue { + const CssHyphens._(); + + static const CssHyphens none = _CssHyphensKeyword('none'); + static const CssHyphens manual = _CssHyphensKeyword('manual'); + static const CssHyphens auto = _CssHyphensKeyword('auto'); + + /// CSS variable reference. + factory CssHyphens.variable(String varName) = _CssHyphensVariable; + + /// Raw CSS value escape hatch. + factory CssHyphens.raw(String value) = _CssHyphensRaw; + + /// Global keyword (inherit, initial, unset, revert). + factory CssHyphens.global(CssGlobal global) = _CssHyphensGlobal; +} + +final class _CssHyphensKeyword extends CssHyphens { + final String keyword; + const _CssHyphensKeyword(this.keyword) : super._(); + + @override + String toCss() => keyword; +} + +final class _CssHyphensVariable extends CssHyphens { + final String varName; + const _CssHyphensVariable(this.varName) : super._(); + + @override + String toCss() => 'var(--$varName)'; +} + +final class _CssHyphensRaw extends CssHyphens { + final String value; + const _CssHyphensRaw(this.value) : super._(); + + @override + String toCss() => value; +} + +final class _CssHyphensGlobal extends CssHyphens { + final CssGlobal global; + const _CssHyphensGlobal(this.global) : super._(); + + @override + String toCss() => global.toCss(); +} diff --git a/packages/spark_css/lib/src/css_types/css_touch_action.dart b/packages/spark_css/lib/src/css_types/css_touch_action.dart new file mode 100644 index 0000000..495ffd3 --- /dev/null +++ b/packages/spark_css/lib/src/css_types/css_touch_action.dart @@ -0,0 +1,75 @@ +import 'css_value.dart'; + +/// CSS touch-action property values. +sealed class CssTouchAction implements CssValue { + const CssTouchAction._(); + + static const CssTouchAction auto = _CssTouchActionKeyword('auto'); + static const CssTouchAction none = _CssTouchActionKeyword('none'); + static const CssTouchAction manipulation = _CssTouchActionKeyword( + 'manipulation', + ); + static const CssTouchAction panX = _CssTouchActionKeyword('pan-x'); + static const CssTouchAction panLeft = _CssTouchActionKeyword('pan-left'); + static const CssTouchAction panRight = _CssTouchActionKeyword('pan-right'); + static const CssTouchAction panY = _CssTouchActionKeyword('pan-y'); + static const CssTouchAction panUp = _CssTouchActionKeyword('pan-up'); + static const CssTouchAction panDown = _CssTouchActionKeyword('pan-down'); + static const CssTouchAction pinchZoom = _CssTouchActionKeyword('pinch-zoom'); + + /// Combines multiple touch-action values. + /// + /// Example: `CssTouchAction.combine([CssTouchAction.panX, CssTouchAction.pinchZoom])` + /// produces `pan-x pinch-zoom`. + factory CssTouchAction.combine(List values) = + _CssTouchActionCombined; + + /// CSS variable reference. + factory CssTouchAction.variable(String varName) = _CssTouchActionVariable; + + /// Raw CSS value escape hatch. + factory CssTouchAction.raw(String value) = _CssTouchActionRaw; + + /// Global keyword (inherit, initial, unset, revert). + factory CssTouchAction.global(CssGlobal global) = _CssTouchActionGlobal; +} + +final class _CssTouchActionKeyword extends CssTouchAction { + final String keyword; + const _CssTouchActionKeyword(this.keyword) : super._(); + + @override + String toCss() => keyword; +} + +final class _CssTouchActionCombined extends CssTouchAction { + final List values; + const _CssTouchActionCombined(this.values) : super._(); + + @override + String toCss() => values.map((v) => v.toCss()).join(' '); +} + +final class _CssTouchActionVariable extends CssTouchAction { + final String varName; + const _CssTouchActionVariable(this.varName) : super._(); + + @override + String toCss() => 'var(--$varName)'; +} + +final class _CssTouchActionRaw extends CssTouchAction { + final String value; + const _CssTouchActionRaw(this.value) : super._(); + + @override + String toCss() => value; +} + +final class _CssTouchActionGlobal extends CssTouchAction { + final CssGlobal global; + const _CssTouchActionGlobal(this.global) : super._(); + + @override + String toCss() => global.toCss(); +} diff --git a/packages/spark_css/lib/src/css_types/css_types.dart b/packages/spark_css/lib/src/css_types/css_types.dart index 97f20af..d1bd2ea 100644 --- a/packages/spark_css/lib/src/css_types/css_types.dart +++ b/packages/spark_css/lib/src/css_types/css_types.dart @@ -19,6 +19,7 @@ export 'css_border_radius.dart'; export 'css_box_shadow.dart'; export 'css_box_sizing.dart'; export 'css_color.dart'; +export 'css_contain.dart'; export 'css_content.dart'; export 'css_cursor.dart'; export 'css_display.dart'; @@ -28,6 +29,7 @@ export 'css_flex_shorthand.dart'; export 'css_font.dart'; export 'css_gradient_direction.dart'; export 'css_grid_template_columns.dart'; +export 'css_hyphens.dart'; export 'css_isolation.dart'; export 'css_justify_items.dart'; export 'css_justify_self.dart'; @@ -51,6 +53,9 @@ export 'css_spacing.dart'; export 'css_text.dart'; export 'css_text_overflow.dart'; export 'css_text_shadow.dart'; +export 'css_touch_action.dart'; export 'css_transform.dart'; export 'css_transition.dart'; +export 'css_user_select.dart'; export 'css_value.dart'; +export 'css_will_change.dart'; diff --git a/packages/spark_css/lib/src/css_types/css_user_select.dart b/packages/spark_css/lib/src/css_types/css_user_select.dart new file mode 100644 index 0000000..d8f35a3 --- /dev/null +++ b/packages/spark_css/lib/src/css_types/css_user_select.dart @@ -0,0 +1,53 @@ +import 'css_value.dart'; + +/// CSS user-select property values. +sealed class CssUserSelect implements CssValue { + const CssUserSelect._(); + + static const CssUserSelect none = _CssUserSelectKeyword('none'); + static const CssUserSelect auto = _CssUserSelectKeyword('auto'); + static const CssUserSelect text = _CssUserSelectKeyword('text'); + static const CssUserSelect all = _CssUserSelectKeyword('all'); + static const CssUserSelect contain = _CssUserSelectKeyword('contain'); + + /// CSS variable reference. + factory CssUserSelect.variable(String varName) = _CssUserSelectVariable; + + /// Raw CSS value escape hatch. + factory CssUserSelect.raw(String value) = _CssUserSelectRaw; + + /// Global keyword (inherit, initial, unset, revert). + factory CssUserSelect.global(CssGlobal global) = _CssUserSelectGlobal; +} + +final class _CssUserSelectKeyword extends CssUserSelect { + final String keyword; + const _CssUserSelectKeyword(this.keyword) : super._(); + + @override + String toCss() => keyword; +} + +final class _CssUserSelectVariable extends CssUserSelect { + final String varName; + const _CssUserSelectVariable(this.varName) : super._(); + + @override + String toCss() => 'var(--$varName)'; +} + +final class _CssUserSelectRaw extends CssUserSelect { + final String value; + const _CssUserSelectRaw(this.value) : super._(); + + @override + String toCss() => value; +} + +final class _CssUserSelectGlobal extends CssUserSelect { + final CssGlobal global; + const _CssUserSelectGlobal(this.global) : super._(); + + @override + String toCss() => global.toCss(); +} diff --git a/packages/spark_css/lib/src/css_types/css_will_change.dart b/packages/spark_css/lib/src/css_types/css_will_change.dart new file mode 100644 index 0000000..feb827d --- /dev/null +++ b/packages/spark_css/lib/src/css_types/css_will_change.dart @@ -0,0 +1,68 @@ +import 'css_value.dart'; + +/// CSS will-change property values. +sealed class CssWillChange implements CssValue { + const CssWillChange._(); + + static const CssWillChange auto = _CssWillChangeKeyword('auto'); + static const CssWillChange scrollPosition = _CssWillChangeKeyword( + 'scroll-position', + ); + static const CssWillChange contents = _CssWillChangeKeyword('contents'); + + /// Hints that the listed CSS property names will change. + /// + /// Example: `CssWillChange.properties(['transform', 'opacity'])` + /// produces `will-change: transform, opacity`. + factory CssWillChange.properties(List properties) = + _CssWillChangeProperties; + + /// CSS variable reference. + factory CssWillChange.variable(String varName) = _CssWillChangeVariable; + + /// Raw CSS value escape hatch. + factory CssWillChange.raw(String value) = _CssWillChangeRaw; + + /// Global keyword (inherit, initial, unset, revert). + factory CssWillChange.global(CssGlobal global) = _CssWillChangeGlobal; +} + +final class _CssWillChangeKeyword extends CssWillChange { + final String keyword; + const _CssWillChangeKeyword(this.keyword) : super._(); + + @override + String toCss() => keyword; +} + +final class _CssWillChangeProperties extends CssWillChange { + final List properties; + const _CssWillChangeProperties(this.properties) : super._(); + + @override + String toCss() => properties.join(', '); +} + +final class _CssWillChangeVariable extends CssWillChange { + final String varName; + const _CssWillChangeVariable(this.varName) : super._(); + + @override + String toCss() => 'var(--$varName)'; +} + +final class _CssWillChangeRaw extends CssWillChange { + final String value; + const _CssWillChangeRaw(this.value) : super._(); + + @override + String toCss() => value; +} + +final class _CssWillChangeGlobal extends CssWillChange { + final CssGlobal global; + const _CssWillChangeGlobal(this.global) : super._(); + + @override + String toCss() => global.toCss(); +} diff --git a/packages/spark_css/lib/src/style.dart b/packages/spark_css/lib/src/style.dart index e5e4085..dc63c44 100644 --- a/packages/spark_css/lib/src/style.dart +++ b/packages/spark_css/lib/src/style.dart @@ -289,6 +289,7 @@ class Style implements CssStyle { CssLength? letterSpacing, CssTextShadow? textShadow, CssTextOverflow? textOverflow, + CssHyphens? hyphens, // Borders CssBorder? border, CssBorder? borderTop, @@ -320,6 +321,10 @@ class Style implements CssStyle { CssMixBlendMode? mixBlendMode, CssFilter? filter, CssFilter? backdropFilter, + CssContain? contain, + CssWillChange? willChange, + CssTouchAction? touchAction, + CssUserSelect? userSelect, // Backgrounds CssBackgroundImage? backgroundImage, CssBackgroundSize? backgroundSize, @@ -439,6 +444,7 @@ class Style implements CssStyle { if (textOverflow != null) { _properties['text-overflow'] = textOverflow.toCss(); } + if (hyphens != null) _properties['hyphens'] = hyphens.toCss(); // Borders if (border != null) _properties['border'] = border.toCss(); @@ -496,6 +502,16 @@ class Style implements CssStyle { if (backdropFilter != null) { _properties['backdrop-filter'] = backdropFilter.toCss(); } + if (contain != null) _properties['contain'] = contain.toCss(); + if (willChange != null) { + _properties['will-change'] = willChange.toCss(); + } + if (touchAction != null) { + _properties['touch-action'] = touchAction.toCss(); + } + if (userSelect != null) { + _properties['user-select'] = userSelect.toCss(); + } // Backgrounds if (backgroundImage != null) { diff --git a/packages/spark_css/test/css_contain_test.dart b/packages/spark_css/test/css_contain_test.dart new file mode 100644 index 0000000..718837b --- /dev/null +++ b/packages/spark_css/test/css_contain_test.dart @@ -0,0 +1,74 @@ +import 'package:spark_css/spark_css.dart'; +import 'package:test/test.dart'; + +void main() { + group('CssContain', () { + test('keyword shorthands output correct CSS', () { + expect(CssContain.none.toCss(), equals('none')); + expect(CssContain.strict.toCss(), equals('strict')); + expect(CssContain.content.toCss(), equals('content')); + }); + + test('individual keyword constants output correct CSS', () { + expect(CssContain.size.toCss(), equals('size')); + expect(CssContain.layout.toCss(), equals('layout')); + expect(CssContain.style.toCss(), equals('style')); + expect(CssContain.paint.toCss(), equals('paint')); + }); + + test('flags with no active flags returns none', () { + expect(CssContain.flags().toCss(), equals('none')); + }); + + test('flags with single flag', () { + expect(CssContain.flags(size: true).toCss(), equals('size')); + expect(CssContain.flags(layout: true).toCss(), equals('layout')); + expect(CssContain.flags(style: true).toCss(), equals('style')); + expect(CssContain.flags(paint: true).toCss(), equals('paint')); + }); + + test('flags with multiple flags joins in order', () { + expect( + CssContain.flags(size: true, layout: true).toCss(), + equals('size layout'), + ); + expect( + CssContain.flags(layout: true, style: true, paint: true).toCss(), + equals('layout style paint'), + ); + expect( + CssContain.flags( + size: true, + layout: true, + style: true, + paint: true, + ).toCss(), + equals('size layout style paint'), + ); + }); + + test('variable outputs correct CSS', () { + expect(CssContain.variable('ctn').toCss(), equals('var(--ctn)')); + }); + + test('raw outputs value as-is', () { + expect(CssContain.raw('strict').toCss(), equals('strict')); + }); + + test('global outputs correct CSS', () { + expect(CssContain.global(CssGlobal.inherit).toCss(), equals('inherit')); + expect(CssContain.global(CssGlobal.initial).toCss(), equals('initial')); + expect(CssContain.global(CssGlobal.unset).toCss(), equals('unset')); + expect(CssContain.global(CssGlobal.revert).toCss(), equals('revert')); + expect( + CssContain.global(CssGlobal.revertLayer).toCss(), + equals('revert-layer'), + ); + }); + + test('Style.typed integration', () { + final style = Style.typed(contain: CssContain.strict); + expect(style.toCss(), contains('contain: strict;')); + }); + }); +} diff --git a/packages/spark_css/test/css_hyphens_test.dart b/packages/spark_css/test/css_hyphens_test.dart new file mode 100644 index 0000000..ccc301c --- /dev/null +++ b/packages/spark_css/test/css_hyphens_test.dart @@ -0,0 +1,36 @@ +import 'package:spark_css/spark_css.dart'; +import 'package:test/test.dart'; + +void main() { + group('CssHyphens', () { + test('keywords output correct CSS', () { + expect(CssHyphens.none.toCss(), equals('none')); + expect(CssHyphens.manual.toCss(), equals('manual')); + expect(CssHyphens.auto.toCss(), equals('auto')); + }); + + test('variable outputs correct CSS', () { + expect(CssHyphens.variable('hyph').toCss(), equals('var(--hyph)')); + }); + + test('raw outputs value as-is', () { + expect(CssHyphens.raw('manual').toCss(), equals('manual')); + }); + + test('global outputs correct CSS', () { + expect(CssHyphens.global(CssGlobal.inherit).toCss(), equals('inherit')); + expect(CssHyphens.global(CssGlobal.initial).toCss(), equals('initial')); + expect(CssHyphens.global(CssGlobal.unset).toCss(), equals('unset')); + expect(CssHyphens.global(CssGlobal.revert).toCss(), equals('revert')); + expect( + CssHyphens.global(CssGlobal.revertLayer).toCss(), + equals('revert-layer'), + ); + }); + + test('Style.typed integration', () { + final style = Style.typed(hyphens: CssHyphens.auto); + expect(style.toCss(), contains('hyphens: auto;')); + }); + }); +} diff --git a/packages/spark_css/test/css_touch_action_test.dart b/packages/spark_css/test/css_touch_action_test.dart new file mode 100644 index 0000000..fbb8950 --- /dev/null +++ b/packages/spark_css/test/css_touch_action_test.dart @@ -0,0 +1,71 @@ +import 'package:spark_css/spark_css.dart'; +import 'package:test/test.dart'; + +void main() { + group('CssTouchAction', () { + test('standalone keywords output correct CSS', () { + expect(CssTouchAction.auto.toCss(), equals('auto')); + expect(CssTouchAction.none.toCss(), equals('none')); + expect(CssTouchAction.manipulation.toCss(), equals('manipulation')); + }); + + test('combinable keywords output correct CSS', () { + expect(CssTouchAction.panX.toCss(), equals('pan-x')); + expect(CssTouchAction.panLeft.toCss(), equals('pan-left')); + expect(CssTouchAction.panRight.toCss(), equals('pan-right')); + expect(CssTouchAction.panY.toCss(), equals('pan-y')); + expect(CssTouchAction.panUp.toCss(), equals('pan-up')); + expect(CssTouchAction.panDown.toCss(), equals('pan-down')); + expect(CssTouchAction.pinchZoom.toCss(), equals('pinch-zoom')); + }); + + test('combine outputs space-separated values', () { + final combined = CssTouchAction.combine([ + CssTouchAction.panX, + CssTouchAction.pinchZoom, + ]); + expect(combined.toCss(), equals('pan-x pinch-zoom')); + }); + + test('combine with pan-y and pinch-zoom', () { + final combined = CssTouchAction.combine([ + CssTouchAction.panY, + CssTouchAction.pinchZoom, + ]); + expect(combined.toCss(), equals('pan-y pinch-zoom')); + }); + + test('variable outputs correct CSS', () { + expect(CssTouchAction.variable('ta').toCss(), equals('var(--ta)')); + }); + + test('raw outputs value as-is', () { + expect( + CssTouchAction.raw('pan-x pinch-zoom').toCss(), + equals('pan-x pinch-zoom'), + ); + }); + + test('global outputs correct CSS', () { + expect( + CssTouchAction.global(CssGlobal.inherit).toCss(), + equals('inherit'), + ); + expect( + CssTouchAction.global(CssGlobal.initial).toCss(), + equals('initial'), + ); + expect(CssTouchAction.global(CssGlobal.unset).toCss(), equals('unset')); + expect(CssTouchAction.global(CssGlobal.revert).toCss(), equals('revert')); + expect( + CssTouchAction.global(CssGlobal.revertLayer).toCss(), + equals('revert-layer'), + ); + }); + + test('Style.typed integration', () { + final style = Style.typed(touchAction: CssTouchAction.manipulation); + expect(style.toCss(), contains('touch-action: manipulation;')); + }); + }); +} diff --git a/packages/spark_css/test/css_user_select_test.dart b/packages/spark_css/test/css_user_select_test.dart new file mode 100644 index 0000000..8cc8a75 --- /dev/null +++ b/packages/spark_css/test/css_user_select_test.dart @@ -0,0 +1,44 @@ +import 'package:spark_css/spark_css.dart'; +import 'package:test/test.dart'; + +void main() { + group('CssUserSelect', () { + test('keywords output correct CSS', () { + expect(CssUserSelect.none.toCss(), equals('none')); + expect(CssUserSelect.auto.toCss(), equals('auto')); + expect(CssUserSelect.text.toCss(), equals('text')); + expect(CssUserSelect.all.toCss(), equals('all')); + expect(CssUserSelect.contain.toCss(), equals('contain')); + }); + + test('variable outputs correct CSS', () { + expect(CssUserSelect.variable('us').toCss(), equals('var(--us)')); + }); + + test('raw outputs value as-is', () { + expect(CssUserSelect.raw('text').toCss(), equals('text')); + }); + + test('global outputs correct CSS', () { + expect( + CssUserSelect.global(CssGlobal.inherit).toCss(), + equals('inherit'), + ); + expect( + CssUserSelect.global(CssGlobal.initial).toCss(), + equals('initial'), + ); + expect(CssUserSelect.global(CssGlobal.unset).toCss(), equals('unset')); + expect(CssUserSelect.global(CssGlobal.revert).toCss(), equals('revert')); + expect( + CssUserSelect.global(CssGlobal.revertLayer).toCss(), + equals('revert-layer'), + ); + }); + + test('Style.typed integration', () { + final style = Style.typed(userSelect: CssUserSelect.none); + expect(style.toCss(), contains('user-select: none;')); + }); + }); +} diff --git a/packages/spark_css/test/css_will_change_test.dart b/packages/spark_css/test/css_will_change_test.dart new file mode 100644 index 0000000..145eb51 --- /dev/null +++ b/packages/spark_css/test/css_will_change_test.dart @@ -0,0 +1,53 @@ +import 'package:spark_css/spark_css.dart'; +import 'package:test/test.dart'; + +void main() { + group('CssWillChange', () { + test('keywords output correct CSS', () { + expect(CssWillChange.auto.toCss(), equals('auto')); + expect(CssWillChange.scrollPosition.toCss(), equals('scroll-position')); + expect(CssWillChange.contents.toCss(), equals('contents')); + }); + + test('properties outputs comma-separated list', () { + expect( + CssWillChange.properties(['transform']).toCss(), + equals('transform'), + ); + expect( + CssWillChange.properties(['transform', 'opacity']).toCss(), + equals('transform, opacity'), + ); + }); + + test('variable outputs correct CSS', () { + expect(CssWillChange.variable('wc').toCss(), equals('var(--wc)')); + }); + + test('raw outputs value as-is', () { + expect(CssWillChange.raw('transform').toCss(), equals('transform')); + }); + + test('global outputs correct CSS', () { + expect( + CssWillChange.global(CssGlobal.inherit).toCss(), + equals('inherit'), + ); + expect( + CssWillChange.global(CssGlobal.initial).toCss(), + equals('initial'), + ); + expect(CssWillChange.global(CssGlobal.unset).toCss(), equals('unset')); + expect(CssWillChange.global(CssGlobal.revert).toCss(), equals('revert')); + expect( + CssWillChange.global(CssGlobal.revertLayer).toCss(), + equals('revert-layer'), + ); + }); + + test('Style.typed integration', () { + final style = Style.typed(willChange: CssWillChange.auto); + expect(style.toCss(), contains('will-change: auto;')); + }); + }); +}