widgetbook / widgetbook

Widgetbook is the custom widget library and collaboration platform for Flutter frontend teams.
https://widgetbook.io
694 stars 167 forks source link

Can not select knob option that is a list with 2 items #1179

Open jtdLab opened 1 month ago

jtdLab commented 1 month ago

Description Can not select knob list options with 2 items.

Steps To Reproduce

1.

 final favoriteFinishes = context.knobs.list(
    label: 'Favorite Finishes',
    options: [
      const <int>[],
      const [16],
      const [16, 32],
      const [16, 32, 40],
    ],
    initialOption: const [16, 32, 40],
  );
  1. Select the option with length 2.

Expected Behavior Select it and update the widget.

Additional Context With 0,1 and 3 items it works

Error Logs:

╞═══════════════════════════════════════════════════════════
The following IndexError was thrown building:
RangeError (index): Index out of range: index should be less than 1: 1

When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 296:3       throw_
dart-sdk/lib/_internal/js_dev_runtime/private/js_array.dart 592:7                 _get]
packages/widgetbook/src/fields/field_codec.dart 42:42                             <fn>
dart-sdk/lib/internal/iterable.dart 425:31                                        elementAt
dart-sdk/lib/internal/iterable.dart 354:26                                        moveNext
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 918:20  next
dart-sdk/lib/collection/maps.dart 89:14                                           addEntries
dart-sdk/lib/core/map.dart 210:17                                                 <fn>
dart-sdk/lib/core/map.dart 210:35                                                 fromEntries
packages/widgetbook/src/fields/field_codec.dart 38:12
decodeQueryGroup
packages/widgetbook/src/fields/field.dart 61:33                                   build
packages/widgetbook/src/knobs/knob.dart 70:29                                     <fn>
dart-sdk/lib/internal/iterable.dart 425:31                                        elementAt
dart-sdk/lib/internal/iterable.dart 354:26                                        moveNext
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 918:20  next
dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 483:14                of
dart-sdk/lib/internal/iterable.dart 224:7                                         toList
packages/widgetbook/src/knobs/knob.dart 70:45                                     buildFields
packages/widgetbook/src/layout/responsive_layout.dart 46:28                       <fn>
dart-sdk/lib/internal/iterable.dart 403:20                                        moveNext
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 918:20  next
dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 483:14                of
dart-sdk/lib/core/iterable.dart 497:7                                             toList
packages/widgetbook/src/layout/responsive_layout.dart 46:48                       buildKnobs
packages/widgetbook/src/settings/settings_panel.dart 27:41                        <fn>
packages/flutter/src/widgets/scroll_delegate.dart 490:22                          build
packages/flutter/src/widgets/sliver.dart 831:18                                   [_build]
packages/flutter/src/widgets/sliver.dart 761:67
processElement
dart-sdk/lib/core/iterable.dart 347:29                                            forEach
packages/flutter/src/widgets/sliver.dart 808:18
performRebuild
packages/flutter/src/widgets/framework.dart 5203:7                                rebuild
packages/flutter/src/widgets/framework.dart 2905:18                               buildScope
packages/flutter/src/widgets/binding.dart 1136:9                                  drawFrame
packages/flutter/src/rendering/binding.dart 443:5
[_handlePersistentFrameCallback]
packages/flutter/src/scheduler/binding.dart 1392:7
[_invokeFrameCallback]
packages/flutter/src/scheduler/binding.dart 1313:9
handleDrawFrame
packages/flutter/src/scheduler/binding.dart 1171:5
[_handleDrawFrame]
lib/_engine/engine/platform_dispatcher.dart 1404:5                                invoke
lib/_engine/engine/platform_dispatcher.dart 307:5
invokeOnDrawFrame
lib/_engine/engine/initialization.dart 187:36                                     <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 426:37
_checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 431:39  dcall
══════════════════════════════════════════════════════════════════════════════════════════════
══════
Another exception was thrown: RangeError (index): Index out of range: index should be less
than 1: 1
Another exception was thrown: RangeError (index): Index out of range: index should be less
than 1: 1
Another exception was thrown: RangeError (index): Index out of range: index should be less
than 1: 1
Another exception was thrown: RangeError (index): Index out of range: index should be less
than 1: 1
Another exception was thrown: RangeError (index): Index out of range: index should be less
than 1: 1
YoussefRaafatNasry commented 1 month ago

Hello @jtdLab 👋

Thanks for reporting this issue! I was able to reproduce it on my side, and it turns out that it's caused by the commas. It happened before with string knobs and was fixed in #817.

As a quick workaround for now, you can change how the knob's value is encoded/decoded as follows. Unfortunately this will affect the label of the dropdown as well.

final favoriteFinishes = context.knobs.list(
  label: 'Favorite Finishes',
  labelBuilder: (value) => value.join('-'),
  initialOption: const [16, 32, 40],
  options: [
    const <int>[],
    const [16],
    const [16, 32],
    const [16, 32, 40],
  ],
);

The proper fix would be to use URL encoding/decoding for knobs' values (similar to what we did with knobs' labels in #1165). This will help prevent the issue from happening with other knobs as well.

Would you like to contribute to Widgetbook by submitting a PR for that fix?

yunweneric commented 3 days ago

Hi @YoussefRaafatNasry

I will like to work on this issue.

YoussefRaafatNasry commented 1 day ago

Great, @yunweneric! Looking forward for the PR 👀

yunweneric commented 1 day ago

Awesome 😎