From 5bdc6b41fc47b9115856013ca8b9ae4159431a50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=BF=E8=8F=9C=20Cai?= Date: Tue, 1 Sep 2026 08:25:14 +0800 Subject: [PATCH 1/4] =?UTF-8?q?docs(TStepper):=20=E5=AF=B9=E9=BD=90?= =?UTF-8?q?=E5=85=AC=E5=BC=80=E7=A4=BA=E4=BE=8B=E4=B8=8E=E5=8F=97=E6=8E=A7?= =?UTF-8?q?=E5=A5=91=E7=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cnb/.reusable-stages.yml | 2 +- .github/workflows/test-build.yml | 2 +- .../028-stepper-demo-alignment/acceptance.md | 18 ++ .../evidence/miniprogram-top.png | Bin 0 -> 22734 bytes specs/028-stepper-demo-alignment/plan.md | 6 + specs/028-stepper-demo-alignment/spec.md | 18 ++ specs/028-stepper-demo-alignment/tasks.md | 6 + .../assets/code/stepper._buildBase.txt | 14 +- .../assets/code/stepper._buildBounds.txt | 22 ++ .../assets/code/stepper._buildDisabled.txt | 7 + .../assets/code/stepper._buildSizes.txt | 41 +-- .../assets/code/stepper._buildStates.txt | 20 -- .../assets/code/stepper._buildSteps.txt | 18 -- .../assets/code/stepper._buildTheme.txt | 19 -- .../assets/code/stepper._buildVariants.txt | 35 +-- .../example/lib/page/t_stepper_page.dart | 282 ++++++++---------- .../example/test/demo_page_test_utils.dart | 19 +- .../example/test/fonts/README.md | 5 + .../test/fonts/StepperGoldenCJK-Regular.otf | Bin 0 -> 3516 bytes .../test/fonts/stepper_demo_glyphs.txt | 1 + .../test/goldens/stepper_page_dark.png | Bin 0 -> 37551 bytes .../test/goldens/stepper_page_light.png | Bin 0 -> 36866 bytes .../test/stepper_demo_golden_test.dart | 4 + .../example/test/stepper_demo_test.dart | 51 ++++ .../example/test/stepper_demo_test_spec.dart | 23 ++ .../tool/check_component_coverage.dart | 1 + .../tool/run_component_regression.dart | 3 + .../tool/run_visual_regression.dart | 6 + 28 files changed, 357 insertions(+), 266 deletions(-) create mode 100644 specs/028-stepper-demo-alignment/acceptance.md create mode 100644 specs/028-stepper-demo-alignment/evidence/miniprogram-top.png create mode 100644 specs/028-stepper-demo-alignment/plan.md create mode 100644 specs/028-stepper-demo-alignment/spec.md create mode 100644 specs/028-stepper-demo-alignment/tasks.md create mode 100644 tdesign-component/example/assets/code/stepper._buildBounds.txt create mode 100644 tdesign-component/example/assets/code/stepper._buildDisabled.txt delete mode 100644 tdesign-component/example/assets/code/stepper._buildStates.txt delete mode 100644 tdesign-component/example/assets/code/stepper._buildSteps.txt delete mode 100644 tdesign-component/example/assets/code/stepper._buildTheme.txt create mode 100644 tdesign-component/example/test/fonts/StepperGoldenCJK-Regular.otf create mode 100644 tdesign-component/example/test/fonts/stepper_demo_glyphs.txt create mode 100644 tdesign-component/example/test/goldens/stepper_page_dark.png create mode 100644 tdesign-component/example/test/goldens/stepper_page_light.png create mode 100644 tdesign-component/example/test/stepper_demo_golden_test.dart create mode 100644 tdesign-component/example/test/stepper_demo_test.dart create mode 100644 tdesign-component/example/test/stepper_demo_test_spec.dart diff --git a/.cnb/.reusable-stages.yml b/.cnb/.reusable-stages.yml index 8befeec3b..7f858b95e 100644 --- a/.cnb/.reusable-stages.yml +++ b/.cnb/.reusable-stages.yml @@ -29,7 +29,7 @@ # Example 页面共享功能回归,双 Flutter 版本共用;不包含 Golden。 .example-regression-tests: name: flutter test (example shared regression) - script: cd tdesign-component/example && flutter test --no-pub --exclude-tags golden test/widget_test.dart test/loading_demo_test.dart test/message_demo_test.dart test/notice_bar_page_test.dart test/popup_demo_test.dart test/popover_demo_test.dart test/popover_page_test.dart test/radio_page_test.dart test/rate_demo_test.dart test/tag_page_test.dart + script: cd tdesign-component/example && flutter test --no-pub --exclude-tags golden test/widget_test.dart test/loading_demo_test.dart test/message_demo_test.dart test/notice_bar_page_test.dart test/popup_demo_test.dart test/popover_demo_test.dart test/popover_page_test.dart test/radio_page_test.dart test/rate_demo_test.dart test/stepper_demo_test.dart test/tag_page_test.dart # Demo 结构与 Golden 固定在 Flutter 3.32.0 Linux 执行,测试清单由 Dart 统一维护。 .visual-regression-tests: diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index 714c0f3c9..ff99aac5d 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -85,7 +85,7 @@ jobs: - name: Run example shared functional tests working-directory: ./tdesign-component/example - run: flutter test --no-pub --exclude-tags golden test/widget_test.dart test/loading_demo_test.dart test/message_demo_test.dart test/notice_bar_page_test.dart test/popup_demo_test.dart test/popover_demo_test.dart test/popover_page_test.dart test/radio_page_test.dart test/rate_demo_test.dart test/tag_page_test.dart + run: flutter test --no-pub --exclude-tags golden test/widget_test.dart test/loading_demo_test.dart test/message_demo_test.dart test/notice_bar_page_test.dart test/popup_demo_test.dart test/popover_demo_test.dart test/popover_page_test.dart test/radio_page_test.dart test/rate_demo_test.dart test/stepper_demo_test.dart test/tag_page_test.dart visual-regression: name: visual regression (flutter 3.32.0 linux) diff --git a/specs/028-stepper-demo-alignment/acceptance.md b/specs/028-stepper-demo-alignment/acceptance.md new file mode 100644 index 000000000..9d1cc2cd8 --- /dev/null +++ b/specs/028-stepper-demo-alignment/acceptance.md @@ -0,0 +1,18 @@ +# 验收记录 + +- Flutter 基线:`ccace5c61383dc2c4fd5392f41222e65b54d8010` +- 小程序基线:`b60cdc8a1dce1f06dd45cb4e41eefd31c674e514` +- 公开运行页:`https://tdesign.tencent.com/miniprogram/live/m2w/program/miniprogram/#!pages/stepper/stepper.html` +- API Review:现有受控值、空 callback 禁用、枚举形态与尺寸已收敛,生产源码无需修改。 + +## 验证结果 + +- Flutter 3.32.0 / 3.47.0:组件测试 25 项、Demo 测试 4 项通过,严格 + `flutter analyze` 零告警。 +- 生产源码覆盖率:`258/263 = 98.10%`。 +- 固定 Linux + Flutter 3.32.0 明暗 Golden 各 1 张,更新后立即无更新复跑通过。 +- GitHub/CNB Demo 列表一致,回归/覆盖率/视觉矩阵工具自测通过。 + +## 未验证项 + +- Android/iOS 系统字体逐像素差异不由 Linux Golden 证明。 diff --git a/specs/028-stepper-demo-alignment/evidence/miniprogram-top.png b/specs/028-stepper-demo-alignment/evidence/miniprogram-top.png new file mode 100644 index 0000000000000000000000000000000000000000..d5e55aeea4a40638533c8d51b49de95d2fa9890d GIT binary patch literal 22734 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 literal 0 HcmV?d00001 diff --git a/specs/028-stepper-demo-alignment/plan.md b/specs/028-stepper-demo-alignment/plan.md new file mode 100644 index 000000000..efafe513b --- /dev/null +++ b/specs/028-stepper-demo-alignment/plan.md @@ -0,0 +1,6 @@ +# Plan + +1. 固定跨端基线并完成 API Review。 +2. 重排 Demo 与生成示例代码。 +3. 补行为测试、覆盖率门禁和固定 Linux 明暗 Golden。 +4. 双 Flutter 版本复验并独立提交 PR。 diff --git a/specs/028-stepper-demo-alignment/spec.md b/specs/028-stepper-demo-alignment/spec.md new file mode 100644 index 000000000..f7d4e6750 --- /dev/null +++ b/specs/028-stepper-demo-alignment/spec.md @@ -0,0 +1,18 @@ +# Stepper 公开 Demo 对齐 + +## 目标 + +对齐小程序公开 Demo 的基础、边界、禁用、形态与尺寸矩阵,并建立独立行为与视觉回归。 + +## API Review + +- `value + onChanged` 为严格受控模式;`onChanged == null` 表示整组禁用,不引入 `defaultValue` 或重复的 `disabled`。 +- `min/max/step` 负责数值约束,`TStepperVariant` 与 `TStepperSize` 负责互斥视觉语义。 +- `variant/size` 的实例值、组件 Theme 与默认值优先级已收敛,无需复制小程序字符串 API。 +- 生产组件源码不变,公开 API 无 breaking change。 + +## 行为契约 + +- Demo 顺序与公开页面一致。 +- 最小/最大状态分别由受控值等于边界表达,禁用由空 callback 表达。 +- 所有可交互实例均由页面持有状态。 diff --git a/specs/028-stepper-demo-alignment/tasks.md b/specs/028-stepper-demo-alignment/tasks.md new file mode 100644 index 000000000..537108d9c --- /dev/null +++ b/specs/028-stepper-demo-alignment/tasks.md @@ -0,0 +1,6 @@ +# Tasks + +- [x] DONE 固定跨端基线并完成 API Review +- [x] DONE 对齐公开 Demo 与功能测试 +- [x] DONE 完成 Golden、覆盖率和双版本验证 +- [ ] DOING 提交、推送并远端复核 PR diff --git a/tdesign-component/example/assets/code/stepper._buildBase.txt b/tdesign-component/example/assets/code/stepper._buildBase.txt index 62a0fd0d6..9a5c98239 100644 --- a/tdesign-component/example/assets/code/stepper._buildBase.txt +++ b/tdesign-component/example/assets/code/stepper._buildBase.txt @@ -1,6 +1,8 @@ -Widget _buildBase(BuildContext context) => _buildRow(context, [ - TStepper( - value: _baseValue, - onChanged: (value) => setState(() => _baseValue = value), - ), - ]); +Widget _buildBase(BuildContext context) => _row([ + TStepper( + key: const ValueKey('stepper-base'), + value: _base, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _base = value), + ), + ]); diff --git a/tdesign-component/example/assets/code/stepper._buildBounds.txt b/tdesign-component/example/assets/code/stepper._buildBounds.txt new file mode 100644 index 000000000..bee8b0657 --- /dev/null +++ b/tdesign-component/example/assets/code/stepper._buildBounds.txt @@ -0,0 +1,22 @@ +Widget _buildBounds(BuildContext context) => _row([ + TStepper( + key: const ValueKey('stepper-minimum'), + value: _minimum, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _minimum = value), + ), + TStepper( + value: _middle, + min: 5, + max: 999, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _middle = value), + ), + TStepper( + key: const ValueKey('stepper-maximum'), + value: _maximum, + max: 999, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _maximum = value), + ), + ]); diff --git a/tdesign-component/example/assets/code/stepper._buildDisabled.txt b/tdesign-component/example/assets/code/stepper._buildDisabled.txt new file mode 100644 index 000000000..0eb7b2b04 --- /dev/null +++ b/tdesign-component/example/assets/code/stepper._buildDisabled.txt @@ -0,0 +1,7 @@ +Widget _buildDisabled(BuildContext context) => _row(const [ + TStepper( + key: ValueKey('stepper-disabled'), + value: 1, + variant: TStepperVariant.filled, + ), + ]); diff --git a/tdesign-component/example/assets/code/stepper._buildSizes.txt b/tdesign-component/example/assets/code/stepper._buildSizes.txt index 69bb40614..d2daf9427 100644 --- a/tdesign-component/example/assets/code/stepper._buildSizes.txt +++ b/tdesign-component/example/assets/code/stepper._buildSizes.txt @@ -1,20 +1,21 @@ -Widget _buildSizes(BuildContext context) => _buildRow(context, [ - TStepper( - value: _smallValue, - size: TStepperSize.small, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _smallValue = value), - ), - TStepper( - value: _mediumValue, - size: TStepperSize.medium, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _mediumValue = value), - ), - TStepper( - value: _largeValue, - size: TStepperSize.large, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _largeValue = value), - ), - ]); +Widget _buildSizes(BuildContext context) => _row([ + TStepper( + key: const ValueKey('stepper-sizes'), + value: _large, + size: TStepperSize.large, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _large = value), + ), + TStepper( + value: _medium, + size: TStepperSize.medium, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _medium = value), + ), + TStepper( + value: _small, + size: TStepperSize.small, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _small = value), + ), + ]); diff --git a/tdesign-component/example/assets/code/stepper._buildStates.txt b/tdesign-component/example/assets/code/stepper._buildStates.txt deleted file mode 100644 index 888379033..000000000 --- a/tdesign-component/example/assets/code/stepper._buildStates.txt +++ /dev/null @@ -1,20 +0,0 @@ -Widget _buildStates(BuildContext context) => _buildRow(context, [ - TStepper( - value: _minValue, - min: 0, - max: 10, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _minValue = value), - ), - TStepper( - value: _maxValue, - min: 0, - max: 10, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _maxValue = value), - ), - const TStepper( - value: 5, - variant: TStepperVariant.filled, - ), - ]); diff --git a/tdesign-component/example/assets/code/stepper._buildSteps.txt b/tdesign-component/example/assets/code/stepper._buildSteps.txt deleted file mode 100644 index 962596520..000000000 --- a/tdesign-component/example/assets/code/stepper._buildSteps.txt +++ /dev/null @@ -1,18 +0,0 @@ -Widget _buildSteps(BuildContext context) => _buildRow(context, [ - TStepper( - value: _integerStepValue, - min: 0, - max: 20, - step: 2, - variant: TStepperVariant.outline, - onChanged: (value) => setState(() => _integerStepValue = value), - ), - TStepper( - value: _decimalStepValue, - min: 0, - max: 1, - step: 0.1, - variant: TStepperVariant.outline, - onChanged: (value) => setState(() => _decimalStepValue = value), - ), - ]); diff --git a/tdesign-component/example/assets/code/stepper._buildTheme.txt b/tdesign-component/example/assets/code/stepper._buildTheme.txt deleted file mode 100644 index 9060b912b..000000000 --- a/tdesign-component/example/assets/code/stepper._buildTheme.txt +++ /dev/null @@ -1,19 +0,0 @@ -Widget _buildTheme(BuildContext context) { - return Theme( - data: Theme.of(context).mergeExtension( - TStepperThemeData( - size: TStepperSize.large, - variant: TStepperVariant.filled, - inputWidth: 72, - foregroundColor: context.tTheme.successNormalColor, - backgroundColor: context.tTheme.successLightColor, - ), - ), - child: _buildRow(context, [ - TStepper( - value: _themedValue, - onChanged: (value) => setState(() => _themedValue = value), - ), - ]), - ); - } diff --git a/tdesign-component/example/assets/code/stepper._buildVariants.txt b/tdesign-component/example/assets/code/stepper._buildVariants.txt index 98121acf3..fc3795276 100644 --- a/tdesign-component/example/assets/code/stepper._buildVariants.txt +++ b/tdesign-component/example/assets/code/stepper._buildVariants.txt @@ -1,17 +1,18 @@ -Widget _buildVariants(BuildContext context) => _buildRow(context, [ - TStepper( - value: _normalValue, - variant: TStepperVariant.normal, - onChanged: (value) => setState(() => _normalValue = value), - ), - TStepper( - value: _filledValue, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _filledValue = value), - ), - TStepper( - value: _outlineValue, - variant: TStepperVariant.outline, - onChanged: (value) => setState(() => _outlineValue = value), - ), - ]); +Widget _buildVariants(BuildContext context) => _row([ + TStepper( + key: const ValueKey('stepper-variants'), + value: _filled, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _filled = value), + ), + TStepper( + value: _outline, + variant: TStepperVariant.outline, + onChanged: (value) => setState(() => _outline = value), + ), + TStepper( + value: _normal, + variant: TStepperVariant.normal, + onChanged: (value) => setState(() => _normal = value), + ), + ]); diff --git a/tdesign-component/example/lib/page/t_stepper_page.dart b/tdesign-component/example/lib/page/t_stepper_page.dart index 295e9472c..d86b5cf86 100644 --- a/tdesign-component/example/lib/page/t_stepper_page.dart +++ b/tdesign-component/example/lib/page/t_stepper_page.dart @@ -12,180 +12,136 @@ class TStepperPage extends StatefulWidget { } class _TStepperPageState extends State { - num _baseValue = 1; - num _normalValue = 2; - num _filledValue = 3; - num _outlineValue = 4; - num _smallValue = 1; - num _mediumValue = 2; - num _largeValue = 3; - num _minValue = 0; - num _maxValue = 10; - num _integerStepValue = 2; - num _decimalStepValue = 0.2; - num _themedValue = 5; + num _base = 3; + num _minimum = 0; + num _middle = 99; + num _maximum = 999; + num _filled = 3; + num _outline = 3; + num _normal = 3; + num _large = 3; + num _medium = 3; + num _small = 3; @override - Widget build(BuildContext context) { - return ExamplePage( - title: tTitle(), - desc: '用于数量的增减。', - exampleCodeGroup: 'stepper', - children: [ - ExampleModule( - title: '组件类型', - children: [ - ExampleItem(desc: '基础步进器', builder: _buildBase), - ExampleItem(desc: '步进器形态', builder: _buildVariants), - ], - ), - ExampleModule( - title: '组件尺寸', - children: [ - ExampleItem(desc: '小、中、大', builder: _buildSizes), - ], - ), - ExampleModule( - title: '组件状态', - children: [ - ExampleItem(desc: '边界与整组禁用', builder: _buildStates), - ExampleItem(desc: '整数与小数步长', builder: _buildSteps), - ], - ), - ExampleModule( - title: '主题', - children: [ - ExampleItem(desc: '局部 ThemeData', builder: _buildTheme), - ], - ), - ], - test: const [], - ); - } - - @ExampleCode(group: 'stepper') - Widget _buildBase(BuildContext context) => _buildRow(context, [ - TStepper( - value: _baseValue, - onChanged: (value) => setState(() => _baseValue = value), - ), - ]); + Widget build(BuildContext context) => ExamplePage( + title: tTitle(), + desc: '用于数量的增减。', + exampleCodeGroup: 'stepper', + compactDemo: true, + showTestModule: false, + children: [ + ExampleModule( + title: '组件类型', + children: [ExampleItem(desc: '基础步进器', builder: _buildBase)], + ), + ExampleModule( + title: '组件状态', + children: [ + ExampleItem(desc: '最大最小状态', builder: _buildBounds), + ExampleItem(desc: '禁用状态', builder: _buildDisabled), + ], + ), + ExampleModule( + title: '组件样式', + children: [ + ExampleItem(desc: '步进器样式', builder: _buildVariants), + ExampleItem(desc: '步进器尺寸', builder: _buildSizes), + ], + ), + ], + ); @ExampleCode(group: 'stepper') - Widget _buildVariants(BuildContext context) => _buildRow(context, [ - TStepper( - value: _normalValue, - variant: TStepperVariant.normal, - onChanged: (value) => setState(() => _normalValue = value), - ), - TStepper( - value: _filledValue, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _filledValue = value), - ), - TStepper( - value: _outlineValue, - variant: TStepperVariant.outline, - onChanged: (value) => setState(() => _outlineValue = value), - ), - ]); + Widget _buildBase(BuildContext context) => _row([ + TStepper( + key: const ValueKey('stepper-base'), + value: _base, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _base = value), + ), + ]); @ExampleCode(group: 'stepper') - Widget _buildSizes(BuildContext context) => _buildRow(context, [ - TStepper( - value: _smallValue, - size: TStepperSize.small, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _smallValue = value), - ), - TStepper( - value: _mediumValue, - size: TStepperSize.medium, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _mediumValue = value), - ), - TStepper( - value: _largeValue, - size: TStepperSize.large, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _largeValue = value), - ), - ]); + Widget _buildBounds(BuildContext context) => _row([ + TStepper( + key: const ValueKey('stepper-minimum'), + value: _minimum, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _minimum = value), + ), + TStepper( + value: _middle, + min: 5, + max: 999, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _middle = value), + ), + TStepper( + key: const ValueKey('stepper-maximum'), + value: _maximum, + max: 999, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _maximum = value), + ), + ]); @ExampleCode(group: 'stepper') - Widget _buildStates(BuildContext context) => _buildRow(context, [ - TStepper( - value: _minValue, - min: 0, - max: 10, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _minValue = value), - ), - TStepper( - value: _maxValue, - min: 0, - max: 10, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _maxValue = value), - ), - const TStepper( - value: 5, - variant: TStepperVariant.filled, - ), - ]); + Widget _buildDisabled(BuildContext context) => _row(const [ + TStepper( + key: ValueKey('stepper-disabled'), + value: 1, + variant: TStepperVariant.filled, + ), + ]); @ExampleCode(group: 'stepper') - Widget _buildSteps(BuildContext context) => _buildRow(context, [ - TStepper( - value: _integerStepValue, - min: 0, - max: 20, - step: 2, - variant: TStepperVariant.outline, - onChanged: (value) => setState(() => _integerStepValue = value), - ), - TStepper( - value: _decimalStepValue, - min: 0, - max: 1, - step: 0.1, - variant: TStepperVariant.outline, - onChanged: (value) => setState(() => _decimalStepValue = value), - ), - ]); + Widget _buildVariants(BuildContext context) => _row([ + TStepper( + key: const ValueKey('stepper-variants'), + value: _filled, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _filled = value), + ), + TStepper( + value: _outline, + variant: TStepperVariant.outline, + onChanged: (value) => setState(() => _outline = value), + ), + TStepper( + value: _normal, + variant: TStepperVariant.normal, + onChanged: (value) => setState(() => _normal = value), + ), + ]); @ExampleCode(group: 'stepper') - Widget _buildTheme(BuildContext context) { - return Theme( - data: Theme.of(context).mergeExtension( - TStepperThemeData( - size: TStepperSize.large, - variant: TStepperVariant.filled, - inputWidth: 72, - foregroundColor: context.tTheme.successNormalColor, - backgroundColor: context.tTheme.successLightColor, - ), - ), - child: _buildRow(context, [ - TStepper( - value: _themedValue, - onChanged: (value) => setState(() => _themedValue = value), - ), - ]), - ); - } + Widget _buildSizes(BuildContext context) => _row([ + TStepper( + key: const ValueKey('stepper-sizes'), + value: _large, + size: TStepperSize.large, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _large = value), + ), + TStepper( + value: _medium, + size: TStepperSize.medium, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _medium = value), + ), + TStepper( + value: _small, + size: TStepperSize.small, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _small = value), + ), + ]); - Widget _buildRow(BuildContext context, List children) { - return Container( - width: double.infinity, - padding: const EdgeInsets.all(16), - color: context.tTheme.bgColorContainer, - child: Wrap( - spacing: 16, - runSpacing: 16, - crossAxisAlignment: WrapCrossAlignment.center, - children: children, - ), - ); - } + Widget _row(List children) => Wrap( + spacing: 16, + runSpacing: 16, + crossAxisAlignment: WrapCrossAlignment.center, + children: children, + ); } diff --git a/tdesign-component/example/test/demo_page_test_utils.dart b/tdesign-component/example/test/demo_page_test_utils.dart index 8c1f45fa1..aba3393c2 100644 --- a/tdesign-component/example/test/demo_page_test_utils.dart +++ b/tdesign-component/example/test/demo_page_test_utils.dart @@ -25,8 +25,13 @@ class DemoPageTestSpec { this.expectedComponentCount, this.useFeedbackGoldenFont = false, this.useAlignmentCjkFont = false, + this.supplementalCjkFontFamily, + this.supplementalCjkFontPath, this.precacheAssetImages = const [], - }); + }) : assert( + (supplementalCjkFontFamily == null) == + (supplementalCjkFontPath == null), + ); final String name; final String title; @@ -36,6 +41,8 @@ class DemoPageTestSpec { final int? expectedComponentCount; final bool useFeedbackGoldenFont; final bool useAlignmentCjkFont; + final String? supplementalCjkFontFamily; + final String? supplementalCjkFontPath; final List precacheAssetImages; } @@ -142,6 +149,15 @@ Future _loadGoldenFonts(DemoPageTestSpec spec) async { ); loaders.add(alignmentCjkFont.load()); } + if (spec.supplementalCjkFontFamily case final family?) { + final supplementalCjkFont = FontLoader(family) + ..addFont( + File( + spec.supplementalCjkFontPath!, + ).readAsBytes().then(ByteData.sublistView), + ); + loaders.add(supplementalCjkFont.load()); + } await Future.wait(loaders); } @@ -233,6 +249,7 @@ ThemeData _withGoldenFonts(ThemeData theme, DemoPageTestSpec spec) { if (spec.useFeedbackGoldenFont) _feedbackGoldenCjkFontFamily, _goldenCjkFontFamily, if (spec.useAlignmentCjkFont) _alignmentCjkFontFamily, + if (spec.supplementalCjkFontFamily case final family?) family, ]; return theme.copyWith( textTheme: theme.textTheme.apply(fontFamilyFallback: fallback), diff --git a/tdesign-component/example/test/fonts/README.md b/tdesign-component/example/test/fonts/README.md index 733eb9045..4252ccc23 100644 --- a/tdesign-component/example/test/fonts/README.md +++ b/tdesign-component/example/test/fonts/README.md @@ -14,6 +14,10 @@ NoticeBar 新增整页 Golden 的独立字体子集,字符清单见 新增文案的补充 fallback。它排在原字体之后,避免扩充原字体改变 Button、Checkbox、 Upload 等既有 Golden 的字形选择与像素基线。 +`StepperGoldenCJK-Regular.otf` 仅补充 Stepper 整页 Golden 的“步”字,字符清单见 +`stepper_demo_glyphs.txt`,不会改变既有组件的字形选择。子集 SHA-256 为 +`6df8e74aa398c55ff2140025fd79c31300653bc02ddf31d35ec94f9c5ae3d0d0`。 + `RadioGoldenCJK-Regular.otf` 使用同一上游与子集参数,字符清单见 `radio_glyphs.txt`,仅用于 Radio 整页 Golden。子集 SHA-256 为 `cdd6b80b52382a5345597848ba58ef53ddf630aa29bfa1a4165b63264c000c2d`。 @@ -36,5 +40,6 @@ Upload 等既有 Golden 的字形选择与像素基线。 Textarea、Upload、PullDownRefresh、Toast 或 SwipeCell Demo 页面文案后,更新原字符清单; 更新 Loading、Message、Popover 或 Popup 页面文案时,更新补充字符清单;更新 ActionSheet、Dialog、DropdownMenu 或 NoticeBar 页面文案时,更新 feedback 字符清单。 +更新 Stepper 页面文案时,更新 Stepper 字符清单。 随后在固定 Linux + Flutter 3.32 环境更新对应组件的权威 Golden;不得使用系统字体 生成基线。 diff --git a/tdesign-component/example/test/fonts/StepperGoldenCJK-Regular.otf b/tdesign-component/example/test/fonts/StepperGoldenCJK-Regular.otf new file mode 100644 index 0000000000000000000000000000000000000000..55cac4fc90dd65155e8206fe9bbd5406c1877fb7 GIT binary patch literal 3516 zcmbVPeQZW1C<460+a9 z&khjiAKiPp@1Aqd$NQa+d;J`V#Uj)|kCK!22mAWO*TRRNCi1>R<+Z0fCV6_gS#jAFaA__+$Vd_ciY29foAb!^oML^7$$+6b) z2_}IUh??lnz^1sCfo9w`txy*@n|7e0M=G?F`sk?&?V=EUT%l_yp@<6YrftgiE3}6~ z%J~XiOJ0Y&LN8OEbTn3Iui|ySSfT4^o9opItx}ikvkG1Bc&euAzk#|uzu@&+7vibl z1igq8w2kc*#26qybwaCMQUTC{deId*8YLa{21-#8w?Uh!19wT@KGGI-d=!Uv2C|Lh zLsmktE6_M4DGU23Y;{;0c;>-}p*sOvT}p$ri+0m6xFk(tU4u>lUi`SbXbZF>xWk|Z zVOPY6LMIFVQ3?X{&6Zn$JOusiwB!H6A(r?Xk(fD_oJ4ygvXsQbk!R@u;_8&BeV9Ax zKH$v&XBzg5dJOYH49>QX?#1ZFvl}tqvjpeO*}5@TcBYm_T+NCA#sd6n7)9ietD{Q{ zd7uzLF@`7m%OTSf5=%dj$ART~wTEd6@-&7(zWb5mop|n}2T-G45Z20yp~|fUF4H ztn?g)t&W>xV4p!C%tJbXdmQL(e|ArB&+rIOj&{oou-@ci~@H z;XT9Iv3ptoKW99H!BH0E8+nEI74HhJ97k8c`#Ay)8D%-=D+D>`Xt%T$$PeS=>hgOG zNOSZZaB=wJ`sYEVkQ?^QYg`|$_>`;wzk}Z^q=zw?XV$HDIHSm+pBa@Vv53k$5_m8B zvo-C!e*-!Nj3Ng216Q&a9Ua3S97gAeWc{(3bo}vYNUB(G_G8C=Yp2|rvyESH4kcwh z?4G`U5+!An9mte@YIJ;o_3civqRf?!^DHJa$<^tDAG<@jQ^pW+3Gs4oR(GD=k6dBS za02VqI`OGjgeTUGA}a%!Bgm?K0$%q#fZWFADtq9%Ej@qujNu`^6tV>T7Jz{F%_vZD zXD~jyd$~^qtwY_Sn0e2y!@OPc%rTB{VLgW0MsO0uB;Skr4nt=Ud_PWGw&j}h-iu&0 zBrW{|yaJ3E{wJ}0@Sx%WBmInbQp3|2YAjGW_-g5rFB`Me5w zLfu%Cf~-Xx-g!U7;gxrwy?Zt69lI9x?^gyIjLhBzjF2@sn~aX7ycepwgyr0y_I}Dj zYM(6jDZ>~h;fv$2&u5OtKF6ytRPbFt!QIoVg@=ID+0Cz;}!M zTEe`7zYOH;!h7-IgByHWUs$l8Pd+Q<{G}tWg~#x#b(>2emxB~VX&%fKb5Si@hz8q- z_2lG)mgnUj^KP^CsJg~nt(a>Z=31w@%4Ka*o!1_@cCxk3X!SJKtl32O|MUfQ?P{Wh zS#@3cjXTP3s$VsqQQOMDT23BCaW}+Ek3ILx-b8Lx?@#F2;&^c?m@}sG#v6rIJr$6JI=+>DcHK3{Z?0geHo4Eum+$d|KqjL^zjAPUxaP z8}~^KjzL6&q7uZ7Yqy5j9@evZems5~36SQJdCf@SQ=9he=Z{KFT-Jp>xe=u3Bo#?DXe{=BM3e+uXw~*866A&1|FFdTnl`rTN1$v-1}{^ZwBmrpxco zf%nf|1vl4jG1p+muas9@-cjDsR37_7Is8%ZBiOxe-q-Tb{aZHoj6D0u&$CY-`tY}Z z{rmZuTC3f3v{)r;Q_$RKUB2S6ntH76hpc_ZiPDM8@kz7!V)@7AyUKT#p9!5@6|)?h z@3m-GZTVeu^%YO^2XiaSE6QgtTW8(P)BoLSU9bkrB~Jqfwrsg6)b%f!uQr)qQP;n0 zUTU(QINDm%chr5_d%EuQpHvm2{&98r=Z98QB^SJJ*IhXNysEzalM_{$>^d*C(i&1i zeFHJ7MQ7sTzLXbtt(Ue@54oj$eS9iELH=Z3Pm@2TWyi^%*0LJ;C$wS~-&QwUFZysA nXzdy7*?X|0G?Mb~YbyWOSm>UA5dSqQ{{d`u=H$PY4MhI~QMcq@ literal 0 HcmV?d00001 diff --git a/tdesign-component/example/test/fonts/stepper_demo_glyphs.txt b/tdesign-component/example/test/fonts/stepper_demo_glyphs.txt new file mode 100644 index 000000000..c81d8e6b0 --- /dev/null +++ b/tdesign-component/example/test/fonts/stepper_demo_glyphs.txt @@ -0,0 +1 @@ +步 diff --git a/tdesign-component/example/test/goldens/stepper_page_dark.png b/tdesign-component/example/test/goldens/stepper_page_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..3021db07d732316eac31e82d0c05b63aaa14de5b GIT binary patch literal 37551 zcmeFZc{tW>-!FQ(n>ElJ6{&<&q(K==r9#M9X3CI|Q0Ac`NoXL+Os32;88f7=MCN(U zlzE=npYwU%_pf)Yb?jrUwb$N%?B_V@e(r8v!|y!L@Aor(PZw#)tD9*VX(<%S=Ihrk z%TOpZ<`l}RW9!%APvUoVcHtj1rZQJWC~;-``tdKTO+~KDt;hdt*57?Wp&X!GzkE^7 z!f&v}QbVF{Wo1m4=bi1lYX@Dgtv~qofR_5f>D13VVnb^6<*$fWC`6?x$wkY}-Fmqz z>`LnUZQ{o{WDZWVzF+Njyz=t2;M~&KjbW}kZ`W&OwR+^~lnI&+`)rLrZ#tYg!zdT8 zCdkalqta9BKd8f4>)KwvLHy_wLueEe$=r z?``%gzZ^Ggr_6RZGk-XxyM;~C&!Vzrr^t(SI-}Vtk3!e9=o07 zINXwT=ia^RA|n4ROb>O{#wt_x3ETPEuPp6mW@bLB7`Ms6-+zDV{W`n5w%bHrTpe<` z@$(!XAJ6^TV*-MLG<$fB_9g55Iy$ptGuQ2HVQu}+*H>ImkG(4V#-ZcK-3*)3Xp9Hz zPg3j_hIk*3wEi0J{yEpSvRs1q`I*Dj*^pu}rnPPRb_QM}m8hvNX8li-lTQgRjy{vL zY|FL1SDz3(KL6&>)y}@Y?`(lKA$8AvefNI*_Ki=Q*Qoix@#8n<@?@INvJ6jOE?64Y z$g>y=X|;bb&aGLndU0{_`>$WxLyf66GcD%Sv!^F8XTj@thI{rgg%Q&&06O-&2S z%cU&ULPa;LsH(aec16eM7X12kBVw?G+5T=t$dzL%8T6-4o$@#2RE)d(_34_KB_^kN z!D(Z2GqXRw4|0R`Yd%ZU58nCqiiL$GSY@WGvs1+PtRdx`S>J2Pgx%VA?|z!d)=MxS zY4zuAwRq;~x#O%+^R2ig>qbjU%ab;<#`<+}Zed}pK0ZEVal3zdC)=+qv$f=0{cP0o zr8(PDHlh?CaKv_HejuKYMaXvE>@?%%9IL5=Sc+oT-NL_@FNuiEPF6|LOu8=|Q_KE< zmsmAgr*1DOz0f%~daIB;MYH~GBY7)!nd|uT+rK_bOiB4u=Fe|4@r&20Nmf=iF)b}z z(w}eNd6UZz78XYGq?*zUPxA0+{rUdJ!qRfAMp50%S~yT4&~BbXQc`lCpq1x9UHlzg z-K!TaP~IK6q19RBg8jA6VL$(4`kgzAUu-=TVCKynHPKt1Y`0|PpR{rJiM|><6vo=x z+Pk{C$$AwBZES2j4bAP(54Pn6W@MaGvl%PCT5md*ZDr7*rjp>Xm)E_%zW!=b9#&A~ zD@_&NZ@@6`Vb@x`LUpv_$eY2H+qLNr)UlUKTXU@EMhod4QLlP1-3S!2^)$Ax#cme* z-KL_WbHtbT!3o)x0_{}Ac(vlPvMu)Z_Kauriwc}J(&)A23c9@F0_1Q+PQP;+Oz#ZGGSuIb$(Vio#~jr{rtI6SXlTY z?}Iqr&+~ty<6pdbb$75nu{2P4CG+F^lP6C;d8!?9Woi5;SBhT6(@&oc=gxL+R7%xf zq^81g$3XzkYpE zS}NhbpZ^<{Gd?-~#f$a&)satJTsFiir`KASkL1iSVGqd!Lvid6uU@ATXUf{mj732g zpS`s8r@taNZk)$o9~v6U!2fvg(B{V!>@4;@!Mk;FXi^NDcHy(O+ASD{goaLu&hF(k zDxy;VX3{=(uw9t0h*uYW`t<1w4-Z9AKgvk<#1_i0k7v66{CKx%@7Y%$KI};|Yzp5O zKie1T(N`I^kxeS#Fb~f*ETz@-;E$oE^xK&xVU-Gn&o?)GdBpkf;X@SA=Uevk8Bg@w z@L!snoyGA}J8Rf@d1-#?USkRev&|^YNbbT33Lb%0eS&85mq)HB%lmnGc|V>tq~dRr zck+B}V{5yCj;?olsHr%&*Pq|qWa_Vcccy6Q%`G8#bq}XdIYte4jp8sUizH_fp;7yko zEk#5`JXt@j+p-UTylN8zk0bW6LcH4MHKC3J%o99%5&|#@1XOC|r(Ow<#ZI?N-v=4UYzD<---NCi^bp_>f2CeM0pgjsD88 z(|W%z^a?sXf6ik${%2d;gv)j|&*ZnOR;}_meQz7ina*%?<|f9|FHqyOKMf5H{X%&! z2*2U$nIvdEO}~5hx;1%9l*W{M&r(y*JbwI`f-kv>g3_9z6g$3%FHrRD+c@eLN8ZQb zX_WK6WBw_rsq%K$9r2D2JBzHBl3(_g9-^D6ufNr5JtC+*sTQkrCU<#$;Hr?7l(={y zl}f9wuD(3i8>lrvj@H$ySJf=LcQ!XSe?aXi@nG)#{^pS1xra~v{Pz8=j(V1r#a|U6 zWq;S!mNE8r^7FjqdDkba*2w@9{PWL0z#>6dv#_`syAG$_+`PQKgAK{3h8*2!Q~4DY zHzSO6bi&8ap$elhNaK_E^EEUy@RgSb2)d@H^KNE5-Ci!dQdCpp6&cBnub7mFpKI^# zzB1AC%d4&>(=?)VWC;s=_{E4D`034c>5VZnpBXz7 z6O)*KK~zXqp#6M*grlP)_r1!)IQQJAPk+Kv&d$##8MW{g6c*A%D#S8ATSwQ^^UIes zL8^#j0oP8JmsZCP%@jD04ibeQsQD~^2i3>JtaT}GWf_l6j7{TZvT=t7s*CpW@^bdlbkk|WMo;rL+w`L3mz)YQ>({VN zn)O#+(QV3+O#AWu`)}nE+w_7iiq}#3g68IZ+qZAe&dIs`#Vks#rJ(D?%$?S3%Zx8y zc+7{JwG|>t4WO#0t-w{DG~+-$L^H4 z%S)<_Pfp&&mtMVYo$y=XvQxTc?HwJ#6WenSqqXRwE@V&DDr18?h6s)(LpS*{UFRO2T<(JPXXY!@7YB|~-J6`nx zrv3EdRQzz>RL7^$pgH5@@bEBS)y?9u>1mzsuUS^FUag^}Rgh`gdn?^&|D(Uv9Vl0< zEG#sDbJ*|9Dk>^{zk^qC8f=S(;(S9zT7r($RG{ z7mqg8lP9&eqvI=qB3fDp@7Kj0PmK!>W|99a$HLFQ7aIzoD{N74S3vMQPEeof>@YUG zm3oNC=;1Aqt@}q&?sTUI8?qOMv$`2ay}8tNddvLH0Ks&AeLSgCx+fQVm?vkNtmyln zOH*~~#c}Txlhy6!oW497;L*sZV4Vux_VOkqBm~(l%~J+jvJ|6y-@X;;rg||5+X-Zu zkMxXo6yk&llkUD|<1S+?u7QDpUPBTq%4Ox;ncrU?-3L%}adE-dTD@`O#+>daXY{Kz z@Uc{~Ew*Ce0JS%4+$d}30zmC{@!8r$jj#Wptz5RV6T0Dhwz#Os@%QiF3s!CB>i-l1 z;cq=8DxIix1yBAwRwb%rFBaX?a`MQHkFNs*J)E4@h`&FU+1obVUlq~cl+Ja(Hm2iu z@FnWSKUs=>JJ#BEq@gafPAERH5E6WI|0ingwtf3b)7$LCr~cMN-3(oO$$881nT^iB zKAc=dM@L7_S-e_~@#Duj^OOCo%U4gK0)~1Bg@AqNon}0E@E~<@LivWI-?^_>nQe;_ zGz&+kr;i*s-~ia6b?46QWS!0U1ULU;ecv$&TK)jgq>{k@~m+2`EDgR&8lVW=)B zTyNjJxd@2d%6b4u{szurVrnYup+nEm)H%P(vmZT5iz@!NE?!DajR{OiNL(% zNR2+}tiU=4czM0CLj*@tUuI`#ucxIg`1w;jbFu(180C+? zrClW+-kigN|2VPjidE0ctrx$vT8v7!}vr$2><6L_(_I3WdI zm2RDz3mUKqCV~r(fU~IypsAs8;K`FG#kE`lzT-Dl>~0C< zh+MjKujcbkkR`zT$y_NF|*@B)?zjo2AS}R~K`#fYYz?c8zO=E{>^eJGUuJ(2ZA0LLf zxw*S{?-~!(9xn?J{8Feh0mKC|S)By=}tnv#-cHq_{KGgS1=n>Sy@ zxpF?$)uI%gip==Z1V+X)FdcI=oQ z3U}FA)X}HUo=vF{l7==!liohNeehD8QCzSfI08kH5zM|q{8Vw^O_jm8MgNPJQ zhdpS^m5aG`GhX2IX;1tdXn@?{0EjJn$BCj-F)D>EWo7OPu}U|iWLQxuz=fqP&#shm zpE*-pTbovIhyzu;_AiQomvNw=^;vXdyn~aJ(46B;n|dO5f@vvSK zH|;1`le;j?-)h;r-)?D2F^5aU+S+<>XvnJzfC&6!1KR77Ca(J!(IG z6wu0}QjM^p`UDnmRzO_m>S{R(xZ*{$G0Lq(tu=VCA!xTnMMdNR_zUIC_4t1H@PU5o z){9nFd^9vPhmRadvYs(Qua_TO&;y1D2ng^Kuzb5}-4^z4r)ZU=sL>oNz}MA8mS&R}rhsE3`0p zit_gD+k~_wLIH|ZDzT_E}WmLlR#o8`gkV2Q_?>$L zEo*Uw?sL$Cv9U4q;#~{3v9aHJdq-52r=*-7pO}D7Ra9B|7Niy*B(xeE^k$>0n_Czl znN?^XPW_b)=AfVK>pLqU3VER5JRE8~6Q`OL?x`53a@!}u6p6a1EZc?0 z`}XZaS<(Q?rVxSE!GZGj-MhKLHe^}Zqn->*34b~1I+hY%HP$vcpfrG%F* z8X$d!Zfb;a|Na}Orp%u=vlP9%d19R$o5Y9wb<8#wfFJ;t$Q}Tr#ZQ2A+hd1_x|p`? zIF=Wx(f9}0s|UXn0+esx=HR?cd*#X%4v)O~zns|KPAIFOaFtQ!UEel$kNvHQ?yrg7 zjk*C|SQ#bDhNm5*Q7vROsh4ACX>HBvVTv=oZ;*lmBLw9Z%_33z=PvEPp^^8h!ZjZ} zkkZ%xoV3XVk_MIQHG1eBZEd`TkBLg?Yv@sBJESXCea6B%Iy(;>yK?-?YMvuUM9&8e zVf%s$2Wu3Up}xOdS_JBNZ?a(q6%eR;bv}6Bz1kQCe5?VF zzD^;y@_kQnNy)p{uK{Wr1ieR5D)vfANuji%O3P92gOM88;)p>F7dK2k=ep~72pGtp zo}MJLei_ybSA6l^$Cc9@pLT5ti@hTyDX9>iZZ$LPhMv}x{-77@P|PHq1KE?`d{|CW z1V!fkwn5bW?3q?;u@}m>ZY5|H(|%TneHj~j9M1*n@2%bg>HqEr%Z>Nr@o3^zPHE%x zl=|~~ezkdCCSeiL6s0?Y09v*Z%{JJx(ru1{Ho~_+XWVAhuj3%H#I^_YX z`dPPc--f{Mtf+3g6Muu})G42nch=&d6MT(U@y6S`#P7VRnHsOjpKH*Xf+se1Gnq`;|)Vg6)y?OmQ z$n=*dcuXP$W}Py>4GzA(%8BtF9v*BbPrgAJGe&WKzIktWat>GwRHaIYp<3$d&~CJg z?Bcne6sWHOU*mg{iUaS@;SC&wl6YB8ZU;)aC4-RDN>z@vIYE{SfO!P)1-~Y3}2XW)fdz{R$BDg%sz{6RQv{L8lE~3}TVfA0PsZM|>NA zrw!&T0T=0Pf3y{N?IBD9JzFd@D=Vw4@ozztOMyJom8<2Tud9Oa*s{mI?G>BLww%CO zdoIbarp}0CayV;5>+W69#@w7V)(J^&GUjB}T@%_gS8lrXGog42~`C@iG-bhT07X3vR|4!94S(<-@Li-gG z?(o1VdJ%#BOjduEi+8IN%?x{2407`ZTH1rc!hzsjAr*Q-8cWjvZowL#3o9zNLS#qN zEkXC6gJCv0GgAU$3|+`oQO(k6anWXQa1a`GVOg1E?<)l;!qX#dQbtB`+diTi*75uN zsHk{@qW}8s+mM(*959`+&SGife3RMH4rpz_ew$kDS8Pjv{qkacRUG>>&wFm7m(#=d z%zaU)6ZcxPGbNRA5_Mt9v8IhxigTSbYChL(P=OwERQ57xr#3|AnZc68J0*H8U(Vo| ze$py_>BslzB_s%x{rx##&YwR|^_1**=rB5J>~Fe@)EMV2GqbZ6*oohukcz-o^O{qo z?Rk0V;K2_3~MXm&ZuEGtQeU#(HjCoBZd+mmh@fg`l*8Fzkd(jjH;+yu24u30j>8>Q4K} zhMx-)|Z&F0RjVQBVE-{gaMkF}{DlcGjRiKR$0+Noy}^s&46rlc*ptdI*w1x2Q`m{mv=W%E5O=QR1m10MNt3TL<<3`VoeX!)zx{ox3_EM zB|r>SvAeL|i^IEy2Ni*IzRb%PK=6qmw6eTpC4N8=8wShX-6>ms0+>55qk=FX-9UH_(4m7@=*|9E1C#U|JIVd%^ zvn@{IYm~qmfzm6kd%hjUQKs!eTG@~5#rPN<1Mzva%8Bm+0wnL=J)E~VF76Y44*rfi z)M~7u4P>Gi)vWg$wjcQoIPK@}?<%-4^|h<(MhX#pl!Ik0`k!~=nNYjeIZFGOy zQ<+pS*wG7Ll(jV>B*ruwTZv0H2PbQ%HA`&P!UUeo&Md%T{ZRbzJI|;I$ z8CJ=9>;~N!p`x&L!VcSpxXNKXx!rfhg1-KZr&AbOBN#!*VRA#u5jzYwwe&ny75uv+IC zz4@6DC|y^g7S35svO90tU&+aQ-sJGjn>YEqk1(CoTCH0ipbd|?IIRYS8UWIZ|H`Am z`mKRrr(mnR`@4A0~Kr6kWvGMJP50L`qj~{<4D~qf4z1CD;&pzXR+=dGz3JNcw zGmNM8E{KRcl}w<6@)NBX|K8%b<)K4|j><*mqhaVlp#iLcLX%P?w4Nn^tDDb67~UT^ zk<-%(J$${{ww2`w1Ast5i0?81Y^-kDPFRVCLOUU?v)>Y0}(4CkEM5=y~l*#qY@D1M z!9}1^fG#<;Za#;Cm~OIp2Bo}Pw9F|zjMGLfW68)|{e3$3qIj0d2>(d-GbnDPUw;4o z0xamQukX){hh2n*9655tW^t@UZ0XadPdqIwpHE{a6*o8g;l+U997RJlvBNSlGZVp2 zp>PFj92Q2U+t!38-40%$l4-K${{8!4w-Bj0jUPR#$&?yIpMsQ0{JIYxKXwibM4Lwo zqlkgIQLc%LA3A*aPjG7}y@+7IkMlDy5#6zA$Kd}0N?&^X_-urvzZPKVCT1Z&*i^fY z-MRp2KT1COJrCoFNodsqzwJ;dqh2)vNRvhjKU*w8*7#X}0X=%Z4r(kl4FJakxESg& zI5RbN=$}=qPM$ea)6@n41PaUs%L$gKzw&m*y?akR9=w%{C0J+0C9?hzXPxm390RH+ z2cNdNa2}l1OCu$yy8!*K{{>PRG&MC(8#V876MgpV*($6n1zqrspI=ON95xM}R7+j1 z9iHg6h324(tBhK+qhxh}ttXP*vP>N*4v1T}6deA%&i=56(7dDobj zV<}38|W^r{NtC{LbbdHDS<`G!jnd}W2^qq4uMjb|adXcX_{L}{qveIVV zFTLj4jT>t;u)~@GkwIqhh=WSY7v|@;?cC`EmtROo2v7GRu&n=CybB^gHq#BdVhz?K zIRr4wqTvL!i%0f7X%m435C(-$n!C*waH%X%SPGo3uRih6&-cd*tE*G0%R6Av9-HVT z0xDJxq7dk`s0Wi9nAF;}YYB1o^11@k96NmQS2PQ0Fq5K zE&*N$cqJvy2vA)3nr$g6`n+`j2RZCiubLjV`DA~UGj^JWhK6xDS0-+ICX(-Br ztvSk;txzAqpRV7yA+Jzs(3r9TMH%cv6dDq2k#-PazIAa<^dZd!E!EYYME+;1^3+!9 zxflx-6c1P9{{5c_Z2*#;KdzJ_E!q!mz>C5e7C>({WA^&VlZ!60muF1+D_P-5Ji%T7 z0YTPeAl2~BokIA&x8ZEVodfFs>vtIM$ezRc0d?{6)vK})DP?42CZ~Nreta1kdWb|Y zs6avm8@aL_keEQtj8RUHQ*k#%$vxh^Z5TGxSAbCLSI?`a+A@&%Vq#-0A@N12Q^yQL95`XA|3eR)2! zJ_o!#2M32rt_=gKKKm_}s*o!iyQlCId_y&Hs(Y~_#391YhVVnv?zCG?I$Rrv>^fQ) zmX;W32?^Y&7nzR+cA*S~f{COUwJ4q6a?sJj&Qm<2E=tyUa&oeS?@R(X5)@}KM0iMf zza2`jQF*xsdcj`6XqY~sr_$R1F>>B{10Ih7cq4|y@w2>K7j%+uYB<1@%RM$WcKkfq zdnn29LCxNa|1;Q>F7@D#njBs?-KYg2rOkWy?gegfc6MHegw$nGQLrvv7{Uk`g#gf^ z8ht=RBDxYf*$%(;@|7-1q?CCZ$KOsq0<%3sS8)6GcUn?+lM)j0fBkZUn1<)=8Y?RY z5d!-&0$q&gjX28yJy8FMzC`|@CCmIB04jDS!&!qp=%z3F;PlzZE;StFq46Z#8B1C0O=iw!>Ig9i`d)N+*mT5l7Hth(f!g-*)oCdxHQfC=jp z6r!(iS&>fI7GVSi{3J2)B;g7>E?;kMX}K;gPI5OY8OAge2sI?<0t$5AxSc|Q-}2|r zpZ4C~tI)ES7G}5}mgND$SI4WX$J^jD684d-TmJW0^fBs>9~-ckhzeX26Z_JeR8+9h zZ>L~AKjc?!KIfGoa%qG~<2zk6(R#wr&+SYSn4R8;Mi0GBPAH zI!PTG93(LS6bh1qymkBb)@|EFuotigiyInzK>WN%y0($xHlr0H+H(>9Y8S1A%7 zPrE=XCK4$W#kKjI@!29^T=1Z~Krrj>-2o>C!SkLEK&C%ZU99!omeS;<27K zAj&e2jlRf>UN>TA*`*pZY;!<-FU$Y|B=nG-$}3=P#m^TaZ-yqMre2AzF#)IrqWXr< z@c}6zX!_^QpT8L_;v};$jyTE$iY(-XUAilSAZO%tUMN!joZ5Lz` zwTfkCK+MVzHG@^FjSm%8yHjL6Q*nv}ip(BFWNv&sovGUb(8qoE`)i)`mOOiV_~X~4 zq)7VAs>x&D`GVj}&M>0rVVi}e)u66YK&~M1IgfWI05=q@kLAwNR-4SQLuZ6YGj z4vkU%8csYk-0BU}1xw8Qk2ev6o77+%8v#m1Ma4covlo7TempbR*R!yfzga*PCNT<- zRw_@VZE5hDbenh`<4Cu=4Z!LhV?^ZMSHF-g5zn z<9li8-J%y;W7KjO;g(AV2>kHmki|#SU|8AdNZ+}F4kG1y*6oDq7s_iG_b|NCQXv8p zRfN?KNs;G(JxW7MBaeRvT|~IrAMO@PN{RA=oGWNYQ8Hmv+f><16K&Kxnl+(4kVLd| zo59Etf8coJd-`6;DMq@@o3$Z{kX!|JYk%s{$Vj|ET6(%-?r91fjA#K#EGm}D>~Hl3 zNET=XG{5yzk?XmmsY&AiweaiLudI^iH?Um3&cxSz99pgAD45tugL-ZmSy=)DfEtLL z2*yLt#3Tv*0)L+v9cV02lc?E&;3}&UVD|t7h~ON+od-+06jcTDHjE3Pp*Zc7Hg$)# zJ3kf!;vPykCBt&!$c}vmXU?95O2!X!n?3%mJ>viy09w{v2+zr@do;Ij|4OPel;R_ynNs;vzEgh}Vy}Y762rtiG@{v_b(c6kF z?d8yl-^eXM2|16J34n!&@@quMJkK{n0dXOc1c*b*{kknMVn|?#PIxgN*?}Mpd9i!I zj5k0O&8Wc6&Z40ew_B1dCvZ-7{)LOifJR4~AZteg z;b5<60pRlu`3c(xKvix3^XD=S$_rQ5LolDw9Z516Mn?LBwjQ8~!n(S2i9j!U5oxA% za;i|!OV-gb$uaE~r0@IlXEpg;w=#@7Y)1-luq+4v{BiX6Cn+QnmgJif;}7~fJS+)L z|A-3Nh{t>xE>oLgAmG9tYXURrMRxQC7qiG*-_I z{Gc4ZP?T;(;rtjv_arNUc?TVQD3~OBAS$DRe*gYm12xeq&l8g$zb`pkchGJF(?K-- zob7x{QtW8HmW)j0rJ=58bV5N838<#vEZeqiLksGLdLTBJvn6tuE@6Y>o3kDbJkQAy z1iiMJXo2Ob1E&xh<~PhN1pPiGw-gqxqIKWyX=d{kd>rYGu`Ul`6EI*1P-eAN>R-%U zCMV4Z1wgzwO%*D7l&NsuEr=t5P>Zp-6fIRwH(O5+MyZU1^@aVzR0K&7kf9SwIXQ>G zpxbxt3OBF^A_#7G(8s2sK!{-tD3X)w_;LA4DjZnaEicP3^YCDSWOYJC-NX#*T3eZ{ ztrxV?wRLqlJ)k)ifwhIk80Pt+_m-JS1OrPn*EOV|;s3nkynsCUo>MxT@Vb+O4e#*Z zUVr@f*^k}R$0zDk;L?HR*)F=C^1yPqDnvnn`mkvaw*x+)@Nb6CboU_vsN~tH#%BYk zAOvx=d}3k(dF|+=`7r5@-O|Bm202kIn0p}s8AvIJ^Vc-h!885Y;Sb39H@Hv`_#L3W zD)cHHY!0%m31GektL z-kuujX$A~nXkU>nfi|0rxf&V8u2&4FMB@z*wj{j)Tta()9=(XCeC9rBD5^&xyO|9) zGoXrhHy%TjSQpkFU5g#6^CJ-f7M3T_YGH1}M;EK#ZGNGqzWxKcbeZ3I*|@4bcu=1} z0B08#z}_hrBqg`}M_3wM$pc0|fjslmLnKv?=C1)amCEG<<2R&;Q$$Hg>F5&IP_qMG zBmp1P#9AHXh&{cA2Zco!ERB3B5CpW8lI5iZ@t8b>G|(A<-EwuCpog+@a=N0RlkBYB z%91&SM8>1}WeRBI!OPGB<>E}Mk<_d39Y-+pE{-LR{;ms|t&4abkw7a@Eg+da0puZ} zWBhGcFp83+M`04)jG9w;R!bS_!%=xV*Ba;Ni)u^WK zR)ConR#tF93$bg@fy5}M8B|1L7^xi5rF+nR;&bPZ%10}Nfe=E88H3qTh4$er^p#UU zU@=&Y%TYQ)cUV$F$`zhmzrWe!IWod zJE`~k0LUAK*fv;UGI;~pr=Xx9At|Y#x_So|9$lprn8B=Zs5OTldMNcq)JQQVLjaA? z)B$%~WYi#VbSFX*0rIqp-wdyfoBK6hhXPTGbWjAmpd4I|AQ^ms{RttVi!6@p>QFkI zI_3e;k(B<5w0A^u4%~L+hhM^cVAoz*Uf>F}on|0;ZOBoGEo^l_yCpKzty>>t(nXwT zp|FWR$iogILX78{HEXu+*zrj~7}+F@f2=;h!Qq0ZR}rnqg?((Q&fC8>!?bq`y40HA zbN{${c<3T1P9awJOiehtGc7*QmD|e718e+(HGd=v<8|R6hc{2>!Qlk$Q0$yWWkIVU zZaBh6pGe70!Xw?aMf=(ffFyG|8s zHZ(BU!~Zx&^7i#ZGjRGf_4KX*_0tfonnGkQBxpr|-k^nLaB^RD-{%4uc09Z91=>d~ z5o&aWc^|ai?I>`fo65ykikNV1$MjVgfbcQpv{#OftBE0nzz9&|p(96nf~T<`>7ttp z1y7z#lsIG#ryZ$c=%)FlrJK;oByQXwj)f;5aabT}TCHP)EgE0-7_oS`R$35>F(`3y zj#V1tZzohTf~xlmSa4&T?Af!&xTln%`__}-V9lt|Asl}KIf;!e4x#Hl0*qkIAbf^wo3+?Zb97Y>2ncXxkN!hpbXyC(Kj)d>^XJczkV#5PqL2m(oJgb} zfDGgXZr~vy9d($C%LAV3Ry4Bh!w<5@*5bpWgb9jeVeSBh&Ihq15;gNTo|&BdBo!!h z`SNA@ZQDYs0s-UbnVCJX$6-ve=8|kI$#D56!6jaUI5SkrVth;*62wEMz6YrtgQm10 zO(98q?g1O58pqetCfop$ZEYS|WV07OBzw}6Uyjbkbf z<3OwOK|6lH+n7?juc`S2)-lQnN*Z));u?v!sNcG^2Oo;)_4uhvUmFszm7unP<%Y!A z+hdmP+@rsqrRf`40wVtnmb~%GP#r{(b~7oEM)x7gtZ7eaMU*{8!p0|7R!--^d||eo z+=`d-<2TmK<4Tsd!RFfn3gF`~c@$hd(D;$R!k%CYAf5Rv9VyB zCxq>~z*Z2|f#*YD7~crK<#I4~3$a5`;lLIySy@^62)_eb;iUMxmJf$MSQI+>Tbu>fuz>9!o&Cg9-ZuPy;&&5X z-G^;J_8>Hzb-qt}|NMC!5D?eQHgj`i;X7mvyA&)wkvuDeF6DuVwr3ve9s zRtI4tqxz!K&40>bExN;k?WTVmItVi0LMw}=h<{y2rVZ7`rn2QAl&)8=Ua_@o4mROA zerWh-^6BFf?AQ;~lvf$*c$5F0N;|_Uyi&nrpO^Jtw}H5VLhXOu2CfURLd0=MK}@k*;;n86rK7G$ADwyx_PG^iTn!xl|ubnn&Tl?{)0i52+z&?&H;3XY7IbU z%BnYJKBK<_AP-mtLp=p(BOkam|G|MNKpG9!G^wd4Y>l9yVjGiSHiA+Z&^0cv!+T!% z>iv#hq&eP%ZU$*RGX6lunsD<&;v)c_t7zOb>o;%ihLNeQpJl(YoRN`%3RQ+Y-eel0 zERLw)6lAGK$H$K*#$qa*LSptFOoGT=V8^?X0sDRXRP=?(+&iS^+bMcCedcXP+b@1G zA92S#D+q8X5ECVPoXRN&`Le!_$UF`!C9VF>SLA0_nC-Wmau}pda&ZXhd>V3q-6b(& zF!^_omJmKIGu|<*#B==+sQliwij}+}!%+k)3_B zajyHZkWH>7GhJV@<9w2Bghosyb9zS4_m(0a;H_K^F7Op=!71lV-}yr`#W)Zp5DQv} zu?3&UFh6lPqa3ARTKx--jgQN`C!7gzxZ|CaPzSzO_w-5Q_6z??+oQi?#7YN76m=1S zDg^g5!&;IGYysIJA|NeZ0x5<8OGY8cx$@I>NU5vZdwO)}V=w`=h*=0S3X%e&0*ZER zoT_s0(ggBP+z8SW>O?}Y7y-Br0E+o1`OE=JD=VJIgY`VU5#ixtxC}&$TP(vK_6anu zbq<*OlaZDtxeeHez5eE{nwVjh-toCu_cQEfpf3$g&5Q7lEug~uL>l2vNoC4CS-6Y0 z6EtWDQG#~|WG5gOivZDGXynpnwRTv&<+*ZukqYVWIcHY?ncsQ8cLF|F19Y{88OBMp{mBcEx)zoBxym~Bk2>DCl>S;itOOnWxr-Ag~7iLUM@!Y2ht z#~H7Q*COdK0B!^Dk{<7>tX$89RUeB}z#3v2Q_i(PRd2z&%@!|HCj@&txe;6KL5 zR6HJTz79_s!B%h?PsU+9p9s__3LGC2q=TURAI=gvI?|_~s|G*{dxxC=vwOIE?j%N19d zISQ|n@j}G>Q4^~`c#*96k+(b*Z<2mSY3er2Li!B;94UsW8`|-nvG%$B$=U%fbw62jyFT@wqPso;x2!-H9A%Zns zY71ufNP4scMl-Um($dlwl$1X5w1FKWs2NtPry6h2ha^HEXN``(bg0MbS-EwueXimoN4@Oi2=J z0(j-AgAmK1rly7&kJYgXKT-T|VMAdG=Lj2HL_sQ+jR6`kE{PzYnSzBtX~*pATJ6lv zQ^U}oF;i>so22SzVQvQZJsm($O>8JS!`1<`!0SsXN=;PrqgAg_w$OfNk+1eSZ+e7i zkr?Sgfg+?8LXZOn?Lec+Dg=C*!#!$O# z&+APNNEhHC$uEnM`5h!S!N`)3)Y8serz(BiuF(uIoq8JR@|k9!wbwMg?AVkOEY6QB zbAc;2h1L%%?(0Jy55&+b!|+|mx)|63M0G+jwn0b$Bk9EHnzRyx+(Eb=P85>X<%GEj zugpo2nGVE~kk)9&iyk%2+rSc_;9fcIk-IAJbVx%$BpQ;W z3Z8@&M9M;wWu22^ppAQ?u- zfSwkVGBVx^UxetY%)(qW%(tR-)3ZS-tHOlj= zJtzNh6TO5{UPKRKq?wVY6_{x@g}w6{*`=HJX^#P#*MB8)edYPoLiLQt0r={#>OLy*DO# z#MqpJt5k+wg2pJ*+(+l#A@p{ z^3j50ieqbxDKEklC}7$@u+7m;HDSE2ohgIz%;bQKd1ag`|FbkC=`SJK3W!Q1IOzP~ zbYw6Ux(yi}wVj{TZ_t6NSj@g#4$>{~elYeT8uHP$UnKp|ZIDWGL}s{BqB-6!J}I{W zY1HAhECJZ+U~~-)4Si;Otb^iNLHa1Yh?&Ajy#v|gTfGW~&|;cREaNe}L2v|O0BFr= zJhqstK#px2J$*g`5jdsfE+OibPAn+?PpD0~1UM9~dpHZl^3K%d#N7owFD{ zK<2f*;~|7Dy?UHpih;5Z7%MV4c@ppd`;>D6+j=3tY1c?|rtIHIJO&c(LP3Z0;xVqR z3ip?1*2uf^L}Vl8Cty+5#;ZR_G3Ii^Smb!l0Pgv^ooBugL4Q(wxiIQXa3B@y(;h}*40j->kE&vO%uBx(>N$@wi?!ius|k4fc9t= zx=cPXV-Tc=a7aeWyVEKnq?jQvm*HQS>jR189_o~ZyUDC_a;w|u)~w&KfrXvD@5vAv z0PbI4&hV3rz~GHL;spt%+L$YP>EqL|s>#IIxE<`CPGt*J=+gG|8#L%vxIl+wf)=6ps$dEd*cDs0m2coYl{fY6T+LsiY8E;n~296y`%we`E%6 zw7W=uG0!BG4!IQovJ&92puUovk@(Qr!j7exHm(X$ki9nB8ULGqcZmpOzG55(#?cN) zRhTTzL3IKhSBMnOQBxnjJq~?E+<&;Q?;3nIp8<%BWQZ)g92zVv+DVwI%~m`-Jm+v( z3GOGMrg#X=f7kFKmxy4Zoy@u5<{6BkYG)eKLi6ID_gR1secS5lm$#}*UCb-_&CS`> z-RKEwT8+>-{x#e@!{`=Xy3F2NYKt^A7{e&JUG2l}efuPE!yZ6sFF-8iFe~drlnx-I z2pe|f3HDCj(b6K<=pkM}PBbbw4zpOwO0}%iLu3v~!U{nOayJ$-N!muw{=IhC11n|t zwJbdVttIU;WoD>pH?R@mwYVl^a}O3l+|nOozZmHpy_U*%?i^HqADLcwNxnq#$KYr# zc!BmjgwKa2CfI#X!BENI>a!`NOwpy}TG1F^Bm0g11wH_=2zrn(@jFmY(Z0y1gRL@q zt?8g6eHf49!aWTsqY%fL>AQaLvb906v9**&~M!JA!fG(aCCAo;sDxbEyp`KRjgIzrjU9wxH#R zRob|8lQ0zY4$3XW+jh9cbE)V0LFO=7xR1FB6u~1WPQ;ZOHX?Kh$b^8?kM{Q^5HF-L zsPb%Vo)}8{`Y&^GY+W7`H37gF8Fexbhj9RMwFxe4!Tk+5b*~Wo;0Aui#D*RM)5NdF zN6@Z4;z++!v-;!=Xblp;Rn$-q8Q4uC4<+ z5*Ofj1OH)$LVWX#79vm*0Rp%0@gs5uj!Q$Ayq2lMV?6_X51n+7G-4 z@C~IpPU1f9HG(gPk?u;32EgC9K0YoA(P2QXh@W2d@qY8>304pRYE2Rq$g$cF;P)bmy=Uq{?Pi*;W_}^AxCaHg7NcJg8@h4@6gjsw8c3^s66bWjaVr5@#GOE)f@OK`P(Wm<+|fF~P3e#w-wq9(XCft_$&R@LnYK6 zmb~|+k2iUDDF_aEM|>+#4Xu#7zaZc8uQ%gt%H5Z~^0rICZo#DabHvj4_cijwaloYc zfBqia_>g1aBs~Lz3v>erW{6Kt;O-U7OQ=+7yDX5qB%$Qv5-V{WIox)22FGrd2JWN) z@zB!I5e0K0H5Nkl8P)Oa(b-)mQAUxRBbouAxJ01PekNlZCzkW3@eVAPp5u?!VXmS8 zh{OZh2AWZHf6^YFyX%q0KBFoc%cE7a9$TOo85(k{3`*geAS3~xu0F$NXvK&&I4!Zi z^*@Q8H|l2gz>seh$OBq#A+C(P0m1{7__>MugGa_@W<{7@Y@CliM&2CT{UMkh*em56 zf+x^+&ZzDp>TOg+z~_D*eK%|=oXt4|K8VYU@=VAysaU|UxT^CTST+s00G|6`{HicYDW>H-KmD zHPx^h^SsY-5Acb}6#|egMlp=Yjo3CQ@2U&vn1~#b@F{5RcodNGbi-~HYf54eZA$BuvQ=Tv>%;DR)V~2*;xV`-! zd@nic&BYiPyNnGK+$T|kf?^3n|JI>1Ed#Cd!;1T-V%2g!g4v$}KthGR4h0)m^=c#U zguvVcKFcV684ov~N5TA@9iU~>ya|0Ts_1ii^w}W@zDuhTx}> z*jwu_c@;-f9SHq~_Z1{{P?uw|%l#oCm|zzI)Dx^9B!N+eW1xd%@EK|Uk8o@fMgP9* znpW@L?*ZMG85JK}dKRFWWGi^$W4e@UCar8^_lQKZGrW(|tWk|dRGPFlkx#b)FU1Ie0gPLWl8wi zJi=r*%)@%l`~CmL5k^ELF|scyA$wF) z)*>pUEG;BViL^+iWrV0OLt4xfN>Zt8(IQcZvL%U12{Dz*R?+4>-rV(OJ>Jds7{7e?I zw+A&1Ah+SPDM~dtIXUO);w1Fc3?I)ygAb@>(zr6VD%aCi-U4pGM5A>6BsorKdKenl zLbNi4i=t1TX|!fJ1{FHq`7nZdK%|=$G4;e$|_usZI_$;vwiYESmWmo z2DSpkqq)rm>)Z|R1uiV&r+GcQpjWYR$?uj{5XLydJi3!^bif!)>rvmRT|&rCan8w> zKUPrj-5ssQZ6b6pzLk8oJ<4Pdt^>n|Y`9-mCZ?{JU`A^q@ON2ZTdar4W?>=7D{+oel#A+t5=qtS#*}}>P2Pc z4Fqm(aFmCuxK3ch&XYXEliq>&5U3}&6$DBIu5dgF_=RKx<}Yxt8Ezj=oGYDle-@Dg zTVq{|P+YydI;KJsKZzv5y;@1IV&BhnF-mOb7leIYkt z0+GrK($1)ckeEob;~&k;(^LF z-K%vvhqzzlmXE|Xa46<*5+DC_e0SlvR-Cnfri9m?>zB{nokcza1aNk7@ey%lR8$z= z))>CC*Ocrr*=l?oVxs|uX5OG~J$s(yNm3=0@`Tq2Q7XkpfKo7ykRq~6c2+mIS1J{X zm}?Go@UYxLX+oX~q5-F^u&DgZYGL&UeY3W+3$REU4F*8oq!@6qJ-N|ONIw>_3Md>) zGd$$cd|SU&;Dlo-n=h8Ox~|0lQbtQ zt7G`RZC}4YupS~Jg#I=8Q`4!q^m`wg`$W!ie66bJzbyU+QoBF3l&5931f_4dzXA{#leW#<0<$YWRI)hjvVAJSM2YEwFE?-{#h{dzy#IYgwP z7~hRw?})1I9^0Yo>vWPS%J1L3yGq8wvS)fE`tON}S+5^5)Oc|giaTl+G@>y3OfmQG zz)49~uU(q-aYy8g$(zcrU{l%3H_zGk>qOVp#=JPpxQEr3Bo$F{&1$CrhM3^B+;2ed-VCysm|LckaBx$~wh-x6bZ_IWE6W`nN&v z?}tAA{N5n0`Ip~YN|F*}J{!A+C%b6vDPG8X92D1{TPptAGJoYWm&cFWhS-i5-_13N zDRhLER{5#g*L;Q)BP!KjKErd(eO_o!MkW2BDS~jIz(4*6C+>e9&+_+=tPxyM#$b6w zwc-SKNF=^~LH|Fn$pU*$NtUnO<3fw5@l-vX#{zzudgRHHk`jak zwp=TB5pqz|S5wPHfGIyhs=aVwq7BjxOI{SNepmpC4C0drBC(-s=?`mTBdEP|puu8U z3qN-jj5Bz=rN!~uaCQeVv<(H~;#4WX@Jt_ao$RDl#~XI_S~AL9U;f>h2(RX!C7fu7 zf96%(6hR`D1rHzU^=P7oiB6E3PK?qTngbE|$a9cG;RctD;% zXV{kru9(j7yIjWeRHHu~8A9~yTJ7&;xUUEtYoA?2ho;uw(@eNs#BLF2fWxVQID`9) zT4W`5%DB5POR0rm$tPn5Qu7Nkh=q4Z=II4757y?uOzK!t4M-#rPC8iNT)%7(u(7L_ z{48ia_$(}FmjTyvKLHwaI78+sp&y17jdeYm;1>21@YJ0rX|b)MbA)&M7rnxWZCR1~+31U6YXkSo|Spz;x@U#!*;NIfWcZmqTOgW%MX;r543 z6M1<-U(l7lg2ps(UI$q45djqXH6bIZtUSB@izCct=c{}uLTkXWArVd<%u_ZQw2oqF zlGy143WDlaLPtJ8#T5lE$xlMU0m%`GwUP!rBr8jYGx$2@^E;#{MqgMeh*4in!6^_B zK~6eREL{c1EBn-{mnxWHxC|GWZMab>d27~#NH|FY$0lT4&tF}ou8o1|3GxU zNHOM&cEhME5_X92$?tT@iKFN;Eu?UuV&Q)ATT>Ct?Vt2g(IuRxyATwZ5GJ~_*|_=6 zGd52sbRn8%J-~yww%6X4ExxpQ2?!yR#E>CFe(Kgp%A#)Slay`m*T6Tig@J7q{7#k#nnEz$LRb?6JMhll`YhaHf>aBzSy+_$uSq`qQevy+l`QHn^ zd*==Vy%b}y$>Y1XZuvyY06T7~c>P*zp#p4Cap_N-p|E@$4i#R3F=>kLj&1SeY62*S ztzuh8^7U3Gr=avJkiW)N4$KJYj*Wxl<0O6bbl zu2$~q)zNyV$NQ8?S7|{H7jfrtL`M}=34aN8tXy+tDp3yYA&3H~Q3sINwXxTFB5?eh z_UsU-#Ura!sC7dF0|_g|!mov<$Ha{0FQ%AT#1!OTv|lM9(Eh$(@g^?a%0SEbLUA#j zMV2IlPBshTw#|A*gFQE(pHdAsTQF_Aq<>&x$f)7NJ7riLAXO9jp4W4iZbNro?f;Ew z7?Tzs_4#7v8jw|F6TShbh1ETG?n3`fcH)xzk5p&xR~wXdF66FtApHUX2Qfr9*vx`j zh+sHv+T3fFedL4;M>%^@-_Bn^SqOC-b2fwX9ZE#o&6{l&l?}`cd9`n-;~>{v;9!v$ zs=)rA`c=;_eeZ4W`jd|~Otw*V`g$3|r4chXm}P#Iv*=}Up-mw3!07*3Ulvz-mRnXt zN;{6atKoV|WWIBm`%V=hz#yIprFz|d4G$Mdv9#<$qLtgl6rqF2qGPs`s+ISabfA+T z)AE43fXmnSY&+8(w~nw5K7E>+RWf$xwsR(Vvllg$#oyJqG#RIgnoG4Y&9D%VG0QOF zXIyXQ(K!}Oz9=6@G(mB;vbD9HaIfuH_qZENeor(zs}uJ6#fvo)-Z~{cRNY$qqa<*sP8(f)~KCCZ-Wr|)vAo=x1(l?@pcnjF=YEf$=xm^~*k?oh^* zDteBQ|4Aur%9+Vvk4(YB$R%`L94XKzN7b~34eO}rpq;G3^{6s20jxv<=M{Th0pa^3 z#&@ab%t^Ut^qGfpf7Bu`P<7(?kt3tCD!jM~3EJHF?rH(UBqAi0kK;Qc2~2ossda`x z&+))bg{PG zO)gc-lXIFk-w~viGo9nfhCCSqXLBo#m+kMabul>?uCpg+W%T`0_#Pn=5U47LpycBB2GBq*sp}63^PyA`FvPW6o(B)En=wj^75jCV13{QhhG}YDvngk z!iZ{X|8mVz3h@JhUISI8k?SfLBt1R<4++1?asJ7Gc^zBTU1;=B1dxUph^O*B(duKe zwVTS$GQZsjbkv@rrbeXck5tHgOizxN_#EbkPTvxFt`vp7xLj!Cm(`heA!T4=Z1(UQ zsO~rQdI7OU)W5hJ7so8kx^kg=98jA$QTgokyp_z(3U93c?s;Qha!d-EmkW8|_6>5D z(@*}X96+@76PQ~Np(ub8BJvHuN5%{|Ag{BhMWJ?67`lXsEN0|6iQEq4k7DSS%H!DD z4+0{nJjf5R5(sQtgl1G;^!)Hj*U`x-b=&)41O}|;Mv=geq9wTgf2y{o1yfGMPKwG5 zhD#81hD#nM2c4z#?l>;BK!6C2rMWQ$Fj|(c4T3rI)_p>;m2os(h30H(N>R%<^?IU#J-Z#7b@X9gkcW>lBmP1vN^VW_=#ST z#s{8_pV&=o4?rZ1CT%wnS4ULmcQx$(y&cyG*7|iE2<7&Fo{`L?Umd!0nbr2t zfw4jzE|s}=EXcr(Q<=xrSv!Qn(@L>3`f9@kio-LReK6CKlcn; zXwTul;6JEx7MpIk2YAC#@h#ca_zS2&=cwK3fWX**jmp@32!goo%pLCX!@Y!% z00QeT%(0G6*6fB$xJrpXRlprg;Wj;44;TqY{}6~81hf6>R-}rH=o+c{^uYPFSh8BP z?CtDUR;O`)cUvP~&ZI(E!QG%@LSXjnn-=na@2sZxXyZk@8OkYWo2L@aFy$5 zw%>ru_gP>_9Y3%tp4U9@@NSQ}39C|NeK74X%Zs=LR0m@JA7^Sfk;U&=EHUu(QiSpb z2E7D!OAv1l6eDD|u?lcBYCt|Tk&AiyJXQutdwWx+6JQziqI5C!aWejbuZWJPgep>$ zoSmJ+8kVq11@7=Y=FkDFH{%npR2W%W&i*=-1IIU9MssBr=34)B8+hdY!(D6E+_0{Y z5vW*YGF#-h<3$RcSRR0V8LUYgj&-l335n~&hq8cKKMooM{T}~rYcP8z=I>qu7Upl5 zngE5mS z)v$~mA4JD=m6jecVL~qnZ#nZDXVWOIJ!Z@weSo4nuy|?-nxh5e)@ug(k1y?4UMT|F zIp;cvurJEfIKw>nM>=Z5x;lWt@1XXyW!4n)D89^%E`@W!*MZ?``1I+aOb1FGmgI*y z^Qe$oYjB-ZUi2m<#b!h2V=!D|g_ppnS&}iP`2oRHL$KX!EV~>AtLQtGJTK@-;pPSI zV;DYhN7>Fyid~pUh3E6?hz41Yk4S>*dJ+kET#XDWn-$&4X)h-#*x$+EaKrQ>qB2PC z@QsOyQM*r*h@yloMRvX3Hu)2A#0kNum=B;yxU0mVIux939G`DA9}}ne?ID4EWM$1* z4T4vF9gVyQXThp~`B(wz%{- ziu>mserFC#GOdX3KDNC-m#{vjC`+OV`DMs|lNNzLo#0lcrxL-nBGi@hXW?nS9565H z8Xgc16x3eJUkv**1L2}L?~oqSh(*u?}#cGsbC2Mx1`L@-n+*-ES< z>O2Yq`-@1wSs%1=P<<0EMnTFJYj`g=mOGNEB*GDdWLw@?hC)V@bmhtw>M{BZ;6=t!oM*egV>8mX>601jNQfrjF+O^`!9ZbS-Z z3{Q@vM6pL1X(|ohNF}A%M=s0{f!v97Ei~35(2-V1C=Pja<}{noIY~umTNdCzxMtc> zc=FNhRn~Oz*JyaO6i`LUQp;dD;sJE3@+jpf`zf9+WJ;A*FzE}Wn-5qvv)t^j1kbI! zq$-#e=S;!|PX)@>fno6iSz>~FQtYye?s=`WhS5eaH{1u>hSQh5N?+yAmAy}-E>Qn{ zS1Z(gS+T>%$H!>AGectt!YSDT7`4MPK_0BM`4!>~Sq5*|aJtp&YJ7G#*`&k=g|twF z-HyFHPN(bYjq@_(jJSqshm;F;cI=36`ssi6f7b?;8%*iPlLfhYP!(vp3~?LMd%6tc zzld&G)UAw`eFxEeo+_4Ma-IV)OIeo z1K&Pxv*|Yv)NCG=+uNkBvRD>IUmY_Ja)y(B>)7|166abtX1=6sWH3m25*?w{8RH5wS;$-G|QzDuX;(7^dw z=3R#xFZlM~Q;$o>eVmTo?G-U4S;*E%+oE3(26iaGQ&kVIYtT-J{`_a;s+@EvH{T1m zjB0*FRljuh{-uS#PHLKuXZ06I!Aa}xSaJ0UR}T19^2t0=&Y2J%J1ZpLWPW+iMotDd zL19zKXrT;iT`s@N>JIr4Q{3XY>QV4Z=gge8l-pq~!$njV4JEQOc^@QuAe6RgDnhEh zbcu!uX!!tOCu@E%VTjAi)_y z|A98(9dNAhL7IB>fF-~OgK+i3m6MHm8A7(nh`TV{)O^VW;^0Js#zl4=z#`seR#RE6 zs;26Vdb{jHmy;_}N|Q$IFKDxE+2YY3;hemuzPxt+pfQjnCXd@Gw1n~OH*EG`?*Sc# zHO@l`AD$2?(%so!xW~E9w5CG=R!q(GGihxbf3tPJoON;=!S8~U1t*n={q_Qd!nv35 zxR{nnDkA?`MA%fFyY9)y(<5=8+*OH0R!J9oa;n^i-eTnuoVXeTpx~*gyEh`|25_+; z$xI=X`UgS~~ z`+9X)+@}+pE^XU>D=hurT}Nn;(9JdDifvL&S-F=<(>IPQ_u|oz5I+J%@~eA)Z8I;X zU_#le@Dpr3jL7bicZO|mo1R| zt%NmgH2Du|m>#Vio6Dv)Z@z-(_8&?Zy%N@iHIFXdI25yN7cZvk%U?62{xf?V{_oLQ z|BSE3sg#1zgmM$6=5Z751|2N6I)YC9dz$hOKJ;dX%}$=gsm z0bDe}>PgI_6uMc)9Il4H8&_4WqsOH7j&Tj+VE90_j>_K<%3c{YjbX!d+-fnqP|TjN zC|#JRa}O@W!Z#jr{`1w!x&$N?ZFoJ;`YR(rd06Owb|;U~QOHE;a#72OHB#V5@6j_j z0RRaZny(8SA!}F3pY7^Hr&K{+2Nxz-7C@QI5Y0rxr2PSF2LGS*quc3+S9Ff};opn==mm0L5ISph`q|6LwQ}Qh7YV+7ng+ ze5Y=Ke~Du{8(392^%A2;b^lt;CQzW4H8pvR(D?BKug#(q@lt1aG@f>R?Ujk)71#R= z$5&mc=VBycoW|851hxozF>-el){O|a*9roKgEf+UE8(&hy(OdO1fqCRD(T_z3Hkz5 zhVErxX(7$ASb;4atgO$|$5)X+1w z2q?!Ap{&5KqU8Fv7~}?P4pi$vrfg`Vml;iEViBQ4OcE>{Vspko&=9d+8h;r1lINT!ti8iq>))l|f)P6WftGrcm@NQgc3wY;qD zhOznAEkAm{Ut+NMV262?D^}bKFnjFW8g{-)cIx`y*00lF@>}7GyFVu+tXL+Wyv#gk zrMKzE(3KZ#qpH?eTyP#RZS{tq62ept`ld`=5Z^iHx#Ugjrgzfbt%m!{oizPi@8`(< z;H6bxZ+P^L)0H<4{Ra&ysr~PM~@%;vir2ZrE@hpb{~i4%8_#hWWM_q%k4>OMpg{A0_u%Y^GSaWmprw6lTl=}VX3cn{DOzTts+eHry<99%k|wZiw1M&Sf8NRx9_z98ZHCnO}x@<`(?Z4uI$yFeYK}d znWFEu*M?4E1wn_xE-RkqSW&2N3OP&O+6)Ue<7q@|}9l8rcXp04g* zY`+Q~Ex&Zn&C4_4f)jsi^~xl@Ii3zkcl{4izRgrQ6BCnYo(@l>3UT+Lx)cdp!&de}nRKX3!6x;WQ7yameM3`A?t5HaEMs@s=DsfrK(3 z%TtLiM=ZB3eDugU-$r4d$I2aC_SH8BZVqho+Pd{38t7Q4WTgWo`T56-i&yaE;*K4& zdbn`<0FQ&)fQkL*MGa6;$Y*XJ@3B>~;KBu}UtZ>w4w6v0ZCb99342mH`DkAsB#|Cg zC$Z|arHjOO&rC`GIi(%04tdd2BGvo<<69zHr3<%3$HXX4o5m-)TyIHJqt_^2`L=Cl z#|<`Q$s{d)m1g1S(z76;yVX{Q0Zj<7Ns=A?>Io+Gv(`;$|Lo1jr>gr^J>K`m%%Z&8 z-QbyZYwzCjnIWFeuRK4nN?+lMMdd~6W8TO&UJ?nDJ&_8huBC{ z9BpII?p(T1V+)Ij=9ZSi2M>-3YPG?vzgW#|Vrr@kwntKATx@JUUhX&Ur-N?X(^%}{ z;^K}3Y|ZMB6U6rEKBUPXw0LTMa*;*6zyA-1LqgIOM@HMDRupSGTH4gTT2nx_U-6tC zA}Toj(~#%x(r?hCD-tWThSc-MraVeI=Jmu6_SigiU+AwLW@3 z1~z$Sm^H^mb#?Vau+X}-ZFzG`lO7;qjADJ6?nCm?@DA3#9X#j-vBa>!TXn5N&R#?b zjL}40W~S;zr#Fk)p>Dw&;Z6r1enbH<4@Dr!wwu`%8O!wm~&DoR= z#yE~$nj~me*VgXy)OT_^Z)<0_{zBa%bK83`Vsm+QhrALqGTIInUCwAv_aqF>c*Tmi z1tTKU($w!KrrvkH_x_SNp&u0$#njbpQo2`SbMoZx^?OH07_57Jqa};;=I5j9KQz}@ zks_4;4yBGqU8=JBy+yCxg&dS3c<`WXLt|rHeEh;#r3{h8Mhji9pA!u&@yCXaFl_G-8~_k^P!w|MKIPS0BHu$z+4h1>f7M%T}#A zjh|gt>&+V1Pl)@g(`piz4(auvlgzARgS|dqyItqmT1$j$G`L^&5xd0Setf3-l7nS& z%IrE^gP#Msq99GgQfy&wZ_is&fK;+iTG>}+Rn^Bx>-beczx{R`h`h7!wG;Oy^idkr zMEjSnxLS|Bb_SCN6!J9tw`3qjisOxHJo+FSXut#l?ctM6ujrdh*RPM!Z2mLqNl{9v z$tnj-+^LG%2aS!4BDtb7kiJw`RprydB&64+Eo6_;;uo6jTiJ@@!)A)n8EB1kk6NqY z(mr*_g?4D`II}Z9@kG-qgI6AGuW!QO6f(jSAiSAFt>N*?%_Cjf!t|q3#G2=kyrwToKn71zp`&?jM@3y64uhpuJR#rc8;yng+h^91);&Jd3j6u3$ z59{ihnuc4$4{V@=uCA{y!s%4Mc0bVG^7o0qU)NYnim?0JvpJtYoU73hfL%n;(?tvK zpK0D59a0G%Af_={zC0EY#0Gv3V|)Rx;kEnZ9zA>7Zrk>xq5nP7Sq+GHa@Lr)vCGlw zJsy9EU=H5kC7|0&O-v5s>U{L8dymSv-$VYjoyxvtq%4fujna1Bv3M-a!rEm5QduwK)sAci3V#>No z`s~cE*r}M8_cDi?o2ofKF?INHc6Mf!6}iWShtxFXw|n1?Co}lkZR`9$#&rnYAMf;Tm@IV?5H8}*q^D;OrCMA*s1YMS^X7sP2OpT4 zj%@z?Uav6qMa8Fci_{b^o~WLk73Sd5)8cgRA9hWiJo#1CG|xH1dei^tr+)n4p0RDD z$Gxh@+1>{VruAI-YROMa3Xfja?2~wJsEL>ROrOs)_RW+GnP}u%@`Gg0!2i;b_}_D| l{_mswr+bqB(p%RiGrGgQoE+)(8zlUrJ9qJ%L>;Rg{|YED<8=T4 literal 0 HcmV?d00001 diff --git a/tdesign-component/example/test/goldens/stepper_page_light.png b/tdesign-component/example/test/goldens/stepper_page_light.png new file mode 100644 index 0000000000000000000000000000000000000000..8cf6bbd4d3144174db2ce44e799545fa0fdbb4b2 GIT binary patch literal 36866 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

