Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/spark_css/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
- **Feat**: Added `CssObjectFit` sealed class for `object-fit` property with `.fill`, `.contain`, `.cover`, `.none`, `.scaleDown` keywords, plus `.variable()`, `.raw()`, and `.global()` escape hatches.
- **Feat**: Added `CssPointerEvents` sealed class for `pointer-events` property with `.auto`, `.none`, `.visiblePainted`, `.visibleFill`, `.visibleStroke`, `.visible`, `.painted`, `.fill`, `.stroke`, `.all` keywords, plus `.variable()`, `.raw()`, and `.global()` escape hatches.
- **Feat**: Added `CssResize` sealed class for `resize` property with `.none`, `.both`, `.horizontal`, `.vertical`, `.block`, `.inline` keywords, plus `.variable()`, `.raw()`, and `.global()` escape hatches.
- **Feat**: Added `CssScrollBehavior` sealed class for `scroll-behavior` property with `.auto`, `.smooth` keywords, plus `.variable()`, `.raw()`, and `.global()` escape hatches.
- **Feat**: Added `CssTextOverflow` sealed class for `text-overflow` property with `.clip`, `.ellipsis` keywords, `.value()` for custom strings, plus `.variable()`, `.raw()`, and `.global()` escape hatches.
- **Feat**: Added `CssAspectRatio` sealed class for `aspect-ratio` property with `.auto` keyword, `.ratio()`, `.number()`, plus `.variable()`, `.raw()`, and `.global()` escape hatches.
- **Feat**: Added `CssPlaceItems` sealed class for `place-items` shorthand property with align and optional justify parameters, plus `.variable()`, `.raw()`, and `.global()` escape hatches.

### Changed

Expand Down
72 changes: 72 additions & 0 deletions packages/spark_css/lib/src/css_types/css_aspect_ratio.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import 'css_value.dart';

/// CSS aspect-ratio property values.
sealed class CssAspectRatio implements CssValue {
const CssAspectRatio._();

static const CssAspectRatio auto = _CssAspectRatioKeyword('auto');

/// Ratio value (e.g., `16 / 9`).
factory CssAspectRatio.ratio(num width, num height) = _CssAspectRatioRatio;

/// Single number value (e.g., `1` or `0.5`).
factory CssAspectRatio.number(num value) = _CssAspectRatioNumber;

/// CSS variable reference.
factory CssAspectRatio.variable(String varName) = _CssAspectRatioVariable;

/// Raw CSS value escape hatch.
factory CssAspectRatio.raw(String value) = _CssAspectRatioRaw;

/// Global keyword (inherit, initial, unset, revert).
factory CssAspectRatio.global(CssGlobal global) = _CssAspectRatioGlobal;
}

final class _CssAspectRatioKeyword extends CssAspectRatio {
final String keyword;
const _CssAspectRatioKeyword(this.keyword) : super._();

@override
String toCss() => keyword;
}

final class _CssAspectRatioRatio extends CssAspectRatio {
final num width;
final num height;
const _CssAspectRatioRatio(this.width, this.height) : super._();

@override
String toCss() => '$width / $height';
}

final class _CssAspectRatioNumber extends CssAspectRatio {
final num value;
const _CssAspectRatioNumber(this.value) : super._();

@override
String toCss() => '$value';
}

final class _CssAspectRatioVariable extends CssAspectRatio {
final String varName;
const _CssAspectRatioVariable(this.varName) : super._();

@override
String toCss() => 'var(--$varName)';
}

final class _CssAspectRatioRaw extends CssAspectRatio {
final String value;
const _CssAspectRatioRaw(this.value) : super._();

@override
String toCss() => value;
}

final class _CssAspectRatioGlobal extends CssAspectRatio {
final CssGlobal global;
const _CssAspectRatioGlobal(this.global) : super._();

@override
String toCss() => global.toCss();
}
57 changes: 57 additions & 0 deletions packages/spark_css/lib/src/css_types/css_place_items.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import 'css_flex.dart';
import 'css_justify_items.dart';
import 'css_value.dart';

/// CSS place-items shorthand property values.
sealed class CssPlaceItems implements CssValue {
const CssPlaceItems._();

/// Shorthand with align and optional justify.
factory CssPlaceItems(CssAlignItems align, [CssJustifyItems? justify]) =
_CssPlaceItemsShorthand;

/// CSS variable reference.
factory CssPlaceItems.variable(String varName) = _CssPlaceItemsVariable;

/// Raw CSS value escape hatch.
factory CssPlaceItems.raw(String value) = _CssPlaceItemsRaw;

/// Global keyword (inherit, initial, unset, revert).
factory CssPlaceItems.global(CssGlobal global) = _CssPlaceItemsGlobal;
}

