Skip to content

Commit 749c088

Browse files
author
Nguyễn Tuấn Việt
committed
feat: v1.1.3 — CSS @Keyframes, ruby selection fixes, code quality improvements
1 parent a2c927c commit 749c088

File tree

128 files changed

+1963
-1232
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

128 files changed

+1963
-1232
lines changed

benchmark/css_lookup_benchmark.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ String _generateCss(int count) {
111111
final buffer = StringBuffer();
112112
for (int i = 0; i < count; i++) {
113113
if (i % 3 == 0) {
114-
buffer.writeln('tag$i { color: #${i.toRadixString(16).padLeft(6, '0')}; }');
114+
buffer
115+
.writeln('tag$i { color: #${i.toRadixString(16).padLeft(6, '0')}; }');
115116
} else if (i % 3 == 1) {
116117
buffer.writeln('.class$i { font-size: ${14 + (i % 10)}px; }');
117118
} else {

benchmark/layout_regression.dart

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ import 'package:hyper_render/hyper_render.dart';
2424
/// Hard layout-time budgets per fixture (milliseconds, median over N runs).
2525
/// Raise a budget only with a documented justification in the PR description.
2626
const _kThresholds = {
27-
'simple_paragraph': 8, // trivial — must stay well under budget
28-
'mixed_inline': 10, // bold/italic/code/links inline mix
29-
'float_layout': 12, // float + text-wrap — the heaviest inline case
30-
'table_20_rows': 14, // 3-column table, 20 rows with col/row spans
31-
'cjk_ruby': 14, // CJK kinsoku + ruby annotation measurement
32-
'large_article': 16, // 100-paragraph realistic article — worst case
27+
'simple_paragraph': 8, // trivial — must stay well under budget
28+
'mixed_inline': 10, // bold/italic/code/links inline mix
29+
'float_layout': 12, // float + text-wrap — the heaviest inline case
30+
'table_20_rows': 14, // 3-column table, 20 rows with col/row spans
31+
'cjk_ruby': 14, // CJK kinsoku + ruby annotation measurement
32+
'large_article': 16, // 100-paragraph realistic article — worst case
3333
};
3434

3535
const _kWarmupRuns = 3;
@@ -135,7 +135,7 @@ Future<int> _measureOne(WidgetTester tester, String html) async {
135135
),
136136
),
137137
);
138-
await tester.pump(); // layout pass
138+
await tester.pump(); // layout pass
139139
sw.stop();
140140
await tester.pumpWidget(const SizedBox()); // reset between runs
141141
return sw.elapsedMilliseconds;

example/lib/aesthetic_demo.dart

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ class AestheticDemo extends StatelessWidget {
5858
children: [
5959
Row(
6060
children: [
61-
Icon(Icons.auto_awesome, color: Colors.deepPurple.shade700, size: 32),
61+
Icon(Icons.auto_awesome,
62+
color: Colors.deepPurple.shade700, size: 32),
6263
const SizedBox(width: 12),
6364
const Expanded(
6465
child: Text(
@@ -76,19 +77,22 @@ class AestheticDemo extends StatelessWidget {
7677
_buildFeature('✨ Beautiful gradients and shadows'),
7778
_buildFeature('✨ CSS box-shadow and linear-gradients'),
7879
_buildFeature('✨ CSS filters and backdrop-filter (blur)'),
79-
_buildFeature('✨ NEW: word-break and background-size (cover/contain)'),
80+
_buildFeature(
81+
'✨ NEW: word-break and background-size (cover/contain)'),
8082
_buildFeature('✨ NEW: Advanced borders (dashed, dotted, double)'),
81-
_buildFeature('✨ NEW: Professional truncation (text-overflow: ellipsis)'),
82-
],
83-
),
84-
),
85-
);
86-
}
83+
_buildFeature(
84+
'✨ NEW: Professional truncation (text-overflow: ellipsis)'),
85+
],
86+
),
87+
),
88+
);
89+
}
8790

8891
Widget _buildFeature(String text) {
8992
return Padding(
9093
padding: const EdgeInsets.only(bottom: 4),
91-
child: Text(text, style: const TextStyle(fontSize: 12, color: Colors.deepPurple)),
94+
child: Text(text,
95+
style: const TextStyle(fontSize: 12, color: Colors.deepPurple)),
9296
);
9397
}
9498