PJW$Lg~7*V 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 D_Cs9C literal 0 HcmV?d00001 diff --git a/tdesign-component/example/test/stepper_demo_golden_test.dart b/tdesign-component/example/test/stepper_demo_golden_test.dart new file mode 100644 index 000000000..635c56c0b --- /dev/null +++ b/tdesign-component/example/test/stepper_demo_golden_test.dart @@ -0,0 +1,4 @@ +import 'demo_page_test_utils.dart'; +import 'stepper_demo_test_spec.dart'; + +void main() => registerDemoGoldenTests(stepperDemoPageTestSpec); diff --git a/tdesign-component/example/test/stepper_demo_test.dart b/tdesign-component/example/test/stepper_demo_test.dart new file mode 100644 index 000000000..844e7455c --- /dev/null +++ b/tdesign-component/example/test/stepper_demo_test.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:tdesign_flutter/tdesign_flutter.dart'; + +import 'demo_page_test_utils.dart'; +import 'stepper_demo_test_spec.dart'; + +void main() { + registerDemoStructureTests(stepperDemoPageTestSpec); + + testWidgets('Stepper Demo follows official scenario order', (tester) async { + await pumpFullDemoPage(tester, stepperDemoPageTestSpec, ThemeMode.light); + final keys = ['base', 'minimum', 'disabled', 'variants', 'sizes']; + final tops = keys + .map((id) => tester.getTopLeft(find.byKey(ValueKey('stepper-$id'))).dy) + .toList(); + expect(tops, orderedEquals([...tops]..sort())); + await disposeDemoPage(tester); + }, tags: 'demo'); + + testWidgets('bounds and disabled state use the public contract', ( + tester, + ) async { + await pumpFullDemoPage(tester, stepperDemoPageTestSpec, ThemeMode.light); + final minimum = tester.widget( + find.byKey(const ValueKey('stepper-minimum')), + ); + final maximum = tester.widget( + find.byKey(const ValueKey('stepper-maximum')), + ); + final disabled = tester.widget( + find.byKey(const ValueKey('stepper-disabled')), + ); + expect(minimum.value, minimum.min); + expect(maximum.value, maximum.max); + expect(disabled.onChanged, isNull); + await disposeDemoPage(tester); + }, tags: 'demo'); + + testWidgets('Stepper Demo values remain controlled', (tester) async { + await pumpFullDemoPage(tester, stepperDemoPageTestSpec, ThemeMode.light); + final stepper = find.byKey(const ValueKey('stepper-base')); + expect(tester.widget(stepper).value, 3); + await tester.tap( + find.descendant(of: stepper, matching: find.bySemanticsLabel('增加')), + ); + await tester.pump(); + expect(tester.widget(stepper).value, 4); + await disposeDemoPage(tester); + }, tags: 'demo'); +} diff --git a/tdesign-component/example/test/stepper_demo_test_spec.dart b/tdesign-component/example/test/stepper_demo_test_spec.dart new file mode 100644 index 000000000..e73934803 --- /dev/null +++ b/tdesign-component/example/test/stepper_demo_test_spec.dart @@ -0,0 +1,23 @@ +import 'package:tdesign_flutter_example/page/t_stepper_page.dart'; + +import 'demo_page_test_utils.dart'; + +const stepperDemoPageTestSpec = DemoPageTestSpec( + name: 'stepper', + title: 'Stepper 步进器', + page: TStepperPage(), + expectedTexts: [ + '用于数量的增减。', + '01 组件类型', + '基础步进器', + '02 组件状态', + '最大最小状态', + '禁用状态', + '03 组件样式', + '步进器样式', + '步进器尺寸', + ], + useAlignmentCjkFont: true, + supplementalCjkFontFamily: 'TDesign Stepper Golden CJK', + supplementalCjkFontPath: 'test/fonts/StepperGoldenCJK-Regular.otf', +); diff --git a/tdesign-component/tool/check_component_coverage.dart b/tdesign-component/tool/check_component_coverage.dart index abe831590..d2a1c7afd 100644 --- a/tdesign-component/tool/check_component_coverage.dart +++ b/tdesign-component/tool/check_component_coverage.dart @@ -25,6 +25,7 @@ const componentTargets = >{ 'search': ['lib/src/components/search/'], 'swipe_cell': ['lib/src/components/swipe_cell/'], 'switch': ['lib/src/components/switch/'], + 'stepper': ['lib/src/components/stepper/'], 'text': ['lib/src/components/text/'], 'textarea': ['lib/src/components/textarea/'], 'toast': ['lib/src/components/toast/'], diff --git a/tdesign-component/tool/run_component_regression.dart b/tdesign-component/tool/run_component_regression.dart index 9ff6e0d28..714378194 100644 --- a/tdesign-component/tool/run_component_regression.dart +++ b/tdesign-component/tool/run_component_regression.dart @@ -79,6 +79,9 @@ const componentTestSuites = [ 'test/components/switch/t_switch_test.dart', 'test/components/switch/t_cupertino_switch_test.dart', ]), + ComponentTestSuite('stepper', [ + 'test/components/stepper/t_stepper_test.dart', + ]), ComponentTestSuite('upload', ['test/components/upload/t_upload_test.dart']), ComponentTestSuite('form', ['test/components/form/t_form_test.dart']), ComponentTestSuite('input', [ diff --git a/tdesign-component/tool/run_visual_regression.dart b/tdesign-component/tool/run_visual_regression.dart index 34dc23af6..f483ef168 100644 --- a/tdesign-component/tool/run_visual_regression.dart +++ b/tdesign-component/tool/run_visual_regression.dart @@ -126,6 +126,12 @@ const visualTestSuites = [ workingDirectory: 'example', testFiles: ['test/switch_demo_test.dart'], ), + VisualTestSuite( + 'stepper', + 'Stepper Demo', + workingDirectory: 'example', + testFiles: ['test/stepper_demo_golden_test.dart'], + ), VisualTestSuite( 'textarea', 'Textarea Demo', From 36620b81e69d8ae3ba6a06c3fb486724bb9d02c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=BF=20Cai?= Date: Wed, 9 Sep 2026 01:52:10 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix(TStepper):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=8F=97=E6=8E=A7=E4=BA=A4=E4=BA=92=E4=B8=8E=E4=B8=BB=E9=A2=98?= =?UTF-8?q?=E6=8F=92=E5=80=BC=E5=B9=B6=E5=AF=B9=E9=BD=90=E5=85=AC=E5=BC=80?= =?UTF-8?q?=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cnb/.reusable-stages.yml | 2 +- .github/workflows/test-build.yml | 2 +- .../028-stepper-demo-alignment/acceptance.md | 44 ++- specs/028-stepper-demo-alignment/plan.md | 10 +- specs/028-stepper-demo-alignment/spec.md | 11 +- specs/028-stepper-demo-alignment/tasks.md | 13 +- .../example/assets/api/stepper_api.md | 2 +- .../code/stepper.StepperBaseExample.txt | 29 ++ .../code/stepper.StepperBoundsExample.txt | 38 ++ .../code/stepper.StepperDisabledExample.txt | 21 ++ .../code/stepper.StepperSizesExample.txt | 46 +++ .../code/stepper.StepperVariantsExample.txt | 43 +++ .../assets/code/stepper._buildBase.txt | 8 - .../assets/code/stepper._buildBounds.txt | 22 -- .../assets/code/stepper._buildDisabled.txt | 7 - .../assets/code/stepper._buildSizes.txt | 21 -- .../assets/code/stepper._buildVariants.txt | 18 - .../example/lib/annotation/example_code.dart | 5 +- .../lib/page/stepper/stepper_examples.dart | 176 ++++++++++ .../example/lib/page/t_stepper_page.dart | 144 ++------ .../test/goldens/stepper_page_dark.png | Bin 37551 -> 38099 bytes .../test/goldens/stepper_page_light.png | Bin 36866 -> 37958 bytes .../example/test/stepper_demo_test.dart | 136 +++++++ .../example/test/stepper_demo_test_spec.dart | 3 + .../lib/src/components/stepper/t_stepper.dart | 98 ++++-- .../stepper/t_stepper_defaults.dart | 29 ++ .../stepper/t_stepper_theme_data.dart | 47 +-- .../t_stepper_theme_interpolation.dart | 161 +++++++++ .../stepper/goldens/t_stepper_dark.png | Bin 4468 -> 4497 bytes .../stepper/goldens/t_stepper_light.png | Bin 4667 -> 4674 bytes .../stepper/t_stepper_contract_test.dart | 331 ++++++++++++++++++ .../test/tool/generate_example_code_test.dart | 36 ++ .../tool/generate_example_code.dart | 35 +- .../tool/run_component_regression.dart | 1 + .../tool/run_visual_regression.dart | 7 +- 35 files changed, 1267 insertions(+), 279 deletions(-) create mode 100644 tdesign-component/example/assets/code/stepper.StepperBaseExample.txt create mode 100644 tdesign-component/example/assets/code/stepper.StepperBoundsExample.txt create mode 100644 tdesign-component/example/assets/code/stepper.StepperDisabledExample.txt create mode 100644 tdesign-component/example/assets/code/stepper.StepperSizesExample.txt create mode 100644 tdesign-component/example/assets/code/stepper.StepperVariantsExample.txt delete mode 100644 tdesign-component/example/assets/code/stepper._buildBase.txt delete mode 100644 tdesign-component/example/assets/code/stepper._buildBounds.txt delete mode 100644 tdesign-component/example/assets/code/stepper._buildDisabled.txt delete mode 100644 tdesign-component/example/assets/code/stepper._buildSizes.txt delete mode 100644 tdesign-component/example/assets/code/stepper._buildVariants.txt create mode 100644 tdesign-component/example/lib/page/stepper/stepper_examples.dart create mode 100644 tdesign-component/lib/src/components/stepper/t_stepper_defaults.dart create mode 100644 tdesign-component/lib/src/components/stepper/t_stepper_theme_interpolation.dart create mode 100644 tdesign-component/test/components/stepper/t_stepper_contract_test.dart diff --git a/.cnb/.reusable-stages.yml b/.cnb/.reusable-stages.yml index 7f858b95e..013bd2797 100644 --- a/.cnb/.reusable-stages.yml +++ b/.cnb/.reusable-stages.yml @@ -24,7 +24,7 @@ .regression-tool-tests: name: flutter test (regression tooling) - script: cd tdesign-component && flutter test --no-pub test/tool/check_component_coverage_test.dart test/tool/run_component_regression_test.dart test/tool/run_visual_regression_test.dart + script: cd tdesign-component && flutter test --no-pub test/tool/check_component_coverage_test.dart test/tool/run_component_regression_test.dart test/tool/run_visual_regression_test.dart test/tool/generate_example_code_test.dart # Example 页面共享功能回归,双 Flutter 版本共用;不包含 Golden。 .example-regression-tests: diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index ff99aac5d..e5a5230ba 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -81,7 +81,7 @@ jobs: - name: Test regression tooling working-directory: ./tdesign-component - run: flutter test --no-pub test/tool/check_component_coverage_test.dart test/tool/run_component_regression_test.dart test/tool/run_visual_regression_test.dart + run: flutter test --no-pub test/tool/check_component_coverage_test.dart test/tool/run_component_regression_test.dart test/tool/run_visual_regression_test.dart test/tool/generate_example_code_test.dart - name: Run example shared functional tests working-directory: ./tdesign-component/example diff --git a/specs/028-stepper-demo-alignment/acceptance.md b/specs/028-stepper-demo-alignment/acceptance.md index 9d1cc2cd8..703a3585d 100644 --- a/specs/028-stepper-demo-alignment/acceptance.md +++ b/specs/028-stepper-demo-alignment/acceptance.md @@ -1,18 +1,38 @@ # 验收记录 -- Flutter 基线:`ccace5c61383dc2c4fd5392f41222e65b54d8010` -- 小程序基线:`b60cdc8a1dce1f06dd45cb4e41eefd31c674e514` -- 公开运行页:`https://tdesign.tencent.com/miniprogram/live/m2w/program/miniprogram/#!pages/stepper/stepper.html` -- API Review:现有受控值、空 callback 禁用、枚举形态与尺寸已收敛,生产源码无需修改。 +## 2026-09-09 本地修复 -## 验证结果 +- PR 基线:[GitHub #1064](https://github.com/Tencent/tdesign-flutter/pull/1064),head `5bdc6b41fc47b9115856013ca8b9ae4159431a50`,base `ccace5c61383dc2c4fd5392f41222e65b54d8010`。 +- [Figma 展示目标](https://www.figma.com/design/mdBVCCVGERhxoZLle2eLT0?node-id=28591-40152):376 × 960,删除中间 99 示例,禁用值为 0;示例使用完整宽度的容器底色、16px 内边距,基础与禁用左对齐。 +- 小程序参考版本:`fe14543572bc7233226b2f08db6fc1424cd81ed2`。[公开运行页](https://tdesign.tencent.com/miniprogram/live/m2w/program/miniprogram/#!pages/stepper/stepper.html) 仍有 99,本次按指定设计稿处理。 +- 保留现有七个构造参数、枚举和默认值。修复草稿边界与 Theme 插值,不新增 Controller、disabled、integer 或 disableInput。 -- Flutter 3.32.0 / 3.47.0:组件测试 25 项、Demo 测试 4 项通过,严格 - `flutter analyze` 零告警。 -- 生产源码覆盖率:`258/263 = 98.10%`。 -- 固定 Linux + Flutter 3.32.0 明暗 Golden 各 1 张,更新后立即无更新复跑通过。 -- GitHub/CNB Demo 列表一致,回归/覆盖率/视觉矩阵工具自测通过。 +## 实际验证 -## 未验证项 +| 检查 | Flutter 3.32.0 / macOS | Flutter 3.47.0 / macOS | +| --- | --- | --- | +| 组件回归 | 39 项通过 | 39 项通过 | +| 完整 Demo 回归 | 7 项通过 | 7 项通过 | +| 生成器及回归工具自测 | 16 项通过 | 16 项通过 | +| 严格 flutter analyze | 0 error / 0 warning | 0 error / 0 warning | -- Android/iOS 系统字体逐像素差异不由 Linux Golden 证明。 +- 四个生产文件合计行覆盖率:`330/335 = 98.51%`,组件测试全部通过。 +- 行为覆盖:两端边界草稿、父组件接受/拒绝、非法草稿、即时按钮边界更新;主题双向插值、端点、实例尺寸、继承主题、TD token、copyWith、嵌套插值及 AnimatedTheme。 +- 实际打开五个代码面板,验证显示内容与生成资产一致;将五份生成资产原样写为独立 Dart 文件,在最小宿主编译并操作全部十个实例,1 项测试通过。 +- 示例生成器 `--check` 通过;Stepper API 文档从源码重新生成。 +- 新增组件契约测试、生成器测试和四张视觉回归的 CI 入口登记;GitHub/CNB 工具入口同步。 + +## Linux Golden + +- 环境:已有缓存镜像 `tdesign-flutter-golden-cache:3.32.0`,Linux amd64、Flutter 3.32.0、Dart 3.8.0。离线依赖使用 Git `--no-hardlinks` 适配;未修改主工作区依赖或 lockfile。 +- Demo 宽 375、DPR 1,预载中文与图标字体;完整页面高 854。先检查实际明暗图片,再更新两张 Demo 基线并精确复跑。 +- 原组件基线在同一环境已有字体绘制差异:亮色 848 像素(1.82%)、暗色 835 像素(1.80%)。使用 PR head 生产源码复跑后,实际图片与修复后的图片逐字节相同,确认本次修复未改变静态视觉。 + - 亮色 SHA-256:`755a5ee4676911e93f45280d0edb3f052c3ee7cf56840df2d0775ec541dd0dd8`。 + - 暗色 SHA-256:`0bc5e0b70c02f557cac4f7e57b3f8280495b951ee0b1ff4bbd6e5077f0c00ee1`。 +- 校正两张组件基线并纳入视觉回归入口。在 example 目录运行 `flutter test --no-pub test/stepper_demo_golden_test.dart ../test/components/stepper/t_stepper_golden_test.dart`,四项通过,精确 diff 为 0;未放宽比较器容差。 + +## 验证边界与交付 + +- 第二套本地 SDK 是 3.47.0。此前 PR 远端 latest 为 3.47.2,本次未提交或推送,不能把旧 CI 结果作为本次修复的通过证据;实际 latest 仍需远端验证。 +- Android/iOS 真机键盘、IME 和系统字体未验证,Linux Golden 不证明这些路径。 +- 公开签名、枚举和默认值保持兼容,行为变化属于既有契约修复。后续推送时应将 PR 标题和描述调整为修复范围,并记录用户可感知的草稿边界与主题动画修复。 diff --git a/specs/028-stepper-demo-alignment/plan.md b/specs/028-stepper-demo-alignment/plan.md index efafe513b..a362ed067 100644 --- a/specs/028-stepper-demo-alignment/plan.md +++ b/specs/028-stepper-demo-alignment/plan.md @@ -1,6 +1,8 @@ # Plan -1. 固定跨端基线并完成 API Review。 -2. 重排 Demo 与生成示例代码。 -3. 补行为测试、覆盖率门禁和固定 Linux 明暗 Golden。 -4. 双 Flutter 版本复验并独立提交 PR。 +1. 基于 #1064 head `5bdc6b41` 修复,保留用户当前 develop 工作区。 +2. 将运行示例提取为独立 Widget;生成器提取 Widget、必要的直接关联 State 和导入,面板显式绑定类名。 +3. 按 Figma 去掉 99、修正禁用初值和容器布局;保持现有尺寸和公开 API。 +4. 统一草稿与按钮边界判断;主题插值保留端点配置,在内部样式解析处使用真实上下文默认值。 +5. 补组件、完整 Demo、代码面板及生成器回归;验证 95% 生产覆盖率和双 SDK 严格 analyze。 +6. Flutter 3.32 Linux 更新并立即复跑明暗 Golden,记录实际差异与未覆盖项。 diff --git a/specs/028-stepper-demo-alignment/spec.md b/specs/028-stepper-demo-alignment/spec.md index f7d4e6750..ee5927d44 100644 --- a/specs/028-stepper-demo-alignment/spec.md +++ b/specs/028-stepper-demo-alignment/spec.md @@ -2,17 +2,20 @@ ## 目标 -对齐小程序公开 Demo 的基础、边界、禁用、形态与尺寸矩阵,并建立独立行为与视觉回归。 +以 Figma `mdBVCCVGERhxoZLle2eLT0 / 28591:40152` 为展示目标,修复基础、边界、禁用、形态与尺寸示例,并建立独立行为与视觉回归。小程序仅作为 API 和交互参考;设计稿已删除的中间边界示例不再保留。 ## API Review - `value + onChanged` 为严格受控模式;`onChanged == null` 表示整组禁用,不引入 `defaultValue` 或重复的 `disabled`。 - `min/max/step` 负责数值约束,`TStepperVariant` 与 `TStepperSize` 负责互斥视觉语义。 - `variant/size` 的实例值、组件 Theme 与默认值优先级已收敛,无需复制小程序字符串 API。 -- 生产组件源码不变,公开 API 无 breaking change。 +- 保持现有公开构造参数、枚举和默认值,不新增小程序专属参数。修复编辑草稿与按钮可用状态、nullable Theme 插值;属于既有契约修复,不删除能力或修改公开签名。 ## 行为契约 -- Demo 顺序与公开页面一致。 +- Demo 保持三个分组、五个代码入口,共十个步进器;边界只展示 0 / 999,禁用值为 0。基础与禁用左对齐,各块使用完整宽度、组件容器底色和 16px 内边距。 - 最小/最大状态分别由受控值等于边界表达,禁用由空 callback 表达。 -- 所有可交互实例均由页面持有状态。 +- 所有可交互实例由各自 StatefulWidget 示例持有状态,主题切换和页面重建不重置编辑后的值。 +- 五个面板展示实际运行的示例 Widget、对应 State 和依赖导入;页面壳不进入片段。生成器沿用 ExampleCode 注解,支持独立 Widget 及同文件直接关联 State 的提取,不添加示例框架参数。 +- 编辑期间按钮启停和步进运算使用同一个有效草稿值;合法草稿即使从边界开始编辑,也可向两个方向步进。父组件仍为唯一提交值源,拒绝请求时回退,单次操作最多通知一次。 +- Theme 双侧 null 保持继承;单侧 null 按组件当前生效的尺寸、Flutter 显式主题和 TD token 解析后插值,不当作 0 或透明色。插值端点保持原始配置,动态主题和实例尺寸覆盖路径均须验证。 diff --git a/specs/028-stepper-demo-alignment/tasks.md b/specs/028-stepper-demo-alignment/tasks.md index 537108d9c..11fd23065 100644 --- a/specs/028-stepper-demo-alignment/tasks.md +++ b/specs/028-stepper-demo-alignment/tasks.md @@ -1,6 +1,11 @@ # Tasks -- [x] DONE 固定跨端基线并完成 API Review -- [x] DONE 对齐公开 Demo 与功能测试 -- [x] DONE 完成 Golden、覆盖率和双版本验证 -- [ ] DOING 提交、推送并远端复核 PR +- [x] 固定 #1064 head、Figma 节点和小程序参考版本,完成 API Review。 +- [x] 修正边界数量、禁用初值、容器和对齐方式。 +- [x] 五份生成片段包含独立 Widget、必要 State 和导入;验证实际代码面板及最小宿主编译、交互。 +- [x] 统一草稿步进与按钮边界判断,覆盖父组件接受和拒绝请求。 +- [x] 修正 nullable Theme 插值,覆盖尺寸、继承、token、copyWith、嵌套插值和 AnimatedTheme。 +- [x] 完成本地 Flutter 3.32.0 / 3.47.0 回归、严格 analyze、98.51% 生产覆盖率及 CI 工具自测。 +- [x] 检查并更新 Linux Demo 和组件明暗 Golden;四张图精确复跑通过,登记视觉回归入口。 +- [ ] 提交、推送并同步 PR 标题与描述;本次仅完成本地修复。 +- [ ] 推送后验证远端实际 latest;Android/iOS 真机键盘、IME 和系统字体仍待验证。 diff --git a/tdesign-component/example/assets/api/stepper_api.md b/tdesign-component/example/assets/api/stepper_api.md index 4c772ee9b..d272e55ed 100644 --- a/tdesign-component/example/assets/api/stepper_api.md +++ b/tdesign-component/example/assets/api/stepper_api.md @@ -9,7 +9,7 @@ | min | num | 0 | 最小值,必须小于或等于 `max`。 | | onChanged | ValueChanged? | - | 数值变化请求。 点击按钮、提交有效输入或输入框失焦时触发;一次操作最多触发一次。 为 null 时整组禁用。 | | size | TStepperSize? | - | 组件尺寸。 为空时依次使用 `TStepperThemeData.size` 和 `TStepperSize.medium`。 | -| step | num | 1 | 加减按钮使用的步长,必须大于 0。 输入提交不要求是步长的整数倍,但会限制在 `min` 与 `max` 之间。 | +| step | num | 1 | 加减按钮使用的步长,必须大于 0。 输入提交不要求是步长的整数倍,但会限制在 `min` 与 `max` 之间。 编辑时以合法输入草稿作为步进起点,并据此判断按钮是否达到边界。 | | value | num | - | 唯一受控数值,必须位于 `min` 与 `max` 之间。 父组件需要在 `onChanged` 后以新值重建组件,否则输入内容会恢复。 | | variant | TStepperVariant? | - | 组件形态。 为空时依次使用 `TStepperThemeData.variant` 和 `TStepperVariant.normal`。 | diff --git a/tdesign-component/example/assets/code/stepper.StepperBaseExample.txt b/tdesign-component/example/assets/code/stepper.StepperBaseExample.txt new file mode 100644 index 000000000..04bbe8a21 --- /dev/null +++ b/tdesign-component/example/assets/code/stepper.StepperBaseExample.txt @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:tdesign_flutter/tdesign_flutter.dart'; + +/// 在已配置 TDesign 主题的应用中使用 `StepperBaseExample()`。 +class StepperBaseExample extends StatefulWidget { + const StepperBaseExample({super.key}); + + @override + State createState() => _StepperBaseExampleState(); +} + +class _StepperBaseExampleState extends State { + num _base = 3; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + TStepper( + key: const ValueKey('stepper-base'), + value: _base, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _base = value), + ), + ], + ); + } +} diff --git a/tdesign-component/example/assets/code/stepper.StepperBoundsExample.txt b/tdesign-component/example/assets/code/stepper.StepperBoundsExample.txt new file mode 100644 index 000000000..073692624 --- /dev/null +++ b/tdesign-component/example/assets/code/stepper.StepperBoundsExample.txt @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:tdesign_flutter/tdesign_flutter.dart'; + +/// 在已配置 TDesign 主题的应用中使用 `StepperBoundsExample()`。 +class StepperBoundsExample extends StatefulWidget { + const StepperBoundsExample({super.key}); + + @override + State createState() => _StepperBoundsExampleState(); +} + +class _StepperBoundsExampleState extends State { + num _minimum = 0; + num _maximum = 999; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + TStepper( + key: const ValueKey('stepper-minimum'), + value: _minimum, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _minimum = value), + ), + const SizedBox(width: 32), + TStepper( + key: const ValueKey('stepper-maximum'), + value: _maximum, + max: 999, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _maximum = value), + ), + ], + ); + } +} diff --git a/tdesign-component/example/assets/code/stepper.StepperDisabledExample.txt b/tdesign-component/example/assets/code/stepper.StepperDisabledExample.txt new file mode 100644 index 000000000..6f6e370c8 --- /dev/null +++ b/tdesign-component/example/assets/code/stepper.StepperDisabledExample.txt @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:tdesign_flutter/tdesign_flutter.dart'; + +/// 在已配置 TDesign 主题的应用中使用 `StepperDisabledExample()`。 +class StepperDisabledExample extends StatelessWidget { + const StepperDisabledExample({super.key}); + + @override + Widget build(BuildContext context) { + return const Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + TStepper( + key: ValueKey('stepper-disabled'), + value: 0, + variant: TStepperVariant.filled, + ), + ], + ); + } +} diff --git a/tdesign-component/example/assets/code/stepper.StepperSizesExample.txt b/tdesign-component/example/assets/code/stepper.StepperSizesExample.txt new file mode 100644 index 000000000..30ad53e69 --- /dev/null +++ b/tdesign-component/example/assets/code/stepper.StepperSizesExample.txt @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:tdesign_flutter/tdesign_flutter.dart'; + +/// 在已配置 TDesign 主题的应用中使用 `StepperSizesExample()`。 +class StepperSizesExample extends StatefulWidget { + const StepperSizesExample({super.key}); + + @override + State createState() => _StepperSizesExampleState(); +} + +class _StepperSizesExampleState extends State { + num _large = 3; + num _medium = 3; + num _small = 3; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TStepper( + key: const ValueKey('stepper-sizes'), + value: _large, + size: TStepperSize.large, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _large = value), + ), + TStepper( + key: const ValueKey('stepper-medium'), + value: _medium, + size: TStepperSize.medium, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _medium = value), + ), + TStepper( + key: const ValueKey('stepper-small'), + value: _small, + size: TStepperSize.small, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _small = value), + ), + ], + ); + } +} diff --git a/tdesign-component/example/assets/code/stepper.StepperVariantsExample.txt b/tdesign-component/example/assets/code/stepper.StepperVariantsExample.txt new file mode 100644 index 000000000..7e9387981 --- /dev/null +++ b/tdesign-component/example/assets/code/stepper.StepperVariantsExample.txt @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; +import 'package:tdesign_flutter/tdesign_flutter.dart'; + +/// 在已配置 TDesign 主题的应用中使用 `StepperVariantsExample()`。 +class StepperVariantsExample extends StatefulWidget { + const StepperVariantsExample({super.key}); + + @override + State createState() => _StepperVariantsExampleState(); +} + +class _StepperVariantsExampleState extends State { + num _filled = 3; + num _outline = 3; + num _normal = 3; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TStepper( + key: const ValueKey('stepper-variants'), + value: _filled, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _filled = value), + ), + TStepper( + key: const ValueKey('stepper-outline'), + value: _outline, + variant: TStepperVariant.outline, + onChanged: (value) => setState(() => _outline = value), + ), + TStepper( + key: const ValueKey('stepper-normal'), + value: _normal, + variant: TStepperVariant.normal, + onChanged: (value) => setState(() => _normal = value), + ), + ], + ); + } +} diff --git a/tdesign-component/example/assets/code/stepper._buildBase.txt b/tdesign-component/example/assets/code/stepper._buildBase.txt deleted file mode 100644 index 9a5c98239..000000000 --- a/tdesign-component/example/assets/code/stepper._buildBase.txt +++ /dev/null @@ -1,8 +0,0 @@ -Widget _buildBase(BuildContext context) => _row([ - TStepper( - key: const ValueKey('stepper-base'), - value: _base, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _base = value), - ), - ]); diff --git a/tdesign-component/example/assets/code/stepper._buildBounds.txt b/tdesign-component/example/assets/code/stepper._buildBounds.txt deleted file mode 100644 index bee8b0657..000000000 --- a/tdesign-component/example/assets/code/stepper._buildBounds.txt +++ /dev/null @@ -1,22 +0,0 @@ -Widget _buildBounds(BuildContext context) => _row([ - TStepper( - key: const ValueKey('stepper-minimum'), - value: _minimum, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _minimum = value), - ), - TStepper( - value: _middle, - min: 5, - max: 999, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _middle = value), - ), - TStepper( - key: const ValueKey('stepper-maximum'), - value: _maximum, - max: 999, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _maximum = value), - ), - ]); diff --git a/tdesign-component/example/assets/code/stepper._buildDisabled.txt b/tdesign-component/example/assets/code/stepper._buildDisabled.txt deleted file mode 100644 index 0eb7b2b04..000000000 --- a/tdesign-component/example/assets/code/stepper._buildDisabled.txt +++ /dev/null @@ -1,7 +0,0 @@ -Widget _buildDisabled(BuildContext context) => _row(const [ - TStepper( - key: ValueKey('stepper-disabled'), - value: 1, - variant: TStepperVariant.filled, - ), - ]); diff --git a/tdesign-component/example/assets/code/stepper._buildSizes.txt b/tdesign-component/example/assets/code/stepper._buildSizes.txt deleted file mode 100644 index d2daf9427..000000000 --- a/tdesign-component/example/assets/code/stepper._buildSizes.txt +++ /dev/null @@ -1,21 +0,0 @@ -Widget _buildSizes(BuildContext context) => _row([ - TStepper( - key: const ValueKey('stepper-sizes'), - value: _large, - size: TStepperSize.large, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _large = value), - ), - TStepper( - value: _medium, - size: TStepperSize.medium, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _medium = value), - ), - TStepper( - value: _small, - size: TStepperSize.small, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _small = value), - ), - ]); diff --git a/tdesign-component/example/assets/code/stepper._buildVariants.txt b/tdesign-component/example/assets/code/stepper._buildVariants.txt deleted file mode 100644 index fc3795276..000000000 --- a/tdesign-component/example/assets/code/stepper._buildVariants.txt +++ /dev/null @@ -1,18 +0,0 @@ -Widget _buildVariants(BuildContext context) => _row([ - TStepper( - key: const ValueKey('stepper-variants'), - value: _filled, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _filled = value), - ), - TStepper( - value: _outline, - variant: TStepperVariant.outline, - onChanged: (value) => setState(() => _outline = value), - ), - TStepper( - value: _normal, - variant: TStepperVariant.normal, - onChanged: (value) => setState(() => _normal = value), - ), - ]); diff --git a/tdesign-component/example/lib/annotation/example_code.dart b/tdesign-component/example/lib/annotation/example_code.dart index c2b110fd6..42e283862 100644 --- a/tdesign-component/example/lib/annotation/example_code.dart +++ b/tdesign-component/example/lib/annotation/example_code.dart @@ -1,4 +1,7 @@ -/// Marks a method whose source is exported for the example code viewer. +/// Marks a function, method, or standalone example Widget for the code viewer. +/// +/// An annotated class includes its imports and directly associated same-file +/// `State` class. Other helpers must be self-contained in these classes. class ExampleCode { /// The generated snippet group. It must match the page's example code group. final String group; diff --git a/tdesign-component/example/lib/page/stepper/stepper_examples.dart b/tdesign-component/example/lib/page/stepper/stepper_examples.dart new file mode 100644 index 000000000..31aa7f9bd --- /dev/null +++ b/tdesign-component/example/lib/page/stepper/stepper_examples.dart @@ -0,0 +1,176 @@ +import 'package:flutter/material.dart'; +import 'package:tdesign_flutter/tdesign_flutter.dart'; + +import '../../annotation/example_code.dart'; + +/// 在已配置 TDesign 主题的应用中使用 `StepperBaseExample()`。 +@ExampleCode(group: 'stepper') +class StepperBaseExample extends StatefulWidget { + const StepperBaseExample({super.key}); + + @override + State createState() => _StepperBaseExampleState(); +} + +class _StepperBaseExampleState extends State { + num _base = 3; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + TStepper( + key: const ValueKey('stepper-base'), + value: _base, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _base = value), + ), + ], + ); + } +} + +/// 在已配置 TDesign 主题的应用中使用 `StepperBoundsExample()`。 +@ExampleCode(group: 'stepper') +class StepperBoundsExample extends StatefulWidget { + const StepperBoundsExample({super.key}); + + @override + State createState() => _StepperBoundsExampleState(); +} + +class _StepperBoundsExampleState extends State { + num _minimum = 0; + num _maximum = 999; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + TStepper( + key: const ValueKey('stepper-minimum'), + value: _minimum, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _minimum = value), + ), + const SizedBox(width: 32), + TStepper( + key: const ValueKey('stepper-maximum'), + value: _maximum, + max: 999, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _maximum = value), + ), + ], + ); + } +} + +/// 在已配置 TDesign 主题的应用中使用 `StepperDisabledExample()`。 +@ExampleCode(group: 'stepper') +class StepperDisabledExample extends StatelessWidget { + const StepperDisabledExample({super.key}); + + @override + Widget build(BuildContext context) { + return const Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + TStepper( + key: ValueKey('stepper-disabled'), + value: 0, + variant: TStepperVariant.filled, + ), + ], + ); + } +} + +/// 在已配置 TDesign 主题的应用中使用 `StepperVariantsExample()`。 +@ExampleCode(group: 'stepper') +class StepperVariantsExample extends StatefulWidget { + const StepperVariantsExample({super.key}); + + @override + State createState() => _StepperVariantsExampleState(); +} + +class _StepperVariantsExampleState extends State { + num _filled = 3; + num _outline = 3; + num _normal = 3; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TStepper( + key: const ValueKey('stepper-variants'), + value: _filled, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _filled = value), + ), + TStepper( + key: const ValueKey('stepper-outline'), + value: _outline, + variant: TStepperVariant.outline, + onChanged: (value) => setState(() => _outline = value), + ), + TStepper( + key: const ValueKey('stepper-normal'), + value: _normal, + variant: TStepperVariant.normal, + onChanged: (value) => setState(() => _normal = value), + ), + ], + ); + } +} + +/// 在已配置 TDesign 主题的应用中使用 `StepperSizesExample()`。 +@ExampleCode(group: 'stepper') +class StepperSizesExample extends StatefulWidget { + const StepperSizesExample({super.key}); + + @override + State createState() => _StepperSizesExampleState(); +} + +class _StepperSizesExampleState extends State { + num _large = 3; + num _medium = 3; + num _small = 3; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TStepper( + key: const ValueKey('stepper-sizes'), + value: _large, + size: TStepperSize.large, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _large = value), + ), + TStepper( + key: const ValueKey('stepper-medium'), + value: _medium, + size: TStepperSize.medium, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _medium = value), + ), + TStepper( + key: const ValueKey('stepper-small'), + value: _small, + size: TStepperSize.small, + variant: TStepperVariant.filled, + onChanged: (value) => setState(() => _small = value), + ), + ], + ); + } +} diff --git a/tdesign-component/example/lib/page/t_stepper_page.dart b/tdesign-component/example/lib/page/t_stepper_page.dart index d86b5cf86..aa373b669 100644 --- a/tdesign-component/example/lib/page/t_stepper_page.dart +++ b/tdesign-component/example/lib/page/t_stepper_page.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; -import '../annotation/example_code.dart'; import '../base/example_widget.dart'; +import 'stepper/stepper_examples.dart'; class TStepperPage extends StatefulWidget { const TStepperPage({super.key}); @@ -12,17 +12,6 @@ class TStepperPage extends StatefulWidget { } class _TStepperPageState extends State { - num _base = 3; - num _minimum = 0; - num _middle = 99; - num _maximum = 999; - num _filled = 3; - num _outline = 3; - num _normal = 3; - num _large = 3; - num _medium = 3; - num _small = 3; - @override Widget build(BuildContext context) => ExamplePage( title: tTitle(), @@ -33,115 +22,54 @@ class _TStepperPageState extends State { children: [ ExampleModule( title: '组件类型', - children: [ExampleItem(desc: '基础步进器', builder: _buildBase)], + children: [ + ExampleItem( + desc: '基础步进器', + center: false, + methodName: 'StepperBaseExample', + builder: (_) => _container(const StepperBaseExample()), + ), + ], ), ExampleModule( title: '组件状态', children: [ - ExampleItem(desc: '最大最小状态', builder: _buildBounds), - ExampleItem(desc: '禁用状态', builder: _buildDisabled), + ExampleItem( + desc: '最大最小状态', + center: false, + methodName: 'StepperBoundsExample', + builder: (_) => _container(const StepperBoundsExample()), + ), + ExampleItem( + desc: '禁用状态', + center: false, + methodName: 'StepperDisabledExample', + builder: (_) => _container(const StepperDisabledExample()), + ), ], ), ExampleModule( title: '组件样式', children: [ - ExampleItem(desc: '步进器样式', builder: _buildVariants), - ExampleItem(desc: '步进器尺寸', builder: _buildSizes), + ExampleItem( + desc: '步进器样式', + center: false, + methodName: 'StepperVariantsExample', + builder: (_) => _container(const StepperVariantsExample()), + ), + ExampleItem( + desc: '步进器尺寸', + center: false, + methodName: 'StepperSizesExample', + builder: (_) => _container(const StepperSizesExample()), + ), ], ), ], ); - @ExampleCode(group: 'stepper') - Widget _buildBase(BuildContext context) => _row([ - TStepper( - key: const ValueKey('stepper-base'), - value: _base, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _base = value), - ), - ]); - - @ExampleCode(group: 'stepper') - Widget _buildBounds(BuildContext context) => _row([ - TStepper( - key: const ValueKey('stepper-minimum'), - value: _minimum, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _minimum = value), - ), - TStepper( - value: _middle, - min: 5, - max: 999, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _middle = value), - ), - TStepper( - key: const ValueKey('stepper-maximum'), - value: _maximum, - max: 999, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _maximum = value), - ), - ]); - - @ExampleCode(group: 'stepper') - Widget _buildDisabled(BuildContext context) => _row(const [ - TStepper( - key: ValueKey('stepper-disabled'), - value: 1, - variant: TStepperVariant.filled, - ), - ]); - - @ExampleCode(group: 'stepper') - Widget _buildVariants(BuildContext context) => _row([ - TStepper( - key: const ValueKey('stepper-variants'), - value: _filled, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _filled = value), - ), - TStepper( - value: _outline, - variant: TStepperVariant.outline, - onChanged: (value) => setState(() => _outline = value), - ), - TStepper( - value: _normal, - variant: TStepperVariant.normal, - onChanged: (value) => setState(() => _normal = value), - ), - ]); - - @ExampleCode(group: 'stepper') - Widget _buildSizes(BuildContext context) => _row([ - TStepper( - key: const ValueKey('stepper-sizes'), - value: _large, - size: TStepperSize.large, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _large = value), - ), - TStepper( - value: _medium, - size: TStepperSize.medium, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _medium = value), - ), - TStepper( - value: _small, - size: TStepperSize.small, - variant: TStepperVariant.filled, - onChanged: (value) => setState(() => _small = value), - ), - ]); - - Widget _row(List children) => Wrap( - spacing: 16, - runSpacing: 16, - crossAxisAlignment: WrapCrossAlignment.center, - children: children, + Widget _container(Widget child) => ColoredBox( + color: context.tTheme.bgColorContainer, + child: Padding(padding: const EdgeInsets.all(16), child: child), ); } diff --git a/tdesign-component/example/test/goldens/stepper_page_dark.png b/tdesign-component/example/test/goldens/stepper_page_dark.png index 3021db07d732316eac31e82d0c05b63aaa14de5b..9baba17a673cc748810ab8c40a923e7057becc0f 100644 GIT binary patch literal 38099 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 diff --git a/tdesign-component/example/test/goldens/stepper_page_light.png b/tdesign-component/example/test/goldens/stepper_page_light.png index 8cf6bbd4d3144174db2ce44e799545fa0fdbb4b2..428d1a91d0ed533fe18402aa298c62ee5a892653 100644 GIT binary patch literal 37958 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