final class _CssPlaceItemsShorthand extends CssPlaceItems {
final CssAlignItems align;
final CssJustifyItems? justify;
const _CssPlaceItemsShorthand(this.align, [this.justify]) : super._();

@override
String toCss() {
if (justify == null) return align.toCss();
return '${align.toCss()} ${justify!.toCss()}';
}
}

final class _CssPlaceItemsVariable extends CssPlaceItems {
final String varName;
const _CssPlaceItemsVariable(this.varName) : super._();

@override
String toCss() => 'var(--$varName)';
}

final class _CssPlaceItemsRaw extends CssPlaceItems {
final String value;
const _CssPlaceItemsRaw(this.value) : super._();

@override
String toCss() => value;
}

final class _CssPlaceItemsGlobal extends CssPlaceItems {
final CssGlobal global;
const _CssPlaceItemsGlobal(this.global) : super._();

@override
String toCss() => global.toCss();
}
51 changes: 51 additions & 0 deletions packages/spark_css/lib/src/css_types/css_scroll_behavior.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import 'css_value.dart';

/// CSS scroll-behavior property values.
sealed class CssScrollBehavior implements CssValue {
const CssScrollBehavior._();

static const CssScrollBehavior auto = _CssScrollBehaviorKeyword('auto');
static const CssScrollBehavior smooth = _CssScrollBehaviorKeyword('smooth');

/// CSS variable reference.
factory CssScrollBehavior.variable(String varName) =
_CssScrollBehaviorVariable;

/// Raw CSS value escape hatch.
factory CssScrollBehavior.raw(String value) = _CssScrollBehaviorRaw;

/// Global keyword (inherit, initial, unset, revert).
factory CssScrollBehavior.global(CssGlobal global) = _CssScrollBehaviorGlobal;
}

final class _CssScrollBehaviorKeyword extends CssScrollBehavior {
final String keyword;
const _CssScrollBehaviorKeyword(this.keyword) : super._();

@override
String toCss() => keyword;
}

final class _CssScrollBehaviorVariable extends CssScrollBehavior {
final String varName;
const _CssScrollBehaviorVariable(this.varName) : super._();

@override
String toCss() => 'var(--$varName)';
}

final class _CssScrollBehaviorRaw extends CssScrollBehavior {
final String value;
const _CssScrollBehaviorRaw(this.value) : super._();

@override
String toCss() => value;
}

final class _CssScrollBehaviorGlobal extends CssScrollBehavior {
final CssGlobal global;
const _CssScrollBehaviorGlobal(this.global) : super._();

@override
String toCss() => global.toCss();
}
61 changes: 61 additions & 0 deletions packages/spark_css/lib/src/css_types/css_text_overflow.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import 'css_value.dart';

/// CSS text-overflow property values.
sealed class CssTextOverflow implements CssValue {
const CssTextOverflow._();

static const CssTextOverflow clip = _CssTextOverflowKeyword('clip');
static const CssTextOverflow ellipsis = _CssTextOverflowKeyword('ellipsis');

/// Custom string value (outputs with quotes, e.g., `"…"`).
factory CssTextOverflow.value(String value) = _CssTextOverflowValue;

/// CSS variable reference.
factory CssTextOverflow.variable(String varName) = _CssTextOverflowVariable;

/// Raw CSS value escape hatch.
factory CssTextOverflow.raw(String value) = _CssTextOverflowRaw;

/// Global keyword (inherit, initial, unset, revert).
factory CssTextOverflow.global(CssGlobal global) = _CssTextOverflowGlobal;
}

final class _CssTextOverflowKeyword extends CssTextOverflow {
final String keyword;
const _CssTextOverflowKeyword(this.keyword) : super._();

@override
String toCss() => keyword;
}

final class _CssTextOverflowValue extends CssTextOverflow {
final String value;
const _CssTextOverflowValue(this.value) : super._();

@override
String toCss() => '"$value"';
}

final class _CssTextOverflowVariable extends CssTextOverflow {
final String varName;
const _CssTextOverflowVariable(this.varName) : super._();

@override
String toCss() => 'var(--$varName)';
}

final class _CssTextOverflowRaw extends CssTextOverflow {
final String value;
const _CssTextOverflowRaw(this.value) : super._();

@override
String toCss() => value;
}

final class _CssTextOverflowGlobal extends CssTextOverflow {
final CssGlobal global;
const _CssTextOverflowGlobal(this.global) : super._();

@override
String toCss() => global.toCss();
}
4 changes: 4 additions & 0 deletions packages/spark_css/lib/src/css_types/css_types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ library;

