diff --git a/packages/spark_css/CHANGELOG.md b/packages/spark_css/CHANGELOG.md index a7fb5c1..d9b8a4d 100644 --- a/packages/spark_css/CHANGELOG.md +++ b/packages/spark_css/CHANGELOG.md @@ -36,6 +36,11 @@ - **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. +- **Feat**: Added `CssTabSize` sealed class for `tab-size` property with `.number()`, `.length()` factories, plus `.variable()`, `.raw()`, and `.global()` escape hatches. +- **Feat**: Added `CssCaretColor` sealed class for `caret-color` property with `.auto` keyword, `.color()` factory, plus `.variable()`, `.raw()`, and `.global()` escape hatches. +- **Feat**: Added `CssScrollSnapType` sealed class for `scroll-snap-type` property with `.none` keyword, `.axis()` factory with optional strictness, plus `.variable()`, `.raw()`, and `.global()` escape hatches. +- **Feat**: Added `CssScrollSnapAlign` sealed class for `scroll-snap-align` property with `.none`, `.start`, `.end`, `.center` keywords, `.pair()` for two-value syntax, plus `.variable()`, `.raw()`, and `.global()` escape hatches. +- **Feat**: Added `CssScrollMargin` sealed class for `scroll-margin` property with `.all()`, `.symmetric()`, `.only()` factories, plus `.variable()`, `.raw()`, and `.global()` escape hatches. ### Changed diff --git a/packages/spark_css/lib/src/css_types/css_caret_color.dart b/packages/spark_css/lib/src/css_types/css_caret_color.dart new file mode 100644 index 0000000..38ae53d --- /dev/null +++ b/packages/spark_css/lib/src/css_types/css_caret_color.dart @@ -0,0 +1,61 @@ +import 'css_color.dart'; +import 'css_value.dart'; + +/// CSS caret-color property values. +sealed class CssCaretColor implements CssValue { + const CssCaretColor._(); + + static const CssCaretColor auto = _CssCaretColorKeyword('auto'); + + /// Caret color from a CssColor value. + factory CssCaretColor.color(CssColor color) = _CssCaretColorValue; + + /// CSS variable reference. + factory CssCaretColor.variable(String varName) = _CssCaretColorVariable; + + /// Raw CSS value escape hatch. + factory CssCaretColor.raw(String value) = _CssCaretColorRaw; + + /// Global keyword (inherit, initial, unset, revert). + factory CssCaretColor.global(CssGlobal global) = _CssCaretColorGlobal; +} + +final class _CssCaretColorKeyword extends CssCaretColor { + final String keyword; + const _CssCaretColorKeyword(this.keyword) : super._(); + + @override + String toCss() => keyword; +} + +final class _CssCaretColorValue extends CssCaretColor { + final CssColor color; + const _CssCaretColorValue(this.color) : super._(); + + @override + String toCss() => color.toCss(); +} + +final class _CssCaretColorVariable extends CssCaretColor { + final String varName; + const _CssCaretColorVariable(this.varName) : super._(); + + @override + String toCss() => 'var(--$varName)'; +} + +final class _CssCaretColorRaw extends CssCaretColor { + final String value; + const _CssCaretColorRaw(this.value) : super._(); + + @override + String toCss() => value; +} + +final class _CssCaretColorGlobal extends CssCaretColor { + final CssGlobal global; + const _CssCaretColorGlobal(this.global) : super._(); + + @override + String toCss() => global.toCss(); +} diff --git a/packages/spark_css/lib/src/css_types/css_scroll_margin.dart b/packages/spark_css/lib/src/css_types/css_scroll_margin.dart new file mode 100644 index 0000000..660544c --- /dev/null +++ b/packages/spark_css/lib/src/css_types/css_scroll_margin.dart @@ -0,0 +1,96 @@ +import 'css_length.dart'; +import 'css_value.dart'; + +/// CSS scroll-margin property values. +sealed class CssScrollMargin implements CssValue { + const CssScrollMargin._(); + + /// Same value for all four sides. + /// + /// Example: `CssScrollMargin.all(CssLength.px(10))` → `10px` + factory CssScrollMargin.all(CssLength value) = _CssScrollMarginAll; + + /// Symmetric scroll margin (vertical and horizontal). + /// + /// Example: `CssScrollMargin.symmetric(CssLength.px(10), CssLength.px(20))` → `10px 20px` + factory CssScrollMargin.symmetric(CssLength vertical, CssLength horizontal) = + _CssScrollMarginSymmetric; + + /// Individual sides. + /// + /// Example: `CssScrollMargin.only(top: CssLength.px(10), right: CssLength.px(20), bottom: CssLength.px(30), left: CssLength.px(40))` → `10px 20px 30px 40px` + factory CssScrollMargin.only({ + CssLength? top, + CssLength? right, + CssLength? bottom, + CssLength? left, + }) = _CssScrollMarginOnly; + + /// CSS variable reference. + factory CssScrollMargin.variable(String varName) = _CssScrollMarginVariable; + + /// Raw CSS value escape hatch. + factory CssScrollMargin.raw(String value) = _CssScrollMarginRaw; + + /// Global keyword (inherit, initial, unset, revert). + factory CssScrollMargin.global(CssGlobal global) = _CssScrollMarginGlobal; +} + +final class _CssScrollMarginAll extends CssScrollMargin { + final CssLength value; + const _CssScrollMarginAll(this.value) : super._(); + + @override + String toCss() => value.toCss(); +} + +final class _CssScrollMarginSymmetric extends CssScrollMargin { + final CssLength vertical; + final CssLength horizontal; + const _CssScrollMarginSymmetric(this.vertical, this.horizontal) : super._(); + + @override + String toCss() => '${vertical.toCss()} ${horizontal.toCss()}'; +} + +final class _CssScrollMarginOnly extends CssScrollMargin { + final CssLength? top; + final CssLength? right; + final CssLength? bottom; + final CssLength? left; + const _CssScrollMarginOnly({this.top, this.right, this.bottom, this.left}) + : super._(); + + @override + String toCss() { + final t = top ?? CssLength.zero; + final r = right ?? CssLength.zero; + final b = bottom ?? CssLength.zero; + final l = left ?? CssLength.zero; + return '${t.toCss()} ${r.toCss()} ${b.toCss()} ${l.toCss()}'; + } +} + +final class _CssScrollMarginVariable extends CssScrollMargin { + final String varName; + const _CssScrollMarginVariable(this.varName) : super._(); + + @override + String toCss() => 'var(--$varName)'; +} + +final class _CssScrollMarginRaw extends CssScrollMargin { + final String value; + const _CssScrollMarginRaw(this.value) : super._(); + + @override + String toCss() => value; +} + +final class _CssScrollMarginGlobal extends CssScrollMargin { + final CssGlobal global; + const _CssScrollMarginGlobal(this.global) : super._(); + + @override + String toCss() => global.toCss(); +} diff --git a/packages/spark_css/lib/src/css_types/css_scroll_snap_align.dart b/packages/spark_css/lib/src/css_types/css_scroll_snap_align.dart new file mode 100644 index 0000000..b3c152c --- /dev/null +++ b/packages/spark_css/lib/src/css_types/css_scroll_snap_align.dart @@ -0,0 +1,69 @@ +import 'css_value.dart'; + +/// CSS scroll-snap-align property values. +sealed class CssScrollSnapAlign implements CssValue { + const CssScrollSnapAlign._(); + + static const CssScrollSnapAlign none = _CssScrollSnapAlignKeyword('none'); + static const CssScrollSnapAlign start = _CssScrollSnapAlignKeyword('start'); + static const CssScrollSnapAlign end = _CssScrollSnapAlignKeyword('end'); + static const CssScrollSnapAlign center = _CssScrollSnapAlignKeyword('center'); + + /// Two-value syntax: inline alignment and block alignment. + /// + /// Example: `CssScrollSnapAlign.pair('start', 'end')` → `start end` + factory CssScrollSnapAlign.pair(String align, String blockAlign) = + _CssScrollSnapAlignPair; + + /// CSS variable reference. + factory CssScrollSnapAlign.variable(String varName) = + _CssScrollSnapAlignVariable; + + /// Raw CSS value escape hatch. + factory CssScrollSnapAlign.raw(String value) = _CssScrollSnapAlignRaw; + + /// Global keyword (inherit, initial, unset, revert). + factory CssScrollSnapAlign.global(CssGlobal global) = + _CssScrollSnapAlignGlobal; +} + +final class _CssScrollSnapAlignKeyword extends CssScrollSnapAlign { + final String keyword; + const _CssScrollSnapAlignKeyword(this.keyword) : super._(); + + @override + String toCss() => keyword; +} + +final class _CssScrollSnapAlignPair extends CssScrollSnapAlign { + final String align; + final String blockAlign; + const _CssScrollSnapAlignPair(this.align, this.blockAlign) : super._(); + + @override + String toCss() => '$align $blockAlign'; +} + +final class _CssScrollSnapAlignVariable extends CssScrollSnapAlign { + final String varName; + const _CssScrollSnapAlignVariable(this.varName) : super._(); + + @override + String toCss() => 'var(--$varName)'; +} + +final class _CssScrollSnapAlignRaw extends CssScrollSnapAlign { + final String value; + const _CssScrollSnapAlignRaw(this.value) : super._(); + + @override + String toCss() => value; +} + +final class _CssScrollSnapAlignGlobal extends CssScrollSnapAlign { + final CssGlobal global; + const _CssScrollSnapAlignGlobal(this.global) : super._(); + + @override + String toCss() => global.toCss(); +} diff --git a/packages/spark_css/lib/src/css_types/css_scroll_snap_type.dart b/packages/spark_css/lib/src/css_types/css_scroll_snap_type.dart new file mode 100644 index 0000000..d9df56e --- /dev/null +++ b/packages/spark_css/lib/src/css_types/css_scroll_snap_type.dart @@ -0,0 +1,68 @@ +import 'css_value.dart'; + +/// CSS scroll-snap-type property values. +sealed class CssScrollSnapType implements CssValue { + const CssScrollSnapType._(); + + static const CssScrollSnapType none = _CssScrollSnapTypeKeyword('none'); + + /// Scroll snap type with axis and optional strictness. + /// + /// [axis] must be one of: `x`, `y`, `block`, `inline`, `both`. + /// [strictness] is optional: `mandatory` or `proximity`. + /// + /// Example: `CssScrollSnapType.axis('x', 'mandatory')` → `x mandatory` + factory CssScrollSnapType.axis(String axis, [String? strictness]) = + _CssScrollSnapTypeAxis; + + /// CSS variable reference. + factory CssScrollSnapType.variable(String varName) = + _CssScrollSnapTypeVariable; + + /// Raw CSS value escape hatch. + factory CssScrollSnapType.raw(String value) = _CssScrollSnapTypeRaw; + + /// Global keyword (inherit, initial, unset, revert). + factory CssScrollSnapType.global(CssGlobal global) = _CssScrollSnapTypeGlobal; +} + +final class _CssScrollSnapTypeKeyword extends CssScrollSnapType { + final String keyword; + const _CssScrollSnapTypeKeyword(this.keyword) : super._(); + + @override + String toCss() => keyword; +} + +final class _CssScrollSnapTypeAxis extends CssScrollSnapType { + final String axis; + final String? strictness; + const _CssScrollSnapTypeAxis(this.axis, [this.strictness]) : super._(); + + @override + String toCss() => strictness != null ? '$axis $strictness' : axis; +} + +final class _CssScrollSnapTypeVariable extends CssScrollSnapType { + final String varName; + const _CssScrollSnapTypeVariable(this.varName) : super._(); + + @override + String toCss() => 'var(--$varName)'; +} + +final class _CssScrollSnapTypeRaw extends CssScrollSnapType { + final String value; + const _CssScrollSnapTypeRaw(this.value) : super._(); + + @override + String toCss() => value; +} + +final class _CssScrollSnapTypeGlobal extends CssScrollSnapType { + final CssGlobal global; + const _CssScrollSnapTypeGlobal(this.global) : super._(); + + @override + String toCss() => global.toCss(); +} diff --git a/packages/spark_css/lib/src/css_types/css_tab_size.dart b/packages/spark_css/lib/src/css_types/css_tab_size.dart new file mode 100644 index 0000000..07ff71c --- /dev/null +++ b/packages/spark_css/lib/src/css_types/css_tab_size.dart @@ -0,0 +1,62 @@ +import 'css_length.dart'; +import 'css_value.dart'; + +/// CSS tab-size property values. +sealed class CssTabSize implements CssValue { + const CssTabSize._(); + + /// Tab size as a number (number of spaces). + factory CssTabSize.number(int value) = _CssTabSizeNumber; + + /// Tab size as a length. + factory CssTabSize.length(CssLength value) = _CssTabSizeLength; + + /// CSS variable reference. + factory CssTabSize.variable(String varName) = _CssTabSizeVariable; + + /// Raw CSS value escape hatch. + factory CssTabSize.raw(String value) = _CssTabSizeRaw; + + /// Global keyword (inherit, initial, unset, revert). + factory CssTabSize.global(CssGlobal global) = _CssTabSizeGlobal; +} + +final class _CssTabSizeNumber extends CssTabSize { + final int value; + const _CssTabSizeNumber(this.value) : super._(); + + @override + String toCss() => '$value'; +} + +final class _CssTabSizeLength extends CssTabSize { + final CssLength value; + const _CssTabSizeLength(this.value) : super._(); + + @override + String toCss() => value.toCss(); +} + +final class _CssTabSizeVariable extends CssTabSize { + final String varName; + const _CssTabSizeVariable(this.varName) : super._(); + + @override + String toCss() => 'var(--$varName)'; +} + +final class _CssTabSizeRaw extends CssTabSize { + final String value; + const _CssTabSizeRaw(this.value) : super._(); + + @override + String toCss() => value; +} + +final class _CssTabSizeGlobal extends CssTabSize { + final CssGlobal global; + const _CssTabSizeGlobal(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 d1bd2ea..092bc5c 100644 --- a/packages/spark_css/lib/src/css_types/css_types.dart +++ b/packages/spark_css/lib/src/css_types/css_types.dart @@ -18,6 +18,7 @@ export 'css_border_collapse.dart'; export 'css_border_radius.dart'; export 'css_box_shadow.dart'; export 'css_box_sizing.dart'; +export 'css_caret_color.dart'; export 'css_color.dart'; export 'css_contain.dart'; export 'css_content.dart'; @@ -49,7 +50,11 @@ export 'css_radial_shape.dart'; export 'css_radial_size.dart'; export 'css_resize.dart'; export 'css_scroll_behavior.dart'; +export 'css_scroll_margin.dart'; +export 'css_scroll_snap_align.dart'; +export 'css_scroll_snap_type.dart'; export 'css_spacing.dart'; +export 'css_tab_size.dart'; export 'css_text.dart'; export 'css_text_overflow.dart'; export 'css_text_shadow.dart'; diff --git a/packages/spark_css/lib/src/style.dart b/packages/spark_css/lib/src/style.dart index dc63c44..96c95ea 100644 --- a/packages/spark_css/lib/src/style.dart +++ b/packages/spark_css/lib/src/style.dart @@ -325,6 +325,11 @@ class Style implements CssStyle { CssWillChange? willChange, CssTouchAction? touchAction, CssUserSelect? userSelect, + CssTabSize? tabSize, + CssCaretColor? caretColor, + CssScrollSnapType? scrollSnapType, + CssScrollSnapAlign? scrollSnapAlign, + CssScrollMargin? scrollMargin, // Backgrounds CssBackgroundImage? backgroundImage, CssBackgroundSize? backgroundSize, @@ -512,6 +517,19 @@ class Style implements CssStyle { if (userSelect != null) { _properties['user-select'] = userSelect.toCss(); } + if (tabSize != null) _properties['tab-size'] = tabSize.toCss(); + if (caretColor != null) { + _properties['caret-color'] = caretColor.toCss(); + } + if (scrollSnapType != null) { + _properties['scroll-snap-type'] = scrollSnapType.toCss(); + } + if (scrollSnapAlign != null) { + _properties['scroll-snap-align'] = scrollSnapAlign.toCss(); + } + if (scrollMargin != null) { + _properties['scroll-margin'] = scrollMargin.toCss(); + } // Backgrounds if (backgroundImage != null) { diff --git a/packages/spark_css/test/css_caret_color_test.dart b/packages/spark_css/test/css_caret_color_test.dart new file mode 100644 index 0000000..5ccef3d --- /dev/null +++ b/packages/spark_css/test/css_caret_color_test.dart @@ -0,0 +1,48 @@ +import 'package:spark_css/spark_css.dart'; +import 'package:test/test.dart'; + +void main() { + group('CssCaretColor', () { + test('auto keyword outputs correct CSS', () { + expect(CssCaretColor.auto.toCss(), equals('auto')); + }); + + test('color outputs correct CSS', () { + expect(CssCaretColor.color(CssColor.red).toCss(), equals('red')); + expect( + CssCaretColor.color(CssColor.hex('#ff0000')).toCss(), + equals('#ff0000'), + ); + }); + + test('variable outputs correct CSS', () { + expect(CssCaretColor.variable('cc').toCss(), equals('var(--cc)')); + }); + + test('raw outputs value as-is', () { + expect(CssCaretColor.raw('red').toCss(), equals('red')); + }); + + test('global outputs correct CSS', () { + expect( + CssCaretColor.global(CssGlobal.inherit).toCss(), + equals('inherit'), + ); + expect( + CssCaretColor.global(CssGlobal.initial).toCss(), + equals('initial'), + ); + expect(CssCaretColor.global(CssGlobal.unset).toCss(), equals('unset')); + expect(CssCaretColor.global(CssGlobal.revert).toCss(), equals('revert')); + expect( + CssCaretColor.global(CssGlobal.revertLayer).toCss(), + equals('revert-layer'), + ); + }); + + test('Style.typed integration', () { + final style = Style.typed(caretColor: CssCaretColor.auto); + expect(style.toCss(), contains('caret-color: auto;')); + }); + }); +} diff --git a/packages/spark_css/test/css_scroll_margin_test.dart b/packages/spark_css/test/css_scroll_margin_test.dart new file mode 100644 index 0000000..25337a8 --- /dev/null +++ b/packages/spark_css/test/css_scroll_margin_test.dart @@ -0,0 +1,71 @@ +import 'package:spark_css/spark_css.dart'; +import 'package:test/test.dart'; + +void main() { + group('CssScrollMargin', () { + test('all outputs correct CSS', () { + expect(CssScrollMargin.all(CssLength.px(10)).toCss(), equals('10px')); + }); + + test('symmetric outputs correct CSS', () { + expect( + CssScrollMargin.symmetric(CssLength.px(10), CssLength.px(20)).toCss(), + equals('10px 20px'), + ); + }); + + test('only outputs correct CSS', () { + expect( + CssScrollMargin.only( + top: CssLength.px(10), + right: CssLength.px(20), + bottom: CssLength.px(30), + left: CssLength.px(40), + ).toCss(), + equals('10px 20px 30px 40px'), + ); + }); + + test('only with partial values defaults to zero', () { + expect( + CssScrollMargin.only(top: CssLength.px(10)).toCss(), + equals('10px 0 0 0'), + ); + }); + + test('variable outputs correct CSS', () { + expect(CssScrollMargin.variable('sm').toCss(), equals('var(--sm)')); + }); + + test('raw outputs value as-is', () { + expect(CssScrollMargin.raw('10px 20px').toCss(), equals('10px 20px')); + }); + + test('global outputs correct CSS', () { + expect( + CssScrollMargin.global(CssGlobal.inherit).toCss(), + equals('inherit'), + ); + expect( + CssScrollMargin.global(CssGlobal.initial).toCss(), + equals('initial'), + ); + expect(CssScrollMargin.global(CssGlobal.unset).toCss(), equals('unset')); + expect( + CssScrollMargin.global(CssGlobal.revert).toCss(), + equals('revert'), + ); + expect( + CssScrollMargin.global(CssGlobal.revertLayer).toCss(), + equals('revert-layer'), + ); + }); + + test('Style.typed integration', () { + final style = Style.typed( + scrollMargin: CssScrollMargin.all(CssLength.px(10)), + ); + expect(style.toCss(), contains('scroll-margin: 10px;')); + }); + }); +} diff --git a/packages/spark_css/test/css_scroll_snap_align_test.dart b/packages/spark_css/test/css_scroll_snap_align_test.dart new file mode 100644 index 0000000..a61080c --- /dev/null +++ b/packages/spark_css/test/css_scroll_snap_align_test.dart @@ -0,0 +1,60 @@ +import 'package:spark_css/spark_css.dart'; +import 'package:test/test.dart'; + +void main() { + group('CssScrollSnapAlign', () { + test('keywords output correct CSS', () { + expect(CssScrollSnapAlign.none.toCss(), equals('none')); + expect(CssScrollSnapAlign.start.toCss(), equals('start')); + expect(CssScrollSnapAlign.end.toCss(), equals('end')); + expect(CssScrollSnapAlign.center.toCss(), equals('center')); + }); + + test('pair outputs correct CSS', () { + expect( + CssScrollSnapAlign.pair('start', 'end').toCss(), + equals('start end'), + ); + expect( + CssScrollSnapAlign.pair('center', 'none').toCss(), + equals('center none'), + ); + }); + + test('variable outputs correct CSS', () { + expect(CssScrollSnapAlign.variable('ssa').toCss(), equals('var(--ssa)')); + }); + + test('raw outputs value as-is', () { + expect(CssScrollSnapAlign.raw('start end').toCss(), equals('start end')); + }); + + test('global outputs correct CSS', () { + expect( + CssScrollSnapAlign.global(CssGlobal.inherit).toCss(), + equals('inherit'), + ); + expect( + CssScrollSnapAlign.global(CssGlobal.initial).toCss(), + equals('initial'), + ); + expect( + CssScrollSnapAlign.global(CssGlobal.unset).toCss(), + equals('unset'), + ); + expect( + CssScrollSnapAlign.global(CssGlobal.revert).toCss(), + equals('revert'), + ); + expect( + CssScrollSnapAlign.global(CssGlobal.revertLayer).toCss(), + equals('revert-layer'), + ); + }); + + test('Style.typed integration', () { + final style = Style.typed(scrollSnapAlign: CssScrollSnapAlign.start); + expect(style.toCss(), contains('scroll-snap-align: start;')); + }); + }); +} diff --git a/packages/spark_css/test/css_scroll_snap_type_test.dart b/packages/spark_css/test/css_scroll_snap_type_test.dart new file mode 100644 index 0000000..5f05062 --- /dev/null +++ b/packages/spark_css/test/css_scroll_snap_type_test.dart @@ -0,0 +1,74 @@ +import 'package:spark_css/spark_css.dart'; +import 'package:test/test.dart'; + +void main() { + group('CssScrollSnapType', () { + test('none keyword outputs correct CSS', () { + expect(CssScrollSnapType.none.toCss(), equals('none')); + }); + + test('axis only outputs correct CSS', () { + expect(CssScrollSnapType.axis('x').toCss(), equals('x')); + expect(CssScrollSnapType.axis('y').toCss(), equals('y')); + expect(CssScrollSnapType.axis('block').toCss(), equals('block')); + expect(CssScrollSnapType.axis('inline').toCss(), equals('inline')); + expect(CssScrollSnapType.axis('both').toCss(), equals('both')); + }); + + test('axis with strictness outputs correct CSS', () { + expect( + CssScrollSnapType.axis('x', 'mandatory').toCss(), + equals('x mandatory'), + ); + expect( + CssScrollSnapType.axis('y', 'proximity').toCss(), + equals('y proximity'), + ); + expect( + CssScrollSnapType.axis('both', 'mandatory').toCss(), + equals('both mandatory'), + ); + }); + + test('variable outputs correct CSS', () { + expect(CssScrollSnapType.variable('sst').toCss(), equals('var(--sst)')); + }); + + test('raw outputs value as-is', () { + expect( + CssScrollSnapType.raw('x mandatory').toCss(), + equals('x mandatory'), + ); + }); + + test('global outputs correct CSS', () { + expect( + CssScrollSnapType.global(CssGlobal.inherit).toCss(), + equals('inherit'), + ); + expect( + CssScrollSnapType.global(CssGlobal.initial).toCss(), + equals('initial'), + ); + expect( + CssScrollSnapType.global(CssGlobal.unset).toCss(), + equals('unset'), + ); + expect( + CssScrollSnapType.global(CssGlobal.revert).toCss(), + equals('revert'), + ); + expect( + CssScrollSnapType.global(CssGlobal.revertLayer).toCss(), + equals('revert-layer'), + ); + }); + + test('Style.typed integration', () { + final style = Style.typed( + scrollSnapType: CssScrollSnapType.axis('x', 'mandatory'), + ); + expect(style.toCss(), contains('scroll-snap-type: x mandatory;')); + }); + }); +} diff --git a/packages/spark_css/test/css_tab_size_test.dart b/packages/spark_css/test/css_tab_size_test.dart new file mode 100644 index 0000000..2d0fb54 --- /dev/null +++ b/packages/spark_css/test/css_tab_size_test.dart @@ -0,0 +1,40 @@ +import 'package:spark_css/spark_css.dart'; +import 'package:test/test.dart'; + +void main() { + group('CssTabSize', () { + test('number outputs correct CSS', () { + expect(CssTabSize.number(4).toCss(), equals('4')); + expect(CssTabSize.number(8).toCss(), equals('8')); + }); + + test('length outputs correct CSS', () { + expect(CssTabSize.length(CssLength.px(20)).toCss(), equals('20px')); + expect(CssTabSize.length(CssLength.em(2)).toCss(), equals('2em')); + }); + + test('variable outputs correct CSS', () { + expect(CssTabSize.variable('ts').toCss(), equals('var(--ts)')); + }); + + test('raw outputs value as-is', () { + expect(CssTabSize.raw('4').toCss(), equals('4')); + }); + + test('global outputs correct CSS', () { + expect(CssTabSize.global(CssGlobal.inherit).toCss(), equals('inherit')); + expect(CssTabSize.global(CssGlobal.initial).toCss(), equals('initial')); + expect(CssTabSize.global(CssGlobal.unset).toCss(), equals('unset')); + expect(CssTabSize.global(CssGlobal.revert).toCss(), equals('revert')); + expect( + CssTabSize.global(CssGlobal.revertLayer).toCss(), + equals('revert-layer'), + ); + }); + + test('Style.typed integration', () { + final style = Style.typed(tabSize: CssTabSize.number(4)); + expect(style.toCss(), contains('tab-size: 4;')); + }); + }); +}