@@ -108,7 +112,8 @@ class AestheticDemo extends StatelessWidget {
108112
const SizedBox(height: 12),
109113
Card(
110114
elevation: 2,
111-
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
115+
shape:
116+
RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
112117
child: Padding(
113118
padding: const EdgeInsets.all(16),
114119
child: HyperViewer(
@@ -153,7 +158,8 @@ class AestheticDemo extends StatelessWidget {
153158
const SizedBox(height: 12),
154159
Card(
155160
elevation: 2,
156-
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
161+
shape:
162+
RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
157163
child: Padding(
158164
padding: const EdgeInsets.all(16),
159165
child: HyperViewer(
@@ -203,7 +209,8 @@ class AestheticDemo extends StatelessWidget {
203209
const SizedBox(height: 12),
204210
Card(
205211
elevation: 2,
206-
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
212+
shape:
213+
RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
207214
child: Padding(
208215
padding: const EdgeInsets.all(16),
209216
child: HyperViewer(

example/lib/animation_demo.dart

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,7 @@ class _CssKeyframesSection extends StatelessWidget {
152152
<p>This card is animated purely via CSS @keyframes — no Dart code.</p>
153153
</div>
154154
''',
155-
codeSnippet:
156-
'@keyframes fadeSlideUp {\n'
155+
codeSnippet: '@keyframes fadeSlideUp {\n'
157156
' from { opacity: 0; transform: translateY(24px); }\n'
158157
' to { opacity: 1; transform: translateY(0px); }\n'
159158
'}\n'
@@ -191,8 +190,7 @@ class _CssKeyframesSection extends StatelessWidget {
191190
<span class="badge">🎉 Pop-in animation!</span>
192191
</div>
193192
''',
194-
codeSnippet:
195-
'@keyframes popIn {\n'
193+
codeSnippet: '@keyframes popIn {\n'
196194
' 0% { opacity: 0; transform: scale(0.6); }\n'
197195
' 70% { transform: scale(1.08); }\n'
198196
' 100% { opacity: 1; transform: scale(1); }\n'
@@ -230,8 +228,7 @@ class _CssKeyframesSection extends StatelessWidget {
230228
<div class="item c">Item 3 — 800 ms</div>
231229
</div>
232230
''',
233-
codeSnippet:
234-
'/* Stagger via animation-duration */\n'
231+
codeSnippet: '/* Stagger via animation-duration */\n'
235232
'.a { animation-duration: 400ms; }\n'
236233
'.b { animation-duration: 600ms; }\n'
237234
'.c { animation-duration: 800ms; }',
@@ -349,17 +346,17 @@ class _WidgetAnimationsSection extends StatelessWidget {
349346
style: TextStyle(fontSize: 14, color: Colors.black87),
350347
),
351348
const SizedBox(height: 16),
352-
_buildAnimationCard('fadeIn', 'Fade In',
353-
Colors.blue.shade50, Colors.blue.shade700),
349+
_buildAnimationCard(
350+
'fadeIn', 'Fade In', Colors.blue.shade50, Colors.blue.shade700),
354351
const SizedBox(height: 12),
355352
_buildAnimationCard('slideInLeft', 'Slide In from Left',
356353
Colors.purple.shade50, Colors.purple.shade700),
357354
const SizedBox(height: 12),
358-
_buildAnimationCard('bounce', 'Bounce',
359-
Colors.green.shade50, Colors.green.shade700),
355+
_buildAnimationCard(
356+
'bounce', 'Bounce', Colors.green.shade50, Colors.green.shade700),
360357
const SizedBox(height: 12),
361-
_buildAnimationCard('pulse', 'Pulse',
362-
Colors.orange.shade50, Colors.orange.shade700),
358+
_buildAnimationCard(
359+
'pulse', 'Pulse', Colors.orange.shade50, Colors.orange.shade700),
363360
],
364361
);
365362
}
@@ -396,18 +393,15 @@ class _WidgetAnimationsSection extends StatelessWidget {
396393
fontSize: 14)),
397394
const Spacer(),
398395
Container(
399-
padding:
400-
const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
396+
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
401397
decoration: BoxDecoration(
402398
color: textColor.withValues(alpha: 0.12),
403399
borderRadius: BorderRadius.circular(8),
404400
),
405401
child: Text(
406402
'animationName: "$name"',
407403
style: TextStyle(
408-
fontFamily: 'monospace',
409-
fontSize: 11,
410-
color: textColor),
404+
fontFamily: 'monospace', fontSize: 11, color: textColor),
411405
),
412406
),
413407
],
@@ -420,8 +414,7 @@ class _WidgetAnimationsSection extends StatelessWidget {
420414
decoration: BoxDecoration(
421415
color: Colors.white,
422416
borderRadius: BorderRadius.circular(8),
423-
border:
424-
Border.all(color: textColor.withValues(alpha: 0.2)),
417+
border: Border.all(color: textColor.withValues(alpha: 0.2)),
425418
),
426419
padding: const EdgeInsets.all(8),
427420
child: HyperViewer(html: html, mode: HyperRenderMode.sync),
@@ -438,8 +431,7 @@ class _WidgetAnimationsSection extends StatelessWidget {
438431
Icon(icon, color: DemoColors.accent, size: 24),
439432
const SizedBox(width: 8),
440433
Text(title,
441-
style:
442-
const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
434+
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
443435
],
444436
);
445437
}
@@ -457,8 +449,7 @@ class _ExtensionMethodsSection extends StatefulWidget {
457449
_ExtensionMethodsSectionState();
458450
}
459451

460-
class _ExtensionMethodsSectionState
461-
extends State<_ExtensionMethodsSection> {
452+
class _ExtensionMethodsSectionState extends State<_ExtensionMethodsSection> {
462453
bool _visible = true;
463454

464455
@override
@@ -471,8 +462,7 @@ class _ExtensionMethodsSectionState
471462
Icon(Icons.extension, color: DemoColors.accent, size: 24),
472463
SizedBox(width: 8),
473464
Text('Extension Methods',
474-
style:
475-
TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
465+
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
476466
],
477467
),
478468
const SizedBox(height: 8),
@@ -565,8 +555,7 @@ class _CapabilityTable extends StatelessWidget {
565555
Icon(Icons.table_chart, color: DemoColors.accent, size: 24),
566556
SizedBox(width: 8),
567557
Text('CSS Animation Coverage',
568-
style:
569-
TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
558+
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
570559
],
571560
),
572561
const SizedBox(height: 12),
@@ -590,8 +579,7 @@ class _CapabilityTable extends StatelessWidget {
590579
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 7),
591580
child: Row(
592581
children: [
593-
Text(done ? '✅' : '🚧',
594-
style: const TextStyle(fontSize: 15)),
582+
Text(done ? '✅' : '🚧', style: const TextStyle(fontSize: 15)),
595583
const SizedBox(width: 10),
596584
Expanded(
597585
child: Column(
@@ -606,8 +594,8 @@ class _CapabilityTable extends StatelessWidget {
606594
? Colors.green.shade800
607595
: Colors.grey.shade700)),
608596
Text(desc,
609-
style: TextStyle(
610-
fontSize: 12, color: Colors.grey.shade600)),
597+
style:
598+
TextStyle(fontSize: 12, color: Colors.grey.shade600)),
611599
],
612600
),
613601
),

example/lib/base_url_demo.dart

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -190,12 +190,9 @@ class _BaseUrlDemoState extends State<BaseUrlDemo> {
190190
fontSize: 12,
191191
color: Colors.purple)),
192192
const SizedBox(height: 4),
193-
_buildResolvedUrl(
194-
baseImgUrl, '150/150?random=10'),
195-
_buildResolvedUrl(
196-
baseImgUrl, '150/150?random=20'),
197-
_buildResolvedUrl(
198-
baseImgUrl, '150/150?random=30'),
193+
_buildResolvedUrl(baseImgUrl, '150/150?random=10'),
194+
_buildResolvedUrl(baseImgUrl, '150/150?random=20'),
195+
_buildResolvedUrl(baseImgUrl, '150/150?random=30'),
199196
],
200197
),
201198
),
@@ -224,9 +221,7 @@ class _BaseUrlDemoState extends State<BaseUrlDemo> {
224221
child: Text(
225222
'"$relative" → $resolved',
226223
style: const TextStyle(
227-
fontFamily: 'monospace',
228-
fontSize: 11,
229-
color: Colors.deepPurple),
224+
fontFamily: 'monospace', fontSize: 11, color: Colors.deepPurple),
230225
overflow: TextOverflow.ellipsis,
231226
),
232227
);

example/lib/css_animations_demo.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
22
import 'package:hyper_render/hyper_render.dart';
33

44
/// Demo showcase for CSS Keyframes and Animations in HyperRender.
5-
///
5+
///
66
/// Demonstrates:
77
/// - CSS @keyframes definition
88
/// - Animation shorthand property

example/lib/css_properties_demo.dart

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ class CssPropertiesDemo extends StatelessWidget {
4444
),
4545
_buildPropertyCard(
4646
title: 'text-overflow',
47-
description: 'Truncate text with ellipsis (requires width + nowrap + hidden)',
47+
description:
48+
'Truncate text with ellipsis (requires width + nowrap + hidden)',
4849
html: '''
4950
<div style="width: 200px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border: 1px solid #ddd; padding: 8px;">
5051
This is a very long text that will be truncated with ellipsis
@@ -56,7 +57,8 @@ class CssPropertiesDemo extends StatelessWidget {
5657
),
5758
_buildPropertyCard(
5859
title: 'border-style',
59-
description: 'Different border styles: solid, dashed, dotted, double',
60+
description:
61+
'Different border styles: solid, dashed, dotted, double',
6062
html: '''
6163
<div style="border: 2px solid red; padding: 8px; margin: 4px 0;">
6264
Solid border (default)
@@ -358,7 +360,8 @@ class CssPropertiesDemo extends StatelessWidget {
358360
_buildSection('🌟 Additional Properties'),
359361
_buildPropertyCard(
360362
title: 'opacity (4 levels)',
361-
description: 'Transparency at 100%, 75%, 50%, and 25% — clearly visible difference',
363+
description:
364+
'Transparency at 100%, 75%, 50%, and 25% — clearly visible difference',
362365
html: '''
363366
<div style="background: #3F51B5; color: white; padding: 12px; margin: 4px 0; opacity: 1.0;">
364367
Fully opaque — opacity: 1.0 (100%)
@@ -376,7 +379,8 @@ class CssPropertiesDemo extends StatelessWidget {
376379
),
377380
_buildPropertyCard(
378381
title: 'position: relative (top / left offset)',
379-
description: 'Relative positioning shifts element from its normal flow position',
382+
description:
383+
'Relative positioning shifts element from its normal flow position',
380384
html: '''
381385
<div style="background: #f5f5f5; padding: 20px; border: 1px solid #ddd;">
382386
<div style="background: #E8F5E9; padding: 8px; border: 1px solid #4CAF50;">
@@ -535,14 +539,21 @@ class CssPropertiesDemo extends StatelessWidget {
535539
],
536540
),
537541
const SizedBox(height: 16),
538-
_buildCoverageBullet('✅ Box Model: margin, padding, border, width, height', '100%'),
539-
_buildCoverageBullet('✅ Typography: fonts, text-decoration, alignment, spacing', '95%'),
542+
_buildCoverageBullet(
543+
'✅ Box Model: margin, padding, border, width, height', '100%'),
544+
_buildCoverageBullet(
545+
'✅ Typography: fonts, text-decoration, alignment, spacing',
546+
'95%'),
540547
_buildCoverageBullet('✅ NEW: text-shadow, text-overflow', '100%'),
541-
_buildCoverageBullet('✅ NEW: border-style (solid, dashed, dotted, double)', '100%'),
548+
_buildCoverageBullet(
549+
'✅ NEW: border-style (solid, dashed, dotted, double)', '100%'),
542550
_buildCoverageBullet('✅ NEW: direction (RTL/LTR) for i18n', '100%'),
543-
_buildCoverageBullet('✅ Colors: hex, rgb, rgba, named colors', '100%'),
544-
_buildCoverageBullet('✅ Layout: display, float ⭐, clear, opacity', '100%'),
545-
_buildCoverageBullet('✅ Advanced: Flexbox, Grid, box-shadow, filters', '95%'),
551+
_buildCoverageBullet(
552+
'✅ Colors: hex, rgb, rgba, named colors', '100%'),
553+
_buildCoverageBullet(
554+
'✅ Layout: display, float ⭐, clear, opacity', '100%'),
555+
_buildCoverageBullet(
556+
'✅ Advanced: Flexbox, Grid, box-shadow, filters', '95%'),
546557
const SizedBox(height: 12),
547558
Text(
548559
'HyperRender now supports 70+ CSS properties!',

0 commit comments

Comments
 (0)