export 'css_animation.dart';
export 'css_angle.dart';
export 'css_aspect_ratio.dart';
export 'css_background.dart';
export 'css_background_attachment.dart';
export 'css_background_clip.dart';
Expand Down Expand Up @@ -33,13 +34,16 @@ export 'css_number.dart';
export 'css_object_fit.dart';
export 'css_outline.dart';
export 'css_overflow.dart';
export 'css_place_items.dart';
export 'css_pointer_events.dart';
export 'css_position.dart';
export 'css_radial_shape.dart';
export 'css_radial_size.dart';
export 'css_resize.dart';
export 'css_scroll_behavior.dart';
export 'css_spacing.dart';
export 'css_text.dart';
export 'css_text_overflow.dart';
export 'css_text_shadow.dart';
export 'css_transform.dart';
export 'css_transition.dart';
Expand Down
14 changes: 14 additions & 0 deletions packages/spark_css/lib/src/style.dart
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ class Style implements CssStyle {
// Layout
CssDisplay? display,
CssPosition? position,
CssAspectRatio? aspectRatio,
// Sizing
CssLength? width,
CssLength? height,
Expand Down Expand Up @@ -271,6 +272,7 @@ class Style implements CssStyle {
CssNumber? flexShrink,
CssLength? gap,
CssFlexShorthand? flex,
CssPlaceItems? placeItems,
// Typography
CssLength? fontSize,
CssFontWeight? fontWeight,
Expand All @@ -284,6 +286,7 @@ class Style implements CssStyle {
CssNumber? lineHeight,
CssLength? letterSpacing,
CssTextShadow? textShadow,
CssTextOverflow? textOverflow,
// Borders
CssBorder? border,
CssBorder? borderTop,
Expand All @@ -310,6 +313,7 @@ class Style implements CssStyle {
CssObjectFit? objectFit,
CssPointerEvents? pointerEvents,
CssResize? resize,
CssScrollBehavior? scrollBehavior,
CssFilter? filter,
CssFilter? backdropFilter,
// Backgrounds
Expand Down Expand Up @@ -348,6 +352,9 @@ class Style implements CssStyle {
// Layout
if (display != null) _properties['display'] = display.toCss();
if (position != null) _properties['position'] = position.toCss();
if (aspectRatio != null) {
_properties['aspect-ratio'] = aspectRatio.toCss();
}

// Sizing
if (width != null) _properties['width'] = width.toCss();
Expand Down Expand Up @@ -398,6 +405,7 @@ class Style implements CssStyle {
if (flexShrink != null) _properties['flex-shrink'] = flexShrink.toCss();
if (gap != null) _properties['gap'] = gap.toCss();
if (flex != null) _properties['flex'] = flex.toCss();
if (placeItems != null) _properties['place-items'] = placeItems.toCss();

// Typography
if (fontSize != null) _properties['font-size'] = fontSize.toCss();
Expand All @@ -418,6 +426,9 @@ class Style implements CssStyle {
_properties['letter-spacing'] = letterSpacing.toCss();
}
if (textShadow != null) _properties['text-shadow'] = textShadow.toCss();
if (textOverflow != null) {
_properties['text-overflow'] = textOverflow.toCss();
}

// Borders
if (border != null) _properties['border'] = border.toCss();
Expand Down Expand Up @@ -464,6 +475,9 @@ class Style implements CssStyle {
_properties['pointer-events'] = pointerEvents.toCss();
}
if (resize != null) _properties['resize'] = resize.toCss();
if (scrollBehavior != null) {
_properties['scroll-behavior'] = scrollBehavior.toCss();
}
if (filter != null) _properties['filter'] = filter.toCss();
if (backdropFilter != null) {
_properties['backdrop-filter'] = backdropFilter.toCss();
Expand Down
34 changes: 34 additions & 0 deletions packages/spark_css/test/css_aspect_ratio_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'package:spark_css/spark_css.dart';
import 'package:test/test.dart';

void main() {
group('CssAspectRatio', () {
test('auto keyword outputs correct CSS', () {
expect(CssAspectRatio.auto.toCss(), equals('auto'));
});
test('ratio outputs correct CSS', () {
expect(CssAspectRatio.ratio(16, 9).toCss(), equals('16 / 9'));
expect(CssAspectRatio.ratio(4, 3).toCss(), equals('4 / 3'));
});
test('number outputs correct CSS', () {
expect(CssAspectRatio.number(1).toCss(), equals('1'));
expect(CssAspectRatio.number(0.5).toCss(), equals('0.5'));
});
test('variable outputs correct CSS', () {
expect(CssAspectRatio.variable('ar').toCss(), equals('var(--ar)'));
});
test('raw outputs value as-is', () {
expect(CssAspectRatio.raw('16 / 9').toCss(), equals('16 / 9'));
});
test('global outputs correct CSS', () {
expect(
CssAspectRatio.global(CssGlobal.inherit).toCss(),
equals('inherit'),
);
});
test('Style.typed integration', () {
final style = Style.typed(aspectRatio: CssAspectRatio.ratio(16, 9));
expect(style.toCss(), contains('aspect-ratio: 16 / 9;'));
});
});
}
Loading