PJW$Lg~7*V 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 D_Cs9C diff --git a/tdesign-component/example/test/stepper_demo_test.dart b/tdesign-component/example/test/stepper_demo_test.dart index 844e7455c..ebea72b60 100644 --- a/tdesign-component/example/test/stepper_demo_test.dart +++ b/tdesign-component/example/test/stepper_demo_test.dart @@ -1,6 +1,12 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:provider/provider.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; +import 'package:tdesign_flutter_example/base/example_base.dart'; +import 'package:tdesign_flutter_example/page/t_stepper_page.dart'; +import 'package:tdesign_flutter_example/provider/theme_mode_provider.dart'; import 'demo_page_test_utils.dart'; import 'stepper_demo_test_spec.dart'; @@ -34,6 +40,7 @@ void main() { expect(minimum.value, minimum.min); expect(maximum.value, maximum.max); expect(disabled.onChanged, isNull); + expect(disabled.value, 0); await disposeDemoPage(tester); }, tags: 'demo'); @@ -48,4 +55,133 @@ void main() { expect(tester.widget(stepper).value, 4); await disposeDemoPage(tester); }, tags: 'demo'); + + testWidgets('all design instances, styles and container bounds match', ( + tester, + ) async { + await pumpFullDemoPage(tester, stepperDemoPageTestSpec, ThemeMode.light); + final steppers = tester + .widgetList(find.byType(TStepper)) + .toList(); + expect(steppers.map((stepper) => stepper.value), [ + 3, + 0, + 999, + 0, + 3, + 3, + 3, + 3, + 3, + 3, + ]); + expect(steppers.map((stepper) => stepper.variant), [ + TStepperVariant.filled, + TStepperVariant.filled, + TStepperVariant.filled, + TStepperVariant.filled, + TStepperVariant.filled, + TStepperVariant.outline, + TStepperVariant.normal, + TStepperVariant.filled, + TStepperVariant.filled, + TStepperVariant.filled, + ]); + expect( + steppers.skip(7).map((stepper) => stepper.size), + TStepperSize.values.reversed, + ); + for (final key in ['base', 'minimum', 'disabled', 'variants', 'sizes']) { + final stepper = find.byKey(ValueKey('stepper-$key')); + expect(tester.getTopLeft(stepper).dx, 16); + final container = find + .ancestor(of: stepper, matching: find.byType(ColoredBox)) + .first; + expect(tester.getSize(container).width, 375); + expect( + tester.widget(container).color, + Theme.of( + tester.element(stepper), + ).extension()!.bgColorContainer, + ); + expect( + tester.getTopLeft(stepper).dy - tester.getTopLeft(container).dy, + 16, + ); + } + final minimum = find.byKey(const ValueKey('stepper-minimum')); + final maximum = find.byKey(const ValueKey('stepper-maximum')); + expect(tester.getTopLeft(maximum).dx - tester.getTopRight(minimum).dx, 32); + await disposeDemoPage(tester); + }, tags: 'demo'); + + testWidgets('theme rebuild preserves each example state', (tester) async { + await pumpFullDemoPage(tester, stepperDemoPageTestSpec, ThemeMode.light); + for (final key in ['base', 'minimum', 'variants', 'sizes']) { + final stepper = find.byKey(ValueKey('stepper-$key')); + await tester.tap( + find.descendant(of: stepper, matching: find.bySemanticsLabel('增加')), + ); + await tester.pump(); + } + await pumpFullDemoPage(tester, stepperDemoPageTestSpec, ThemeMode.dark); + for (final key in ['base', 'minimum', 'variants', 'sizes']) { + expect( + tester.widget(find.byKey(ValueKey('stepper-$key'))).value, + key == 'minimum' ? 1 : 4, + ); + } + await disposeDemoPage(tester); + }, tags: 'demo'); + + testWidgets( + 'all five real code panels load their complete generated example', + (tester) async { + tester.view.physicalSize = const Size(375, 1100); + tester.view.devicePixelRatio = 1; + addTearDown(tester.view.resetPhysicalSize); + addTearDown(tester.view.resetDevicePixelRatio); + final model = ExamplePageModel( + text: 'Stepper 步进器', + name: 'stepper', + pageBuilder: (_, __) => const TStepperPage(), + )..showAction = true; + await tester.pumpWidget( + ChangeNotifierProvider( + create: (_) => ThemeModeProvider(), + child: MaterialApp( + theme: TThemeBuilder.light(TThemeData.defaultData()), + home: ExamplePageInheritedTheme( + model: model, + child: const TStepperPage(), + ), + ), + ), + ); + await tester.pumpAndSettle(); + await tester.tap(find.byIcon(TIcons.code)); + await tester.pumpAndSettle(); + expect(find.text('code'), findsNWidgets(5)); + const names = [ + 'StepperBaseExample', + 'StepperBoundsExample', + 'StepperDisabledExample', + 'StepperVariantsExample', + 'StepperSizesExample', + ]; + for (var i = 0; i < names.length; i++) { + await tester.tap(find.text('code').at(i)); + await tester.pumpAndSettle(); + final expected = await rootBundle.loadString( + 'assets/code/stepper.${names[i]}.txt', + ); + final content = tester.widget(find.byType(Markdown)).data; + expect(content, contains(expected)); + Navigator.of(tester.element(find.byType(Markdown))).pop(); + await tester.pumpAndSettle(); + } + await disposeDemoPage(tester); + }, + tags: 'demo', + ); } diff --git a/tdesign-component/example/test/stepper_demo_test_spec.dart b/tdesign-component/example/test/stepper_demo_test_spec.dart index e73934803..75630772a 100644 --- a/tdesign-component/example/test/stepper_demo_test_spec.dart +++ b/tdesign-component/example/test/stepper_demo_test_spec.dart @@ -1,3 +1,4 @@ +import 'package:tdesign_flutter/tdesign_flutter.dart'; import 'package:tdesign_flutter_example/page/t_stepper_page.dart'; import 'demo_page_test_utils.dart'; @@ -6,6 +7,8 @@ const stepperDemoPageTestSpec = DemoPageTestSpec( name: 'stepper', title: 'Stepper 步进器', page: TStepperPage(), + componentType: TStepper, + expectedComponentCount: 10, expectedTexts: [ '用于数量的增减。', '01 组件类型', diff --git a/tdesign-component/lib/src/components/stepper/t_stepper.dart b/tdesign-component/lib/src/components/stepper/t_stepper.dart index 440812ae9..7a4bec8af 100644 --- a/tdesign-component/lib/src/components/stepper/t_stepper.dart +++ b/tdesign-component/lib/src/components/stepper/t_stepper.dart @@ -7,7 +7,9 @@ import 'package:tdesign_flutter_icons/tdesign_flutter_icons.dart' show TIcons; import '../../theme/t_colors.dart'; import '../../theme/t_radius.dart'; import '../../theme/t_theme.dart'; +import 't_stepper_defaults.dart'; import 't_stepper_theme_data.dart'; +import 't_stepper_theme_interpolation.dart'; import 't_stepper_types.dart'; export 't_stepper_types.dart'; @@ -43,6 +45,7 @@ class TStepper extends StatefulWidget { /// 加减按钮使用的步长,必须大于 0。 /// /// 输入提交不要求是步长的整数倍,但会限制在 [min] 与 [max] 之间。 + /// 编辑时以合法输入草稿作为步进起点,并据此判断按钮是否达到边界。 this.step = 1, /// 组件尺寸。 @@ -75,6 +78,8 @@ class TStepper extends StatefulWidget { final num max; /// 加减按钮使用的正数步长;直接输入不要求是步长的整数倍。 + /// + /// 编辑时合法草稿同时决定步进起点与按钮的边界状态。 final num step; /// 组件尺寸;为空时依次使用组件主题和 [TStepperSize.medium]。 @@ -93,6 +98,9 @@ class _TStepperState extends State { bool _editing = false; bool get _disabled => widget.onChanged == null; + num get _stepBase => _editing + ? num.tryParse(_textController.text) ?? widget.value + : widget.value; num get _effectiveMin => widget.min.isNaN ? 0 : widget.min; num get _effectiveMax { final min = _effectiveMin; @@ -127,8 +135,8 @@ class _TStepperState extends State { @override Widget build(BuildContext context) { final style = _StepperStyle.resolve(context, widget); - final canDecrease = !_disabled && widget.value > _effectiveMin; - final canIncrease = !_disabled && widget.value < _effectiveMax; + final canDecrease = !_disabled && _stepBase > _effectiveMin; + final canIncrease = !_disabled && _stepBase < _effectiveMax; final spacing = style.variant == TStepperVariant.outline ? 0.0 : style.spacing; @@ -232,7 +240,7 @@ class _TStepperState extends State { : oldValue; }), ], - onChanged: (_) => _editing = true, + onChanged: (_) => setState(() => _editing = true), onSubmitted: (_) => _submitDraft(unfocus: true), onTapOutside: (_) => _submitDraft(unfocus: true), ), @@ -249,15 +257,14 @@ class _TStepperState extends State { } void _stepBy(num delta) { - final draft = num.tryParse(_textController.text); - final base = _editing && draft != null ? draft : widget.value; + final base = _stepBase; _requestChange(_normalizeStepResult(base + delta, base), unfocus: true); } void _submitDraft({required bool unfocus}) { final parsed = num.tryParse(_textController.text); if (parsed == null) { - _editing = false; + setState(() => _editing = false); _setText(widget.value); if (unfocus) { _focusNode.unfocus(); @@ -269,7 +276,7 @@ class _TStepperState extends State { void _requestChange(num next, {required bool unfocus}) { final clamped = next.clamp(_effectiveMin, _effectiveMax); - _editing = false; + setState(() => _editing = false); if (unfocus) { _focusNode.unfocus(); } @@ -417,6 +424,38 @@ class _StepperButton extends StatelessWidget { } class _StepperStyle { + static _StepperStyle _lerp(_StepperStyle a, _StepperStyle b, double t) { + return _StepperStyle( + variant: t < 0.5 ? a.variant : b.variant, + controlSize: a.controlSize + (b.controlSize - a.controlSize) * t, + inputWidth: a.inputWidth + (b.inputWidth - a.inputWidth) * t, + iconSize: a.iconSize + (b.iconSize - a.iconSize) * t, + spacing: a.spacing + (b.spacing - a.spacing) * t, + borderWidth: a.borderWidth + (b.borderWidth - a.borderWidth) * t, + borderRadius: BorderRadius.lerp(a.borderRadius, b.borderRadius, t)!, + foregroundColor: Color.lerp(a.foregroundColor, b.foregroundColor, t)!, + disabledForegroundColor: Color.lerp( + a.disabledForegroundColor, + b.disabledForegroundColor, + t, + )!, + iconColor: Color.lerp(a.iconColor, b.iconColor, t)!, + backgroundColor: Color.lerp(a.backgroundColor, b.backgroundColor, t)!, + disabledBackgroundColor: Color.lerp( + a.disabledBackgroundColor, + b.disabledBackgroundColor, + t, + )!, + borderColor: Color.lerp(a.borderColor, b.borderColor, t)!, + textStyle: TextStyle.lerp(a.textStyle, b.textStyle, t)!, + disabledTextStyle: TextStyle.lerp( + a.disabledTextStyle, + b.disabledTextStyle, + t, + )!, + ); + } + const _StepperStyle({ required this.variant, required this.controlSize, @@ -452,32 +491,31 @@ class _StepperStyle { final TextStyle disabledTextStyle; static _StepperStyle resolve(BuildContext context, TStepper widget) { + return _resolveTheme( + context, + widget, + Theme.of(context).extension(), + ); + } + + static _StepperStyle _resolveTheme( + BuildContext context, + TStepper widget, + TStepperThemeData? componentTheme, + ) { + if (componentTheme is StepperThemeInterpolation) { + return _lerp( + _resolveTheme(context, widget, componentTheme.begin), + _resolveTheme(context, widget, componentTheme.end), + componentTheme.progress, + ); + } final materialTheme = Theme.of(context); - final componentTheme = materialTheme.extension(); final token = context.tTheme; final size = widget.size ?? componentTheme?.size ?? TStepperSize.medium; final variant = widget.variant ?? componentTheme?.variant ?? TStepperVariant.normal; - final geometry = switch (size) { - TStepperSize.small => const ( - controlSize: 20.0, - inputWidth: 34.0, - iconSize: 12.0, - fontSize: 10.0, - ), - TStepperSize.medium => const ( - controlSize: 24.0, - inputWidth: 38.0, - iconSize: 16.0, - fontSize: 12.0, - ), - TStepperSize.large => const ( - controlSize: 26.0, - inputWidth: 45.0, - iconSize: 20.0, - fontSize: 16.0, - ), - }; + final geometry = stepperGeometry(size); final defaultTextStyle = context.tExplicitDefaultTextStyle; final materialTextStyle = materialTheme.tExplicitTextTheme?.bodySmall ?? const TextStyle(); @@ -512,11 +550,11 @@ class _StepperStyle { controlSize: componentTheme?.controlSize ?? geometry.controlSize, inputWidth: componentTheme?.inputWidth ?? geometry.inputWidth, iconSize: componentTheme?.iconSize ?? geometry.iconSize, - spacing: componentTheme?.spacing ?? 4, + spacing: componentTheme?.spacing ?? stepperSpacing, borderRadius: componentTheme?.borderRadius ?? BorderRadius.circular(token.radiusSmall), - borderWidth: componentTheme?.borderWidth ?? 1, + borderWidth: componentTheme?.borderWidth ?? stepperBorderWidth, foregroundColor: foregroundColor, disabledForegroundColor: disabledForegroundColor, iconColor: diff --git a/tdesign-component/lib/src/components/stepper/t_stepper_defaults.dart b/tdesign-component/lib/src/components/stepper/t_stepper_defaults.dart new file mode 100644 index 000000000..3d6d61a03 --- /dev/null +++ b/tdesign-component/lib/src/components/stepper/t_stepper_defaults.dart @@ -0,0 +1,29 @@ +import 't_stepper_types.dart'; + +// One geometry definition serves normal rendering and theme interpolation. +typedef StepperGeometry = ({ + double controlSize, + double inputWidth, + double iconSize, + double fontSize, +}); + +StepperGeometry stepperGeometry(TStepperSize? size) => switch (size) { + TStepperSize.small => ( + controlSize: 20, + inputWidth: 34, + iconSize: 12, + fontSize: 10, + ), + TStepperSize.large => ( + controlSize: 26, + inputWidth: 45, + iconSize: 20, + fontSize: 16, + ), + TStepperSize.medium || + null => (controlSize: 24, inputWidth: 38, iconSize: 16, fontSize: 12), +}; + +const stepperSpacing = 4.0; +const stepperBorderWidth = 1.0; diff --git a/tdesign-component/lib/src/components/stepper/t_stepper_theme_data.dart b/tdesign-component/lib/src/components/stepper/t_stepper_theme_data.dart index 220042c5e..ba8f26d6b 100644 --- a/tdesign-component/lib/src/components/stepper/t_stepper_theme_data.dart +++ b/tdesign-component/lib/src/components/stepper/t_stepper_theme_data.dart @@ -1,7 +1,6 @@ -import 'dart:ui' show lerpDouble; - import 'package:flutter/material.dart'; +import 't_stepper_theme_interpolation.dart'; import 't_stepper_types.dart'; /// `TStepper` 的组件级主题。 @@ -65,11 +64,11 @@ class TStepperThemeData extends ThemeExtension { /// 在继承 DefaultTextStyle 和 ThemeData.textTheme 后合并;非空字段可覆盖 /// 默认字号、行高及 [foregroundColor]。 this.textStyle, - }) : assert(inputWidth == null || inputWidth > 0), - assert(controlSize == null || controlSize > 0), - assert(iconSize == null || iconSize > 0), - assert(spacing == null || spacing >= 0), - assert(borderWidth == null || borderWidth >= 0); + }) : assert(inputWidth == null || inputWidth > 0), + assert(controlSize == null || controlSize > 0), + assert(iconSize == null || iconSize > 0), + assert(spacing == null || spacing >= 0), + assert(borderWidth == null || borderWidth >= 0); /// 默认尺寸;为空时使用中尺寸。 final TStepperSize? size; @@ -150,34 +149,20 @@ class TStepperThemeData extends ThemeExtension { ); } + /// 插值保留未指定字段的继承语义,由组件结合当前实例尺寸与主题解析。 + /// + /// 两端均未指定的字段仍为 null;端点返回原始配置。 @override TStepperThemeData lerp(ThemeExtension? other, double t) { if (other is! TStepperThemeData) { return this; } - return TStepperThemeData( - size: t < 0.5 ? size : other.size, - variant: t < 0.5 ? variant : other.variant, - inputWidth: lerpDouble(inputWidth, other.inputWidth, t), - controlSize: lerpDouble(controlSize, other.controlSize, t), - iconSize: lerpDouble(iconSize, other.iconSize, t), - spacing: lerpDouble(spacing, other.spacing, t), - borderRadius: BorderRadius.lerp(borderRadius, other.borderRadius, t), - borderWidth: lerpDouble(borderWidth, other.borderWidth, t), - foregroundColor: Color.lerp(foregroundColor, other.foregroundColor, t), - disabledForegroundColor: Color.lerp( - disabledForegroundColor, - other.disabledForegroundColor, - t, - ), - backgroundColor: Color.lerp(backgroundColor, other.backgroundColor, t), - disabledBackgroundColor: Color.lerp( - disabledBackgroundColor, - other.disabledBackgroundColor, - t, - ), - borderColor: Color.lerp(borderColor, other.borderColor, t), - textStyle: TextStyle.lerp(textStyle, other.textStyle, t), - ); + if (t == 0) { + return this; + } + if (t == 1) { + return other; + } + return StepperThemeInterpolation(this, other, t); } } diff --git a/tdesign-component/lib/src/components/stepper/t_stepper_theme_interpolation.dart b/tdesign-component/lib/src/components/stepper/t_stepper_theme_interpolation.dart new file mode 100644 index 000000000..2c6168054 --- /dev/null +++ b/tdesign-component/lib/src/components/stepper/t_stepper_theme_interpolation.dart @@ -0,0 +1,161 @@ +import 'dart:ui' show lerpDouble; + +import 'package:flutter/material.dart'; + +import 't_stepper_defaults.dart'; +import 't_stepper_theme_data.dart'; +import 't_stepper_types.dart'; + +// Internal interpolation data, deliberately not exported from the package. +// Unset visual fields depend on the consuming widget's size, inherited styles, +// and tokens. Resolve both endpoints there instead of promoting placeholder +// colors or geometry into explicit component overrides. +class StepperThemeInterpolation extends TStepperThemeData { + StepperThemeInterpolation(this.begin, this.end, this.progress) + : super( + size: progress < 0.5 ? begin.size : end.size, + variant: progress < 0.5 ? begin.variant : end.variant, + inputWidth: _number( + begin.inputWidth, + end.inputWidth, + stepperGeometry(begin.size).inputWidth, + stepperGeometry(end.size).inputWidth, + progress, + ), + controlSize: _number( + begin.controlSize, + end.controlSize, + stepperGeometry(begin.size).controlSize, + stepperGeometry(end.size).controlSize, + progress, + ), + iconSize: _number( + begin.iconSize, + end.iconSize, + stepperGeometry(begin.size).iconSize, + stepperGeometry(end.size).iconSize, + progress, + ), + spacing: _number( + begin.spacing, + end.spacing, + stepperSpacing, + stepperSpacing, + progress, + ), + borderRadius: _nullable( + begin.borderRadius, + end.borderRadius, + progress, + BorderRadius.lerp, + ), + borderWidth: _number( + begin.borderWidth, + end.borderWidth, + stepperBorderWidth, + stepperBorderWidth, + progress, + ), + foregroundColor: _nullable( + begin.foregroundColor, + end.foregroundColor, + progress, + Color.lerp, + ), + disabledForegroundColor: _nullable( + begin.disabledForegroundColor, + end.disabledForegroundColor, + progress, + Color.lerp, + ), + backgroundColor: _nullable( + begin.backgroundColor, + end.backgroundColor, + progress, + Color.lerp, + ), + disabledBackgroundColor: _nullable( + begin.disabledBackgroundColor, + end.disabledBackgroundColor, + progress, + Color.lerp, + ), + borderColor: _nullable( + begin.borderColor, + end.borderColor, + progress, + Color.lerp, + ), + textStyle: _nullable( + begin.textStyle, + end.textStyle, + progress, + TextStyle.lerp, + ), + ); + + final TStepperThemeData begin; + final TStepperThemeData end; + final double progress; + + @override + TStepperThemeData copyWith({ + TStepperSize? size, + TStepperVariant? variant, + double? inputWidth, + double? controlSize, + double? iconSize, + double? spacing, + BorderRadius? borderRadius, + double? borderWidth, + Color? foregroundColor, + Color? disabledForegroundColor, + Color? backgroundColor, + Color? disabledBackgroundColor, + Color? borderColor, + TextStyle? textStyle, + }) { + TStepperThemeData copy(TStepperThemeData theme) => theme.copyWith( + size: size, + variant: variant, + inputWidth: inputWidth, + controlSize: controlSize, + iconSize: iconSize, + spacing: spacing, + borderRadius: borderRadius, + borderWidth: borderWidth, + foregroundColor: foregroundColor, + disabledForegroundColor: disabledForegroundColor, + backgroundColor: backgroundColor, + disabledBackgroundColor: disabledBackgroundColor, + borderColor: borderColor, + textStyle: textStyle, + ); + return copy(begin).lerp(copy(end), progress); + } + + static double? _number( + double? a, + double? b, + double defaultA, + double defaultB, + double t, + ) { + if (a == null && b == null) { + return null; + } + return lerpDouble(a ?? defaultA, b ?? defaultB, t); + } + + static T? _nullable( + T? a, + T? b, + double t, + T? Function(T?, T?, double) lerp, + ) { + if (a == null || b == null) { + return t < 0.5 ? a : b; + } + return lerp(a, b, t); + } +} diff --git a/tdesign-component/test/components/stepper/goldens/t_stepper_dark.png b/tdesign-component/test/components/stepper/goldens/t_stepper_dark.png index be65c91f5af05d6d572215448c07dc5a46cd2c40..cbfaa9345a1fe7273d25c38eab7f68cf82477a5b 100644 GIT binary patch literal 4497 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 S>kj@_ff(tTBP(^BBL4-=o_pZ{ literal 4468 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 Kg)({bz`p^`jtF-E diff --git a/tdesign-component/test/components/stepper/t_stepper_contract_test.dart b/tdesign-component/test/components/stepper/t_stepper_contract_test.dart new file mode 100644 index 000000000..bf8e786ae --- /dev/null +++ b/tdesign-component/test/components/stepper/t_stepper_contract_test.dart @@ -0,0 +1,331 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:tdesign_flutter/tdesign_flutter.dart'; + +void main() { + Widget host(Widget child, {TStepperThemeData? theme, TThemeData? token}) => + MaterialApp( + themeAnimationDuration: Duration.zero, + theme: TThemeBuilder.light( + token ?? TThemeData.defaultData(), + ).mergeExtension(theme ?? const TStepperThemeData()), + home: Scaffold(body: Center(child: child)), + ); + + EditableText input(WidgetTester tester) => + tester.widget(find.byType(EditableText)); + + Size size(WidgetTester tester) => tester.getSize( + find.descendant(of: find.byType(TStepper), matching: find.byType(Row)), + ); + + BoxDecoration inputDecoration(WidgetTester tester) => + tester + .widget( + find.ancestor( + of: find.byType(EditableText), + matching: find.byType(DecoratedBox), + ), + ) + .decoration + as BoxDecoration; + + for (final entry in [(0, TIcons.minus, 4), (10, TIcons.plus, 6)]) { + for (final accepts in [true, false]) { + testWidgets('draft at ${entry.$1}, parent accepts: $accepts', ( + tester, + ) async { + num value = entry.$1; + final requests = []; + await tester.pumpWidget( + host( + StatefulBuilder( + builder: (context, setState) => TStepper( + value: value, + max: 10, + onChanged: (next) { + requests.add(next); + if (accepts) { + setState(() => value = next); + } + }, + ), + ), + ), + ); + await tester.enterText(find.byType(EditableText), '5'); + await tester.pump(); + await tester.tap(find.byIcon(entry.$2)); + await tester.pump(); + expect(requests, [entry.$3]); + expect( + input(tester).controller.text, + '${accepts ? entry.$3 : entry.$1}', + ); + if (!accepts) { + await tester.tap(find.byIcon(entry.$2)); + await tester.pump(); + expect(requests, hasLength(1)); + } + }); + } + } + + testWidgets('draft boundaries disable the matching action immediately', ( + tester, + ) async { + final requests = []; + await tester.pumpWidget( + host(TStepper(value: 5, max: 10, onChanged: requests.add)), + ); + await tester.enterText(find.byType(EditableText), '0'); + await tester.pump(); + await tester.tap(find.byIcon(TIcons.minus)); + expect(requests, isEmpty); + await tester.tap(find.byIcon(TIcons.plus)); + await tester.pump(); + expect(requests, [1]); + await tester.enterText(find.byType(EditableText), '10'); + await tester.pump(); + await tester.tap(find.byIcon(TIcons.plus)); + expect(requests, [1]); + await tester.tap(find.byIcon(TIcons.minus)); + await tester.pump(); + expect(requests, [1, 9]); + }); + + testWidgets('invalid draft falls back to the controlled button bounds', ( + tester, + ) async { + final requests = []; + await tester.pumpWidget( + host(TStepper(value: 0, max: 10, onChanged: requests.add)), + ); + await tester.enterText(find.byType(EditableText), '-'); + await tester.pump(); + await tester.tap(find.byIcon(TIcons.minus)); + expect(requests, isEmpty); + await tester.tap(find.byIcon(TIcons.plus)); + await tester.pump(); + expect(requests, [1]); + expect(input(tester).controller.text, '0'); + }); + + test('theme interpolation keeps exact endpoints and unset fields', () { + const a = TStepperThemeData(); + const b = TStepperThemeData(controlSize: 40); + expect(a.lerp(b, 0), same(a)); + expect(a.lerp(b, 1), same(b)); + final unset = a.lerp(a, 0.5); + expect(unset.size, isNull); + expect(unset.variant, isNull); + expect(unset.inputWidth, isNull); + expect(unset.controlSize, isNull); + expect(unset.iconSize, isNull); + expect(unset.spacing, isNull); + expect(unset.borderWidth, isNull); + expect(unset.borderRadius, isNull); + expect(unset.foregroundColor, isNull); + expect(unset.disabledForegroundColor, isNull); + expect(unset.backgroundColor, isNull); + expect(unset.disabledBackgroundColor, isNull); + expect(unset.borderColor, isNull); + expect(unset.textStyle, isNull); + }); + + for (final entry in [ + (TStepperSize.small, 20.0, 34.0, 12.0), + (TStepperSize.medium, 24.0, 38.0, 16.0), + (TStepperSize.large, 26.0, 45.0, 20.0), + ]) { + test('nullable geometry uses ${entry.$1} defaults in both directions', () { + final a = TStepperThemeData(size: entry.$1); + final b = TStepperThemeData( + size: entry.$1, + controlSize: 40, + inputWidth: 80, + iconSize: 24, + spacing: 8, + borderWidth: 3, + ); + for (final t in [0.25, 0.5, 0.75]) { + final forward = a.lerp(b, t); + final reverse = b.lerp(a, 1 - t); + expect(forward.controlSize, entry.$2 + (40 - entry.$2) * t); + expect(reverse.controlSize, forward.controlSize); + expect(forward.inputWidth, entry.$3 + (80 - entry.$3) * t); + expect(reverse.inputWidth, forward.inputWidth); + expect(forward.iconSize, entry.$4 + (24 - entry.$4) * t); + expect(reverse.iconSize, forward.iconSize); + expect(forward.spacing, 4 + 4 * t); + expect(reverse.spacing, forward.spacing); + expect(forward.borderWidth, 1 + 2 * t); + expect(reverse.borderWidth, forward.borderWidth); + } + }); + } + + testWidgets( + 'rendered interpolation uses the instance size and can be copied', + (tester) async { + const a = TStepperThemeData(size: TStepperSize.large); + const b = TStepperThemeData( + controlSize: 40, + inputWidth: 80, + iconSize: 24, + spacing: 8, + ); + final middle = a.lerp(b, 0.5).copyWith(foregroundColor: Colors.red); + await tester.pumpWidget( + host( + TStepper(value: 3, size: TStepperSize.small, onChanged: (_) {}), + theme: middle, + ), + ); + expect(size(tester), const Size(129, 30)); + expect(tester.widget(find.byIcon(TIcons.plus)).size, 18); + expect( + tester.widget(find.byIcon(TIcons.plus)).color, + const Color(0xfff44336), + ); + expect(input(tester).style.color, const Color(0xfff44336)); + }, + ); + + testWidgets('nullable visual styles interpolate from effective tokens', ( + tester, + ) async { + final token = TThemeData.defaultData().copyWithTThemeData( + 'stepper-lerp', + colorMap: { + 'textColorPrimary': Colors.red, + 'textDisabledColor': Colors.green, + 'bgColorSecondaryContainer': Colors.yellow, + 'bgColorComponentDisabled': Colors.orange, + 'componentBorderColor': Colors.blue, + }, + ); + const a = TStepperThemeData(); + const b = TStepperThemeData( + foregroundColor: Colors.black, + disabledForegroundColor: Colors.black, + backgroundColor: Colors.black, + disabledBackgroundColor: Colors.black, + borderColor: Colors.black, + borderRadius: BorderRadius.all(Radius.circular(10)), + textStyle: TextStyle(fontSize: 20, height: 1.5), + ); + for (final reverse in [false, true]) { + final theme = reverse ? b.lerp(a, 0.5) : a.lerp(b, 0.5); + for (final disabled in [false, true]) { + await tester.pumpWidget( + host( + TStepper( + value: 3, + variant: TStepperVariant.filled, + onChanged: disabled ? null : (_) {}, + ), + theme: theme, + token: token, + ), + ); + expect( + input(tester).style.color, + Color.lerp(disabled ? Colors.green : Colors.red, Colors.black, 0.5), + ); + expect(input(tester).style.fontSize, 16); + expect(input(tester).style.height, 1.25); + expect( + inputDecoration(tester).color, + Color.lerp( + disabled ? Colors.orange : Colors.yellow, + Colors.black, + 0.5, + ), + ); + expect( + inputDecoration(tester).borderRadius, + BorderRadius.circular((token.radiusSmall + 10) / 2), + ); + } + await tester.pumpWidget( + host( + TStepper( + value: 3, + variant: TStepperVariant.outline, + onChanged: (_) {}, + ), + theme: theme, + token: token, + ), + ); + expect( + (inputDecoration(tester).border! as Border).top.color, + Color.lerp(Colors.blue, Colors.black, 0.5), + ); + } + }); + + testWidgets('inherited text and icon defaults survive nested interpolation', ( + tester, + ) async { + const a = TStepperThemeData(); + const b = TStepperThemeData(controlSize: 40, foregroundColor: Colors.black); + final theme = a + .lerp(b, 0.5) + .lerp( + const TStepperThemeData( + controlSize: 48, + foregroundColor: Colors.white, + ), + 0.5, + ); + await tester.pumpWidget( + host( + DefaultTextStyle( + style: const TextStyle(color: Colors.red), + child: IconTheme( + data: const IconThemeData(color: Colors.green), + child: TStepper(value: 3, onChanged: (_) {}), + ), + ), + theme: theme, + ), + ); + expect(size(tester).height, 40); + expect( + input(tester).style.color, + Color.lerp(Color.lerp(Colors.red, Colors.black, 0.5), Colors.white, 0.5), + ); + expect( + tester.widget(find.byIcon(TIcons.plus)).color, + Color.lerp( + Color.lerp(Colors.green, Colors.black, 0.5), + Colors.white, + 0.5, + ), + ); + }); + + testWidgets('AnimatedTheme renders valid endpoint and midpoint geometry', ( + tester, + ) async { + Widget scene(TStepperThemeData theme) => MaterialApp( + themeAnimationDuration: const Duration(milliseconds: 200), + themeAnimationCurve: Curves.linear, + theme: TThemeBuilder.light( + TThemeData.defaultData(), + ).mergeExtension(theme), + home: Scaffold(body: TStepper(value: 3, onChanged: (_) {})), + ); + await tester.pumpWidget(scene(const TStepperThemeData())); + expect(size(tester).height, 24); + await tester.pumpWidget(scene(const TStepperThemeData(controlSize: 40))); + expect(size(tester).height, 24); + await tester.pump(const Duration(milliseconds: 100)); + expect(size(tester).height, 32); + await tester.pumpAndSettle(); + expect(size(tester).height, 40); + expect(tester.takeException(), isNull); + }); +} diff --git a/tdesign-component/test/tool/generate_example_code_test.dart b/tdesign-component/test/tool/generate_example_code_test.dart index 7d190cf8a..8abebab3b 100644 --- a/tdesign-component/test/tool/generate_example_code_test.dart +++ b/tdesign-component/test/tool/generate_example_code_test.dart @@ -69,6 +69,42 @@ void demo() {} expect(createGenerator().run(check: true).isUpToDate, isTrue); }); + test('standalone widget includes imports and only its associated State', () { + writeSource('stateful', ''' +import 'package:flutter/material.dart'; +import '../annotation/example_code.dart'; + +@ExampleCode(group: 'counter') +class Counter extends StatefulWidget { + const Counter({super.key}); + @override + State createState() => _CounterState(); +} +class _CounterState extends State { + int value = 3; + @override + Widget build(BuildContext context) => TextButton( + onPressed: () => setState(() => value++), + child: Text(value.toString()), + ); +} +class _OtherState extends State {} +'''); + createGenerator().run(); + final snippet = File( + '${outputDirectory.path}/counter.Counter.txt', + ).readAsStringSync(); + expect(snippet, startsWith("import 'package:flutter/material.dart';")); + expect(snippet, contains('class Counter extends StatefulWidget')); + expect(snippet, contains('class _CounterState extends State')); + expect(snippet, contains('int value = 3;')); + expect(snippet, contains('setState(() => value++)')); + expect(snippet, isNot(contains('_OtherState'))); + expect(snippet, isNot(contains('example_code.dart'))); + expect(snippet, isNot(contains('@ExampleCode'))); + expect(createGenerator().run(check: true).isUpToDate, isTrue); + }); + test('verbose mode reports changes and writes files correctly', () { writeSource('examples', ''' @ExampleCode(group: 'button') diff --git a/tdesign-component/tool/generate_example_code.dart b/tdesign-component/tool/generate_example_code.dart index 2d8f29277..e45af5c2d 100644 --- a/tdesign-component/tool/generate_example_code.dart +++ b/tdesign-component/tool/generate_example_code.dart @@ -126,11 +126,13 @@ class _ExampleCodeCollector extends RecursiveAstVisitor { late File _file; late String _source; + late CompilationUnit _unit; void collect(File file) { _file = file; _source = file.readAsStringSync(); - parseString(content: _source, path: file.path).unit.accept(this); + _unit = parseString(content: _source, path: file.path).unit; + _unit.accept(this); } void throwIfInvalid() { @@ -139,6 +141,12 @@ class _ExampleCodeCollector extends RecursiveAstVisitor { } } + @override + void visitClassDeclaration(ClassDeclaration node) { + _collect(node, node.name.lexeme); + super.visitClassDeclaration(node); + } + @override void visitFunctionDeclaration(FunctionDeclaration node) { _collect(node, node.name.lexeme); @@ -170,13 +178,32 @@ class _ExampleCodeCollector extends RecursiveAstVisitor { } if (group == null || !_groupPattern.hasMatch(group)) { _errors.add( - '${_file.path}: $methodName must declare a literal, non-empty ' - '$_annotationName group containing only letters, digits, "_" or "-".'); + '${_file.path}: $methodName must declare a literal, non-empty ' + '$_annotationName group containing only letters, digits, "_" or "-".', + ); return; } final fileName = '$group.$methodName.txt'; - final source = _sourceWithoutMarker(node, annotation); + var source = _sourceWithoutMarker(node, annotation); + if (node is ClassDeclaration) { + final imports = _unit.directives.whereType().where( + (directive) => + !(directive.uri.stringValue?.endsWith('example_code.dart') ?? + false), + ); + final states = _unit.declarations.whereType().where( + (declaration) => + declaration.extendsClause?.superclass.toSource() == + 'State<${node.name.lexeme}>', + ); + source = [ + if (imports.isNotEmpty) + imports.map((item) => item.toSource()).join('\n'), + source, + for (final state in states) _source.substring(state.offset, state.end), + ].join('\n\n'); + } if (outputs.containsKey(fileName)) { _errors.add('${_file.path}: duplicate generated snippet $fileName.'); return; diff --git a/tdesign-component/tool/run_component_regression.dart b/tdesign-component/tool/run_component_regression.dart index 714378194..74edb6233 100644 --- a/tdesign-component/tool/run_component_regression.dart +++ b/tdesign-component/tool/run_component_regression.dart @@ -81,6 +81,7 @@ const componentTestSuites = [ ]), ComponentTestSuite('stepper', [ 'test/components/stepper/t_stepper_test.dart', + 'test/components/stepper/t_stepper_contract_test.dart', ]), ComponentTestSuite('upload', ['test/components/upload/t_upload_test.dart']), ComponentTestSuite('form', ['test/components/form/t_form_test.dart']), diff --git a/tdesign-component/tool/run_visual_regression.dart b/tdesign-component/tool/run_visual_regression.dart index f483ef168..f003ac8d9 100644 --- a/tdesign-component/tool/run_visual_regression.dart +++ b/tdesign-component/tool/run_visual_regression.dart @@ -128,9 +128,12 @@ const visualTestSuites = [ ), VisualTestSuite( 'stepper', - 'Stepper Demo', + 'Stepper Demo and component', workingDirectory: 'example', - testFiles: ['test/stepper_demo_golden_test.dart'], + testFiles: [ + 'test/stepper_demo_golden_test.dart', + '../test/components/stepper/t_stepper_golden_test.dart', + ], ), VisualTestSuite( 'textarea', From 0c5f3a0a6db60eb5a7cde8ca35fbe10d4bb835ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=BF=20Cai?= Date: Wed, 9 Sep 2026 02:16:34 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix(example):=20=E5=88=87=E6=8D=A2=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E6=A8=A1=E5=BC=8F=E6=97=B6=E4=BF=9D=E7=95=99=E7=A4=BA?= =?UTF-8?q?=E4=BE=8B=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- specs/028-stepper-demo-alignment/acceptance.md | 8 +++++--- specs/028-stepper-demo-alignment/plan.md | 2 +- specs/028-stepper-demo-alignment/spec.md | 2 +- specs/028-stepper-demo-alignment/tasks.md | 5 +++-- .../example/lib/base/example_widget.dart | 15 +++++++-------- .../example/test/stepper_demo_test.dart | 8 ++++++++ 6 files changed, 25 insertions(+), 15 deletions(-) diff --git a/specs/028-stepper-demo-alignment/acceptance.md b/specs/028-stepper-demo-alignment/acceptance.md index 703a3585d..7357e3cf6 100644 --- a/specs/028-stepper-demo-alignment/acceptance.md +++ b/specs/028-stepper-demo-alignment/acceptance.md @@ -19,6 +19,8 @@ - 四个生产文件合计行覆盖率:`330/335 = 98.51%`,组件测试全部通过。 - 行为覆盖:两端边界草稿、父组件接受/拒绝、非法草稿、即时按钮边界更新;主题双向插值、端点、实例尺寸、继承主题、TD token、copyWith、嵌套插值及 AnimatedTheme。 - 实际打开五个代码面板,验证显示内容与生成资产一致;将五份生成资产原样写为独立 Dart 文件,在最小宿主编译并操作全部十个实例,1 项测试通过。 +- iPhone 16 / iOS 18.2 模拟器运行当前提交:实际点击基础、边界、三种样式和三种尺寸实例;从 0 输入合法草稿后点击减号得到 4,从 999 输入 995 后点击加号得到 996;禁用实例保持 0 且两侧按钮不可用。明暗主题切换后已修改值保持。 +- 手机验收发现开启顶部代码模式会把已操作值重置。根因是 `CodeWrapper` 在显示遮罩时临时插入 `Stack`,改变 StatefulWidget 父节点结构。修复为始终保留同一 `Stack` 子树;再次上机确认基础值 3 → 4 后,开启代码模式、打开并关闭代码面板、切换主题,值均保持 4。双 SDK Demo 回归覆盖同一路径。 - 示例生成器 `--check` 通过;Stepper API 文档从源码重新生成。 - 新增组件契约测试、生成器测试和四张视觉回归的 CI 入口登记;GitHub/CNB 工具入口同步。 @@ -33,6 +35,6 @@ ## 验证边界与交付 -- 第二套本地 SDK 是 3.47.0。此前 PR 远端 latest 为 3.47.2,本次未提交或推送,不能把旧 CI 结果作为本次修复的通过证据;实际 latest 仍需远端验证。 -- Android/iOS 真机键盘、IME 和系统字体未验证,Linux Golden 不证明这些路径。 -- 公开签名、枚举和默认值保持兼容,行为变化属于既有契约修复。后续推送时应将 PR 标题和描述调整为修复范围,并记录用户可感知的草稿边界与主题动画修复。 +- 第二套本地 SDK 是 3.47.0。首次修复已推送到 `36620b81`;手机验收后续修复仍需推送并等待远端 actual latest 与新 head 的 CNB review,不能沿用旧 head 的结果。 +- iOS 18.2 模拟器已验证实际点击、文本输入、明暗主题和代码面板;Android/iOS 真机 IME 与系统字体仍未验证,Linux Golden 不证明这些路径。 +- 公开签名、枚举和默认值保持兼容,行为变化属于既有契约修复,无迁移要求。 diff --git a/specs/028-stepper-demo-alignment/plan.md b/specs/028-stepper-demo-alignment/plan.md index a362ed067..08811978e 100644 --- a/specs/028-stepper-demo-alignment/plan.md +++ b/specs/028-stepper-demo-alignment/plan.md @@ -4,5 +4,5 @@ 2. 将运行示例提取为独立 Widget;生成器提取 Widget、必要的直接关联 State 和导入,面板显式绑定类名。 3. 按 Figma 去掉 99、修正禁用初值和容器布局;保持现有尺寸和公开 API。 4. 统一草稿与按钮边界判断;主题插值保留端点配置,在内部样式解析处使用真实上下文默认值。 -5. 补组件、完整 Demo、代码面板及生成器回归;验证 95% 生产覆盖率和双 SDK 严格 analyze。 +5. 补组件、完整 Demo、代码面板及生成器回归;代码模式保持运行示例子树稳定;验证 95% 生产覆盖率和双 SDK 严格 analyze。 6. Flutter 3.32 Linux 更新并立即复跑明暗 Golden,记录实际差异与未覆盖项。 diff --git a/specs/028-stepper-demo-alignment/spec.md b/specs/028-stepper-demo-alignment/spec.md index ee5927d44..4a69d661b 100644 --- a/specs/028-stepper-demo-alignment/spec.md +++ b/specs/028-stepper-demo-alignment/spec.md @@ -15,7 +15,7 @@ - Demo 保持三个分组、五个代码入口,共十个步进器;边界只展示 0 / 999,禁用值为 0。基础与禁用左对齐,各块使用完整宽度、组件容器底色和 16px 内边距。 - 最小/最大状态分别由受控值等于边界表达,禁用由空 callback 表达。 -- 所有可交互实例由各自 StatefulWidget 示例持有状态,主题切换和页面重建不重置编辑后的值。 +- 所有可交互实例由各自 StatefulWidget 示例持有状态,主题切换、代码模式切换和页面重建不重置编辑后的值。 - 五个面板展示实际运行的示例 Widget、对应 State 和依赖导入;页面壳不进入片段。生成器沿用 ExampleCode 注解,支持独立 Widget 及同文件直接关联 State 的提取,不添加示例框架参数。 - 编辑期间按钮启停和步进运算使用同一个有效草稿值;合法草稿即使从边界开始编辑,也可向两个方向步进。父组件仍为唯一提交值源,拒绝请求时回退,单次操作最多通知一次。 - Theme 双侧 null 保持继承;单侧 null 按组件当前生效的尺寸、Flutter 显式主题和 TD token 解析后插值,不当作 0 或透明色。插值端点保持原始配置,动态主题和实例尺寸覆盖路径均须验证。 diff --git a/specs/028-stepper-demo-alignment/tasks.md b/specs/028-stepper-demo-alignment/tasks.md index 11fd23065..e132e1eb1 100644 --- a/specs/028-stepper-demo-alignment/tasks.md +++ b/specs/028-stepper-demo-alignment/tasks.md @@ -3,9 +3,10 @@ - [x] 固定 #1064 head、Figma 节点和小程序参考版本,完成 API Review。 - [x] 修正边界数量、禁用初值、容器和对齐方式。 - [x] 五份生成片段包含独立 Widget、必要 State 和导入;验证实际代码面板及最小宿主编译、交互。 +- [x] 在 iPhone 16 / iOS 18.2 模拟器完成点击验收,修复开启代码模式会重置运行示例状态的问题并补回归。 - [x] 统一草稿步进与按钮边界判断,覆盖父组件接受和拒绝请求。 - [x] 修正 nullable Theme 插值,覆盖尺寸、继承、token、copyWith、嵌套插值和 AnimatedTheme。 - [x] 完成本地 Flutter 3.32.0 / 3.47.0 回归、严格 analyze、98.51% 生产覆盖率及 CI 工具自测。 - [x] 检查并更新 Linux Demo 和组件明暗 Golden;四张图精确复跑通过,登记视觉回归入口。 -- [ ] 提交、推送并同步 PR 标题与描述;本次仅完成本地修复。 -- [ ] 推送后验证远端实际 latest;Android/iOS 真机键盘、IME 和系统字体仍待验证。 +- [x] 提交、推送并同步 GitHub/CNB PR 标题与描述;触发 CNB 定向 review。 +- [ ] 推送手机验收修复后验证远端实际 latest 并重新触发 CNB review;Android/iOS 真机键盘、IME 和系统字体仍待验证。 diff --git a/tdesign-component/example/lib/base/example_widget.dart b/tdesign-component/example/lib/base/example_widget.dart index 0b360eba8..5914fbcb8 100644 --- a/tdesign-component/example/lib/base/example_widget.dart +++ b/tdesign-component/example/lib/base/example_widget.dart @@ -732,10 +732,11 @@ class _CodeWrapperState extends State { if (widget.isCenter) { child = Center(child: child); } - if (apiVisible) { - child = Stack( - children: [ - child, + return Stack( + fit: StackFit.passthrough, + children: [ + child, + if (apiVisible) Positioned( top: 0, bottom: 0, @@ -750,10 +751,8 @@ class _CodeWrapperState extends State { ), ), ), - ], - ); - } - return child; + ], + ); } String _getCodeAssetsPath() { diff --git a/tdesign-component/example/test/stepper_demo_test.dart b/tdesign-component/example/test/stepper_demo_test.dart index ebea72b60..396063e17 100644 --- a/tdesign-component/example/test/stepper_demo_test.dart +++ b/tdesign-component/example/test/stepper_demo_test.dart @@ -159,9 +159,16 @@ void main() { ), ); await tester.pumpAndSettle(); + final base = find.byKey(const ValueKey('stepper-base')); + await tester.tap( + find.descendant(of: base, matching: find.bySemanticsLabel('增加')), + ); + await tester.pump(); + expect(tester.widget(base).value, 4); await tester.tap(find.byIcon(TIcons.code)); await tester.pumpAndSettle(); expect(find.text('code'), findsNWidgets(5)); + expect(tester.widget(base).value, 4); const names = [ 'StepperBaseExample', 'StepperBoundsExample', @@ -180,6 +187,7 @@ void main() { Navigator.of(tester.element(find.byType(Markdown))).pop(); await tester.pumpAndSettle(); } + expect(tester.widget(base).value, 4); await disposeDemoPage(tester); }, tags: 'demo', From 0da91a538bf821c6b05a7d98fc54efc8d257fd5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=BF=20Cai?= Date: Wed, 9 Sep 2026 02:27:57 +0800 Subject: [PATCH 4/4] =?UTF-8?q?docs(stepper):=20=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E6=89=8B=E6=9C=BA=E4=B8=8E=E5=90=88=E5=B9=B6=E5=90=8E=E9=AA=8C?= =?UTF-8?q?=E6=94=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- specs/028-stepper-demo-alignment/acceptance.md | 5 +++-- specs/028-stepper-demo-alignment/tasks.md | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/specs/028-stepper-demo-alignment/acceptance.md b/specs/028-stepper-demo-alignment/acceptance.md index 7357e3cf6..69e9451eb 100644 --- a/specs/028-stepper-demo-alignment/acceptance.md +++ b/specs/028-stepper-demo-alignment/acceptance.md @@ -13,7 +13,7 @@ | --- | --- | --- | | 组件回归 | 39 项通过 | 39 项通过 | | 完整 Demo 回归 | 7 项通过 | 7 项通过 | -| 生成器及回归工具自测 | 16 项通过 | 16 项通过 | +| 生成器及回归工具自测 | 18 项通过 | 18 项通过 | | 严格 flutter analyze | 0 error / 0 warning | 0 error / 0 warning | - 四个生产文件合计行覆盖率:`330/335 = 98.51%`,组件测试全部通过。 @@ -23,6 +23,7 @@ - 手机验收发现开启顶部代码模式会把已操作值重置。根因是 `CodeWrapper` 在显示遮罩时临时插入 `Stack`,改变 StatefulWidget 父节点结构。修复为始终保留同一 `Stack` 子树;再次上机确认基础值 3 → 4 后,开启代码模式、打开并关闭代码面板、切换主题,值均保持 4。双 SDK Demo 回归覆盖同一路径。 - 示例生成器 `--check` 通过;Stepper API 文档从源码重新生成。 - 新增组件契约测试、生成器测试和四张视觉回归的 CI 入口登记;GitHub/CNB 工具入口同步。 +- 合并 `origin/develop@335b30bc` 后,用最终合并提交重新构建 iOS 应用并复跑:基础 3 → 4、最小值 0 → 1、最大值 999 → 998,三种样式与三种尺寸均各自 3 → 4;打开和关闭代码面板、查看 API 文档、切换主题后上述值全部保留。 ## Linux Golden @@ -35,6 +36,6 @@ ## 验证边界与交付 -- 第二套本地 SDK 是 3.47.0。首次修复已推送到 `36620b81`;手机验收后续修复仍需推送并等待远端 actual latest 与新 head 的 CNB review,不能沿用旧 head 的结果。 +- 第二套本地 SDK 是 3.47.0。首次修复已推送到 `36620b81`;手机验收修复和最新 `develop` 合并已在本地完成,推送后须等待远端 actual latest 与新 head 的 CNB review,不能沿用旧 head 的结果。 - iOS 18.2 模拟器已验证实际点击、文本输入、明暗主题和代码面板;Android/iOS 真机 IME 与系统字体仍未验证,Linux Golden 不证明这些路径。 - 公开签名、枚举和默认值保持兼容,行为变化属于既有契约修复,无迁移要求。 diff --git a/specs/028-stepper-demo-alignment/tasks.md b/specs/028-stepper-demo-alignment/tasks.md index e132e1eb1..fed45b1d4 100644 --- a/specs/028-stepper-demo-alignment/tasks.md +++ b/specs/028-stepper-demo-alignment/tasks.md @@ -6,7 +6,7 @@ - [x] 在 iPhone 16 / iOS 18.2 模拟器完成点击验收,修复开启代码模式会重置运行示例状态的问题并补回归。 - [x] 统一草稿步进与按钮边界判断,覆盖父组件接受和拒绝请求。 - [x] 修正 nullable Theme 插值,覆盖尺寸、继承、token、copyWith、嵌套插值和 AnimatedTheme。 -- [x] 完成本地 Flutter 3.32.0 / 3.47.0 回归、严格 analyze、98.51% 生产覆盖率及 CI 工具自测。 +- [x] 完成本地 Flutter 3.32.0 / 3.47.0 回归、严格 analyze、98.51% 生产覆盖率及 CI 工具自测;合并最新 `develop` 后再次通过。 - [x] 检查并更新 Linux Demo 和组件明暗 Golden;四张图精确复跑通过,登记视觉回归入口。 - [x] 提交、推送并同步 GitHub/CNB PR 标题与描述;触发 CNB 定向 review。 - [ ] 推送手机验收修复后验证远端实际 latest 并重新触发 CNB review;Android/iOS 真机键盘、IME 和系统字体仍待验证。