Reorderable table, row, column, wrap, and sliver list that allow drag and drop of the children. https://pub.dartlang.org/packages/reorderables

Overview

** Kindly submit PR if you encounter issues and please make sure you're using stable channel releases.
** Maintaining open source software ain't easy. If you've commercially used this software, please consider support.

reorderables

pub package Awesome Flutter Buy Me A Coffee

Various reorderable, a.k.a. drag and drop, Flutter widgets, including reorderable table, row, column, wrap, and sliver list, that make their children draggable and reorder them within the widget. Parent widget only need to provide an onReorder function that is invoked with the old and new indexes of child being reordered.

Usage

To use this package, add reorderables as a dependency in your pubspec.yaml file.

dependencies:
  reorderables:

And import the package in your code.

import 'package:reorderables/reorderables.dart';

Examples

This package includes ReorderableSliverList, ReorderableTable, ReorderableWrap, ReorderableRow, and ReorderableColumn, which are reorderable versions of Flutter's SliverList, Table, Wrap, Row, and Column respectively.

ReorderableSliverList

ReorderableSliverList behaves exactly like SliverList, but its children are draggable.

To make a SliverList reorderable, replace it with ReorderableSliverList and replace SliverChildListDelegate/SliverChildBuilderDelegate with ReorderableSliverChildListDelegate/ReorderableSliverChildBuilderDelegate. Do make sure that there's a ScrollController attached to the ScrollView that contains ReorderableSliverList, otherwise an error will be thrown when dragging list items.

class _SliverExampleState extends State<SliverExample> {
  List<Widget> _rows;

  @override
  void initState() {
    super.initState();
    _rows = List<Widget>.generate(50,
        (int index) => Text('This is sliver child $index', textScaleFactor: 2)
    );
  }

  @override
  Widget build(BuildContext context) {
    void _onReorder(int oldIndex, int newIndex) {
      setState(() {
        Widget row = _rows.removeAt(oldIndex);
        _rows.insert(newIndex, row);
      });
    }
    // Make sure there is a scroll controller attached to the scroll view that contains ReorderableSliverList.
    // Otherwise an error will be thrown.
    ScrollController _scrollController = PrimaryScrollController.of(context) ?? ScrollController();

    return CustomScrollView(
      // A ScrollController must be included in CustomScrollView, otherwise
      // ReorderableSliverList wouldn't work
      controller: _scrollController,
      slivers: <Widget>[
        SliverAppBar(
          expandedHeight: 210.0,
          flexibleSpace: FlexibleSpaceBar(
            title: Text('ReorderableSliverList'),
            background: Image.network(
              'https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Yushan'
                '_main_east_peak%2BHuang_Chung_Yu%E9%BB%83%E4%B8%AD%E4%BD%91%2B'
                '9030.png/640px-Yushan_main_east_peak%2BHuang_Chung_Yu%E9%BB%83'
                '%E4%B8%AD%E4%BD%91%2B9030.png'),
          ),
        ),
        ReorderableSliverList(
          delegate: ReorderableSliverChildListDelegate(_rows),
          // or use ReorderableSliverChildBuilderDelegate if needed
//          delegate: ReorderableSliverChildBuilderDelegate(
//            (BuildContext context, int index) => _rows[index],
//            childCount: _rows.length
//          ),
          onReorder: _onReorder,
        )
      ],
    );
  }
}

ReorderableSliverList Demo

ReorderableTable

The difference between table and list is that cells in a table are horizontally aligned, whereas in a list, each item can have children but they are not aligned with children in another item.

Making a row draggable requires cells to be contained in a single widget. This isn't achievable with Table or GridView widget since their children are laid out as cells of widget instead of rows of widget.

class _TableExampleState extends State<TableExample> {
  List<ReorderableTableRow> _itemRows;

  @override
  void initState() {
    super.initState();
    var data = [
      ['Alex', 'D', 'B+', 'AA', ''],
      ['Bob', 'AAAAA+', '', 'B', ''],
      ['Cindy', '', 'To Be Confirmed', '', ''],
      ['Duke', 'C-', '', 'Failed', ''],
      ['Ellenina', 'C', 'B', 'A', 'A'],
      ['Floral', '', 'BBB', 'A', 'A'],
    ];

    Widget _textWithPadding(String text) {
      return Padding(
        padding: EdgeInsets.symmetric(vertical: 4),
        child: Text(text, textScaleFactor: 1.1),
      );
    }

    _itemRows = data.map((row) {
      return ReorderableTableRow(
        //a key must be specified for each row
        key: ObjectKey(row),
        mainAxisSize: MainAxisSize.max,
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          _textWithPadding('${row[0]}'),
          _textWithPadding('${row[1]}'),
          _textWithPadding('${row[2]}'),
          _textWithPadding('${row[3]}'),
//          Text('${row[4]}'),
        ],
      );
    }).toList();
  }

  @override
  Widget build(BuildContext context) {
    var headerRow = ReorderableTableRow(
      mainAxisSize: MainAxisSize.max,
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        Text('Name', textScaleFactor: 1.5),
        Text('Math', textScaleFactor: 1.5),
        Text('Science', textScaleFactor: 1.5),
        Text('Physics', textScaleFactor: 1.5),
        Text('Sports', textScaleFactor: 1.5)
      ]
    );

    void _onReorder(int oldIndex, int newIndex) {
      setState(() {
        ReorderableTableRow row = _itemRows.removeAt(oldIndex);
        _itemRows.insert(newIndex, row);
      });
    }

    return ReorderableTable(
      header: headerRow,
      children: _itemRows,
      onReorder: _onReorder,
    );
  }
}

In a table, cells in each row are aligned on column basis with cells in other rows, whereas cells in a row of a list view don't align with other rows.

ReorderableTable Demo

ReorderableWrap

This widget can also limit the minimum and maximum amount of children in each run, on top of the size-based policy in Wrap's algorithm. See API references for more details. *Since v0.2.5, children of ReorderableWrap don't need to have a key explicitly specified.

class _WrapExampleState extends State<WrapExample> {
  final double _iconSize = 90;
  List<Widget> _tiles;

  @override
  void initState() {
    super.initState();
    _tiles = <Widget>[
      Icon(Icons.filter_1, size: _iconSize),
      Icon(Icons.filter_2, size: _iconSize),
      Icon(Icons.filter_3, size: _iconSize),
      Icon(Icons.filter_4, size: _iconSize),
      Icon(Icons.filter_5, size: _iconSize),
      Icon(Icons.filter_6, size: _iconSize),
      Icon(Icons.filter_7, size: _iconSize),
      Icon(Icons.filter_8, size: _iconSize),
      Icon(Icons.filter_9, size: _iconSize),
    ];
  }

  @override
  Widget build(BuildContext context) {
    void _onReorder(int oldIndex, int newIndex) {
      setState(() {
        Widget row = _tiles.removeAt(oldIndex);
        _tiles.insert(newIndex, row);
      });
    }

    var wrap = ReorderableWrap(
      spacing: 8.0,
      runSpacing: 4.0,
      padding: const EdgeInsets.all(8),
      children: _tiles,
      onReorder: _onReorder,
       onNoReorder: (int index) {
        //this callback is optional
        debugPrint('${DateTime.now().toString().substring(5, 22)} reorder cancelled. index:$index');
      },
      onReorderStarted: (int index) {
        //this callback is optional
        debugPrint('${DateTime.now().toString().substring(5, 22)} reorder started: index:$index');
      }
    );

    var column = Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        wrap,
        ButtonBar(
          alignment: MainAxisAlignment.start,
          children: <Widget>[
            IconButton(
              iconSize: 50,
              icon: Icon(Icons.add_circle),
              color: Colors.deepOrange,
              padding: const EdgeInsets.all(0.0),
              onPressed: () {
                var newTile = Icon(Icons.filter_9_plus, size: _iconSize);
                setState(() {
                  _tiles.add(newTile);
                });
              },
            ),
            IconButton(
              iconSize: 50,
              icon: Icon(Icons.remove_circle),
              color: Colors.teal,
              padding: const EdgeInsets.all(0.0),
              onPressed: () {
                setState(() {
                  _tiles.removeAt(0);
                });
              },
            ),
          ],
        ),
      ],
    );

    return SingleChildScrollView(
      child: column,
    );

  }
}

ReorderableWrap Demo

Nested ReorderableWrap

It is also possible to nest multiple levels of ReorderableWrap. See example/lib/nested_wrap_example.dart for complete example code.

class _NestedWrapExampleState extends State<NestedWrapExample> {
//  List<Widget> _tiles;
  Color _color;
  Color _colorBrighter;

  @override
  void initState() {
    super.initState();
    _color = widget.color ?? Colors.primaries[widget.depth % Colors.primaries.length];
    _colorBrighter = Color.lerp(_color, Colors.white, 0.6);
  }

  @override
  Widget build(BuildContext context) {
    void _onReorder(int oldIndex, int newIndex) {
      setState(() {
        widget._tiles.insert(newIndex, widget._tiles.removeAt(oldIndex));
      });
    }

    var wrap = ReorderableWrap(
      spacing: 8.0,
      runSpacing: 4.0,
      padding: const EdgeInsets.all(8),
      children: widget._tiles,
      onReorder: _onReorder
    );

    var buttonBar = Container(
      color: _colorBrighter,
      child: Row(
        mainAxisSize: MainAxisSize.min,
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          IconButton(
            iconSize: 42,
            icon: Icon(Icons.add_circle),
            color: Colors.deepOrange,
            padding: const EdgeInsets.all(0.0),
            onPressed: () {
              setState(() {
                widget._tiles.add(
                  Card(
                    child: Container(
                      child: Text('${widget.valuePrefix}${widget._tiles.length}', textScaleFactor: 3 / math.sqrt(widget.depth + 1)),
                      padding: EdgeInsets.all((24.0 / math.sqrt(widget.depth + 1)).roundToDouble()),
                    ),
                    color: _colorBrighter,
                    elevation: 3,
                  )
                );
              });
            },
          ),
          IconButton(
            iconSize: 42,
            icon: Icon(Icons.remove_circle),
            color: Colors.teal,
            padding: const EdgeInsets.all(0.0),
            onPressed: () {
              setState(() {
                widget._tiles.removeAt(0);
              });
            },
          ),
          IconButton(
            iconSize: 42,
            icon: Icon(Icons.add_to_photos),
            color: Colors.pink,
            padding: const EdgeInsets.all(0.0),
            onPressed: () {
              setState(() {
                widget._tiles.add(NestedWrapExample(depth: widget.depth + 1, valuePrefix: '${widget.valuePrefix}${widget._tiles.length}.',));
              });
            },
          ),
          Text('Level ${widget.depth} / ${widget.valuePrefix}'),
        ],
      )
    );

    var column = Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        buttonBar,
        wrap,
      ]
    );

    return SingleChildScrollView(
      child: Container(child: column, color: _color,),
    );
  }
}

Nested ReorderableWrap Demo

ReorderableColumn example #1

class _ColumnExample1State extends State<ColumnExample1> {
  List<Widget> _rows;

  @override
  void initState() {
    super.initState();
    _rows = List<Widget>.generate(50,
        (int index) => Text('This is row $index', key: ValueKey(index), textScaleFactor: 1.5)
    );
  }

  @override
  Widget build(BuildContext context) {
    void _onReorder(int oldIndex, int newIndex) {
      setState(() {
        Widget row = _rows.removeAt(oldIndex);
        _rows.insert(newIndex, row);
      });
    }

    return ReorderableColumn(
      header: Text('THIS IS THE HEADER ROW'),
      footer: Text('THIS IS THE FOOTER ROW'),
      crossAxisAlignment: CrossAxisAlignment.start,
      children: _rows,
      onReorder: _onReorder,
    );
  }
}

ReorderableColumn example #1 Demo

ReorderableColumn example #2

class _ColumnExample2State extends State<ColumnExample2> {
  List<Widget> _rows;

  @override
  void initState() {
    super.initState();
    _rows = List<Widget>.generate(10,
        (int index) => Text('This is row $index', key: ValueKey(index), textScaleFactor: 1.5)
    );
  }

  @override
  Widget build(BuildContext context) {
    void _onReorder(int oldIndex, int newIndex) {
      setState(() {
        Widget row = _rows.removeAt(oldIndex);
        _rows.insert(newIndex, row);
      });
    }

    Widget reorderableColumn = IntrinsicWidth(
      child: ReorderableColumn(
        header: Text('List-like view but supports IntrinsicWidth'),
//        crossAxisAlignment: CrossAxisAlignment.start,
        children: _rows,
        onReorder: _onReorder,
      )
    );

    return Transform(
      transform: Matrix4.rotationZ(0),
      alignment: FractionalOffset.topLeft,
      child: Material(
        child: Card(child: reorderableColumn),
        elevation: 6.0,
        color: Colors.transparent,
        borderRadius: BorderRadius.zero,
      ),
    );
  }
}

ReorderableColumn example #2 Demo

ReorderableRow

See exmaple/lib/row_example.dart

ReorderableRow Demo

Issues

I've switched to Flutter channel stable from beta in order avoid compatibility issues. Supporting master or dev channels is not intended as they change frequently. Kindly make sure that you are using stable channel when submitting issues.

Support

If you need commercial support, please reach out to me by sending me message on LinkedIn Hansheng

Otherwise, you can also support me by buying me a coffee or donate me via PayPal. Your support is very much appreciated. :)

Buy Me A Coffee or Donate or Say Thanks!

Comments
  • Can we please get another release?

    Can we please get another release?

    @hanshengchiu as the title states, seeing that you recently merged in null-safety changes, is there any chance that you can please deploy another release to pub.dev, so that folks such as myself can upgrade to null-safety?

    Thanks in advance.

    opened by diegotori 19
  • Leading widget consumes entire tile width. Please use a sized widget.

    Leading widget consumes entire tile width. Please use a sized widget.

    I am creating music player application. In the Queue Songs page I added reorderableSliver list. But whenever I try to drag a list item from it, it throws the blow error. Can you please check this if it is related to control level or did i construct the list in wrong way.

    The error:

    I/flutter (27359): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════ I/flutter (27359): The following assertion was thrown during performLayout(): I/flutter (27359): Leading widget consumes entire tile width. Please use a sized widget. I/flutter (27359): 'package:flutter/src/material/list_tile.dart': I/flutter (27359): Failed assertion: line 1334 pos 7: 'tileWidth != leadingSize.width' I/flutter (27359): I/flutter (27359): Either the assertion indicates an error in the framework itself, or we should provide substantially I/flutter (27359): more information in this error message to help you determine and fix the underlying cause. I/flutter (27359): In either case, please report this assertion by filing a bug on GitHub: I/flutter (27359): https://github.com/flutter/flutter/issues/new?template=BUG.md I/flutter (27359): I/flutter (27359): User-created ancestor of the error-causing widget was: I/flutter (27359): ListTile-[#e87ff] I/flutter (27359): I/flutter (27359): When the exception was thrown, this was the stack: I/flutter (27359): #2 _RenderListTile.performLayout I/flutter (27359): #3 RenderObject.layout I/flutter (27359): #4 RenderPadding.performLayout I/flutter (27359): #5 RenderObject.layout I/flutter (27359): #6 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout I/flutter (27359): #7 RenderObject.layout I/flutter (27359): #8 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout I/flutter (27359): #9 RenderObject.layout I/flutter (27359): #10 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout I/flutter (27359): #11 RenderObject.layout I/flutter (27359): #12 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout I/flutter (27359): #13 RenderObject.layout I/flutter (27359): #14 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout I/flutter (27359): #15 RenderObject.layout I/flutter (27359): #16 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout I/flutter (27359): #17 RenderObject.layout I/flutter (27359): #18 RenderConstrainedBox.performLayout I/flutter (27359): #19 RenderObject.layout I/flutter (27359): #20 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout I/flutter (27359): #21 RenderObject.layout I/flutter (27359): #22 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout I/flutter (27359): #23 RenderObject.layout I/flutter (27359): #24 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout I/flutter (27359): #25 RenderObject.layout I/flutter (27359): #26 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout I/flutter (27359): #27 RenderObject.layout I/flutter (27359): #28 RenderFlex.performLayout I/flutter (27359): #29 RenderObject.layout I/flutter (27359): #30 RenderSliverList.performLayout.advance I/flutter (27359): #31 RenderSliverList.performLayout I/flutter (27359): #32 RenderObject.layout I/flutter (27359): #33 RenderViewportBase.layoutChildSequence I/flutter (27359): #34 RenderViewport._attemptLayout I/flutter (27359): #35 RenderViewport.performLayout I/flutter (27359): #36 RenderObject._layoutWithoutResize I/flutter (27359): #37 PipelineOwner.flushLayout I/flutter (27359): #38 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.drawFrame I/flutter (27359): #39 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame I/flutter (27359): #40 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback I/flutter (27359): #41 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback I/flutter (27359): #42 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame I/flutter (27359): #43 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame I/flutter (27359): #47 _invoke (dart:ui/hooks.dart:238:10) I/flutter (27359): #48 _drawFrame (dart:ui/hooks.dart:196:3) I/flutter (27359): (elided 5 frames from class _AssertionError and package dart:async) I/flutter (27359): I/flutter (27359): The following RenderObject was being processed when the exception was fired: _RenderListTile#e13f0 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE: I/flutter (27359): creator: _ListTile ← MediaQuery ← Padding ← SafeArea ← Semantics ← _PointerListener ← Listener ← I/flutter (27359): _GestureSemantics ← RawGestureDetector ← GestureDetector ← MouseRegion ← InkWell ← ⋯ I/flutter (27359): parentData: offset=Offset(0.0, 0.0) (can use size) I/flutter (27359): constraints: BoxConstraints(w=0.0, h=0.0) I/flutter (27359): size: MISSING I/flutter (27359): This RenderObject had the following descendants (showing up to depth 5): I/flutter (27359): leading: RenderConstrainedBox#7780c NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE I/flutter (27359): child: RenderPositionedBox#c4f06 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE I/flutter (27359): child: RenderSemanticsAnnotations#d3155 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE I/flutter (27359): child: RenderExcludeSemantics#b5a12 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE I/flutter (27359): child: RenderConstrainedBox#48444 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE I/flutter (27359): title: RenderParagraph#b4ae2 NEEDS-LAYOUT NEEDS-PAINT I/flutter (27359): text: TextSpan I/flutter (27359): subtitle: RenderParagraph#98e48 NEEDS-LAYOUT NEEDS-PAINT I/flutter (27359): text: TextSpan I/flutter (27359): ════════════════════════════════════════════════════════════════════════════════════════════════════

    The Code:

    ` return Scaffold( ScrollController _scrollController = PrimaryScrollController.of(context) ?? ScrollController(); final _listTiles = playerUtil.songQueue .map( (song) => ListTile( key: UniqueKey(), title: Text(song.title), subtitle: Text(song.album), isThreeLine: false, leading: SizedBox( width: 40, // can be whatever value you want child: Container( child: Icon(Icons.reorder), alignment: Alignment.center, ), ), ), ) .toList();

      appBar: AppBar(
        title: Text(
          'Queue Songs',
        ),
        // backgroundColor: Colors.transparent,
        elevation: 0,
        leading: IconButton(
          icon: Icon(Icons.arrow_back_ios),
          onPressed: () {
            Navigator.pop(context);
            Navigator.push(
              context,
              MaterialPageRoute(builder: (BuildContext context) {
                return NowPlaying();
              }),
            );
          },
        ),
      ),
      body: CustomScrollView(
        controller: _scrollController,
        slivers: [
          ReorderableSliverList(
            delegate: ReorderableSliverChildListDelegate(_listTiles),
            onReorder: listReorder,
          ),
        ],
      ),
    );
    

    `

    opened by arunkumarsubburaj 11
  • Project breaks for Flutter 1.5.9

    Project breaks for Flutter 1.5.9

    Using the latest flutter version, the library breaks due to flutter changes on Diagnostics related features.

    The error message is:

    Compiler message: file:///Users/brunocalou/Development/flutter/.pub-cache/hosted/pub.dartlang.org/reorderables-0.2.7/lib/src/widgets/reorderable_sliver.dart:76:16: Error: The argument type 'String' can't be assigned to the parameter type 'DiagnosticsNode'.

    • 'DiagnosticsNode' is from 'package:flutter/src/foundation/diagnostics.dart' ('file:///Users/brunocalou/Development/flutter/packages/flutter/lib/src/foundation/diagnostics.dart'). Try changing the type of the parameter, or casting the argument to 'DiagnosticsNode'. context: 'building', ^ file:///Users/brunocalou/Development/flutter/.pub-cache/hosted/pub.dartlang.org/reorderables-0.2.7/lib/src/rendering/tabluar_flex.dart:927:26: Error: The argument type 'String' can't be assigned to the parameter type 'List'.
    • 'List' is from 'dart:core'.
    • 'DiagnosticsNode' is from 'package:flutter/src/foundation/diagnostics.dart' ('file:///Users/brunocalou/Development/flutter/packages/flutter/lib/src/foundation/diagnostics.dart'). Try changing the type of the parameter, or casting the argument to 'List'. overflowHints: debugOverflowHints);

    Flutter doctor output

    Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel master, v1.5.9-pre.258, on Mac OS X 10.14.4 18E226, locale en-BR)

    [✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3) [✓] iOS toolchain - develop for iOS devices (Xcode 10.1) [✓] Android Studio (version 3.3) [✓] IntelliJ IDEA Community Edition (version 2018.3.5) [✓] VS Code (version 1.27.2) [✓] Connected device (1 available)

    opened by brunocalou 9
  • The getter 'width' was called on null

    The getter 'width' was called on null

    Hello, I got this issue when I used ReorderableColumn inside the Stepper widget. Stepper > Step > Form > Column > ReorderableColumn. Whenever I long press the UI for dragging it produces this error:

    flutter: The following assertion was thrown while handling a gesture:
    flutter: ScrollController attached to multiple scroll views.
    flutter: 'package:flutter/src/widgets/scroll_controller.dart':
    flutter: Failed assertion: line 111 pos 12: '_positions.length == 1'
    flutter:
    flutter: Either the assertion indicates an error in the framework itself, or we should provide substantially
    flutter: more information in this error message to help you determine and fix the underlying cause.
    flutter: In either case, please report this assertion by filing a bug on GitHub:
    flutter:   https://github.com/flutter/flutter/issues/new?template=BUG.md
    flutter:
    flutter: When the exception was thrown, this was the stack:
    flutter: #2      ScrollController.position (package:flutter/src/widgets/scroll_controller.dart:111:12)
    flutter: #3      ScrollController.offset (package:flutter/src/widgets/scroll_controller.dart:118:24)
    flutter: #4      _ReorderableFlexContentState._scrollTo (package:reorderables/src/widgets/reorderable_flex.dart:353:51)
    flutter: #5      _ReorderableFlexContentState._wrap.<anonymous closure>.<anonymous closure> (package:reorderables/src/widgets/reorderable_flex.dart:722:11)
    flutter: #6      _DragTargetState.didEnter (package:flutter/src/widgets/drag_target.dart)
    flutter: #7      _DragAvatar.updateDrag.<anonymous closure> (package:flutter/src/widgets/drag_target.dart:658:23)
    flutter: #8      _ListBase&Object&ListMixin.firstWhere (dart:collection/list.dart:137:15)
    flutter: #9      _DragAvatar.updateDrag (package:flutter/src/widgets/drag_target.dart:655:51)
    flutter: #10     new _DragAvatar (package:flutter/src/widgets/drag_target.dart:591:5)
    flutter: #11     _DraggableState._startDrag (package:flutter/src/widgets/drag_target.dart:381:35)
    flutter: #12     LongPressDraggable.createRecognizer.<anonymous closure> (package:flutter/src/widgets/drag_target.dart:319:36)
    flutter: #13     MultiDragGestureRecognizer._startDrag.<anonymous closure> (package:flutter/src/gestures/multidrag.dart:266:52)
    flutter: #14     GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:181:24)
    flutter: #15     MultiDragGestureRecognizer._startDrag (package:flutter/src/gestures/multidrag.dart:266:14)
    flutter: #16     MultiDragGestureRecognizer.acceptGesture.<anonymous closure> (package:flutter/src/gestures/multidrag.dart:256:48)
    flutter: #17     _DelayedPointerState.accepted (package:flutter/src/gestures/multidrag.dart:485:14)
    flutter: #18     MultiDragGestureRecognizer.acceptGesture (package:flutter/src/gestures/multidrag.dart:256:11)
    flutter: #19     GestureArenaManager._resolveInFavorOf (package:flutter/src/gestures/arena.dart:263:12)
    flutter: #20     GestureArenaManager._resolve (package:flutter/src/gestures/arena.dart:222:9)
    flutter: #21     GestureArenaEntry.resolve (package:flutter/src/gestures/arena.dart:52:12)
    flutter: #22     MultiDragPointerState.resolve (package:flutter/src/gestures/multidrag.dart:62:17)
    flutter: #23     _DelayedPointerState._delayPassed (package:flutter/src/gestures/multidrag.dart:471:7)
    flutter: #32     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:382:19)
    flutter: #33     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:416:5)
    flutter: #34     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:171:12)
    flutter: (elided 10 frames from class _AssertionError, package dart:async, and package dart:async-patch)
    flutter:
    flutter: Handler: "onStart"
    flutter: Recognizer:
    flutter:   DelayedMultiDragGestureRecognizer#0bd37
    flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════
    flutter: Another exception was thrown: NoSuchMethodError: The getter 'width' was called on null.
    flutter: Another exception was thrown: NoSuchMethodError: The getter 'width' was called on null.
    
    opened by amitkhairnar44 8
  • ReorderableWrap: adding scroll controller causes exception

    ReorderableWrap: adding scroll controller causes exception

    Hi @hanshengchiu,

    First I need to say that your plugin is amazing and our team love it. Now we face a feature that need some control on the scrollview containing the ReorderableWrap widget.

    Exception log

    The problem is, when we add a scroll controller, we got two exceptions when trying to drag an item.

    ======== Exception caught by gesture library =======================================================
    The following assertion was thrown while routing a pointer event:
    ScrollController not attached to any scroll views.
    'package:flutter/src/widgets/scroll_controller.dart':
    Failed assertion: line 107 pos 12: '_positions.isNotEmpty'
    
    
    Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
    In either case, please report this assertion by filing a bug on GitHub:
      https://github.com/flutter/flutter/issues/new?template=2_bug.md
    
    When the exception was thrown, this was the stack: 
    #2      ScrollController.position (package:flutter/src/widgets/scroll_controller.dart:107:12)
    #3      ScrollController.offset (package:flutter/src/widgets/scroll_controller.dart:115:24)
    #4      _ReorderableWrapContentState._scrollTo (package:reorderables/src/widgets/reorderable_wrap.dart:549:51)
    #5      _ReorderableWrapContentState._wrap.<anonymous closure>._onWillAccept (package:reorderables/src/widgets/reorderable_wrap.dart:1008:9)
    #6      _ReorderableWrapContentState._wrap.<anonymous closure>.<anonymous closure> (package:reorderables/src/widgets/reorderable_wrap.dart:1025:42)
    #7      _DragTargetState.didEnter (package:flutter/src/widgets/drag_target.dart:739:60)
    #8      _DragAvatar.updateDrag.<anonymous closure> (package:flutter/src/widgets/drag_target.dart:895:23)
    #9      ListMixin.firstWhere (dart:collection/list.dart:161:15)
    #10     _DragAvatar.updateDrag (package:flutter/src/widgets/drag_target.dart:890:91)
    #11     _DragAvatar.update (package:flutter/src/widgets/drag_target.dart:840:5)
    #12     MultiDragPointerState._move (package:flutter/src/gestures/multidrag.dart:86:16)
    #13     MultiDragGestureRecognizer._handleEvent (package:flutter/src/gestures/multidrag.dart:259:13)
    #14     PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:94:12)
    #15     PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:139:9)
    #16     _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:539:8)
    #17     PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:137:18)
    #18     PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:123:7)
    #19     GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:439:19)
    #20     GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:419:22)
    #21     RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:322:11)
    #22     GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:374:7)
    #23     GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:338:5)
    #24     GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:296:7)
    #25     GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:279:7)
    #29     _invoke1 (dart:ui/hooks.dart:170:10)
    #30     PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:331:7)
    #31     _dispatchPointerDataPacket (dart:ui/hooks.dart:94:31)
    (elided 5 frames from class _AssertionError and dart:async)
    ====================================================================================================
    
    ======== Exception caught by gesture library =======================================================
    The following assertion was thrown while routing a pointer event:
    'package:flutter/src/widgets/drag_target.dart': Failed assertion: line 753 pos 12: '_candidateAvatars.contains(avatar) || _rejectedAvatars.contains(avatar)': is not true.
    
    
    Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
    In either case, please report this assertion by filing a bug on GitHub:
      https://github.com/flutter/flutter/issues/new?template=2_bug.md
    
    When the exception was thrown, this was the stack: 
    #2      _DragTargetState.didLeave (package:flutter/src/widgets/drag_target.dart:753:12)
    #3      _DragAvatar._leaveAllEntered (package:flutter/src/widgets/drag_target.dart:925:26)
    #4      _DragAvatar.finishDrag (package:flutter/src/widgets/drag_target.dart:936:5)
    #5      _DragAvatar.end (package:flutter/src/widgets/drag_target.dart:848:5)
    #6      MultiDragPointerState._up (package:flutter/src/gestures/multidrag.dart:151:14)
    #7      MultiDragGestureRecognizer._handleEvent (package:flutter/src/gestures/multidrag.dart:263:13)
    #8      PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:94:12)
    #9      PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:139:9)
    #10     _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:539:8)
    #11     PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:137:18)
    #12     PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:123:7)
    #13     GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:439:19)
    #14     GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:419:22)
    #15     RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:322:11)
    #16     GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:374:7)
    #17     GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:338:5)
    #18     GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:296:7)
    #19     GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:279:7)
    #23     _invoke1 (dart:ui/hooks.dart:170:10)
    #24     PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:331:7)
    #25     _dispatchPointerDataPacket (dart:ui/hooks.dart:94:31)
    (elided 5 frames from class _AssertionError and dart:async)
    

    Step to reproduce

    1. flutter create testscroll
    2. copy paste ReorderableWrap exemple to main page
    3. add a scrollController to ReorderableWrap widget

    Flutter doctor

    Doctor summary (to see all details, run flutter doctor -v):
    [✓] Flutter (Channel stable, 2.10.3, on macOS 12.1 21C52 darwin-x64, locale fr-FR)
    [✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
    [✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
    [✓] Chrome - develop for the web
    [✓] Android Studio (version 2020.3)
    [✓] VS Code (version 1.63.2)
    [✓] Connected device (2 available)
    [✓] HTTP Host Availability
    
    opened by GCamanes 7
  • Error while adding library.

    Error while adding library.

    I am getting the below error.

    Version : reorderables: ^0.2.12

    Compiler message:
    ../../../.pub-cache/hosted/pub.dartlang.org/reorderables-0.2.12/lib/src/widgets/reorderable_flex.dart:727:18: Error: The argument type 'Null Function(Key)' can't be assigned to the parameter type 'void Function(Object)'.

    • 'Key' is from 'package:flutter/src/foundation/key.dart' ('../../../flutter-sdk/packages/flutter/lib/src/foundation/key.dart').
    • 'Object' is from 'dart:core'.
      onLeave: (Key leaving) {},
      ^
      ../../../.pub-cache/hosted/pub.dartlang.org/reorderables-0.2.12/lib/src/widgets/reorderable_wrap.dart:951:18: Error: The argument type 'Null Function(int)' can't be assigned to the parameter type 'void Function(Object)'.
    • 'Object' is from 'dart:core'.
      onLeave: (int leaving) {},
      ^
      ../../../.pub-cache/hosted/pub.dartlang.org/reorderables-0.2.12/lib/src/widgets/reorderable_wrap.dart:957:18: Error: The argument type 'Null Function(int)' can't be assigned to the parameter type 'void Function(Object)'.
    • 'Object' is from 'dart:core'.
      onLeave: (int leaving) {},
      ^
      ../../../.pub-cache/hosted/pub.dartlang.org/reorderables-0.2.12/lib/src/widgets/reorderable_sliver.dart:842:18: Error: The argument type 'Null Function(int)' can't be assigned to the parameter type 'void Function(Object)'.
    • 'Object' is from 'dart:core'.
      onLeave: (int leaving) {},
      ^
      Target kernel_snapshot failed: Exception: Errors during snapshot creation: null build failed.

    FAILURE: Build failed with an exception.

    opened by achinverma 7
  • fix: bad type in onLeave

    fix: bad type in onLeave

    Closes https://github.com/hanshengchiu/reorderables/issues/49

    Note these changes are backwards compatible. Backwards compatibility was tested against the stable branch.

    opened by larssn 7
  • fix: missing dragAnchorStrategy,revert to dragAnchor.

    fix: missing dragAnchorStrategy,revert to dragAnchor.

    Hello, I noticed that LongPressDraggable has no dragAnchorStrategy, and I reverted it to dragAnchor. This bug made version 0.4.2 can not work normally..

    opened by ZakAnun 6
  • Support drag and drop with nested lists

    Support drag and drop with nested lists

    There may be a way to do this I'm overlooking, but whenever I nest wraps inside warps (or lists) and attempt to drag and drop the copying function seems to throw duplicate global key errors when I pick up the object. The alternative is a sub-list that doesn't save state which isn't ideal. I've tried some ways around this but it looks like the uuid library I'm using is possibly duplicating values or there's something in the way the copy function works that the tree has duplicate keys when moving the items.

    So in other words I have a list of tiles with sub-lists, whenever I try to move them it throws an exception.

    opened by psycry 6
  • Ft: add scroll phyiscs to SingleChildScrollView in ReorderableWrap

    Ft: add scroll phyiscs to SingleChildScrollView in ReorderableWrap

    Use case: When using the ReorderableWrap widget there was some ClampingScrollPhysics visible when testing on an Android device, even though the wrap was not scrollable. Hence it would be nice to adjust the scroll physics of the SingleChildScrollView in which the wrappedChildren are placed.

    Love to get any feedback. @hanshengchiu

    opened by pcvdheuvel 4
  • ReorderableWrap  cannot move any other indexed item to index 0. All other operations work.

    ReorderableWrap cannot move any other indexed item to index 0. All other operations work.

    In a reorderable wrap. No element further down the list can be placed at index 0. They come upto index 1 and not any further.

    If you try moving items from top to any place at bottom, it works absolutely fine. But cannot move any item from botttom to absolute top.

    opened by srihariash999 4
  • Add support for drag handles (only allow drag on certain parts of child widget)

    Add support for drag handles (only allow drag on certain parts of child widget)

    It would be great if it was possible to allow drag only on a certain parts of the widget and not on all of it. Just like the ReorderableDragStartListener works for flutters own ReorderableListView.

    Currently when using a ReorderableColumn, it makes the whole widget dragable, which is a huge deal breaker, when it's used in a ListView. Because when I also want instant dragability (setting needsLongPressDraggable = false) I can't scroll the list view anymore (as my scroll movement would reorder widgets instead of scrolling).

    opened by derteufelqwe 1
  • Q: How to define min/maxMainAxisCount per selected rows?

    Q: How to define min/maxMainAxisCount per selected rows?

    How to define min/maxMainAxisCount per selected rows? E.g. I would like to keep max 1 widget in the row1 while the rest of rows should have e.g. up to 5 widgets.

    opened by maciejpos 0
  • Expanded children alignment in ReorderableWrap

    Expanded children alignment in ReorderableWrap

    Hi Follks, Is it possible to expand/spread equally the children to use entire available width as depicted below (to achieve the same result as via GridView.extent)?

    image

        var wrap = ReorderableWrap( // based on original demo source code
          spacing: 8.0,
          runSpacing: 4.0,
          padding: const EdgeInsets.all(8),
          children: _tiles,
          onReorder: _onReorder,
          onNoReorder: (int index) {
            //this callback is optional
            debugPrint('${DateTime.now().toString().substring(5, 22)} reorder cancelled. index:$index');
          },
          onReorderStarted: (int index) {
            //this callback is optional
            debugPrint('${DateTime.now().toString().substring(5, 22)} reorder started: index:$index');
          }
        );
    
        Widget wrapGridView = GridView.extent( // this place children as expected however it's of course not reorderable...
          crossAxisSpacing: 8,
          mainAxisSpacing: 4,
          maxCrossAxisExtent: 160,
          shrinkWrap: true,
          children: _tiles,
        );
    
    
    opened by maciejpos 0
  • How to create custom widget

    How to create custom widget

    Hi,

    I'm currently using this widget: https://pub.dev/packages/flutter_treeview

    And I wish to add the possibility to move nodes, ie. change the order, change the parent etc. So, do you think I can do such with your library, so mixing your library and the treeview library? (Or I must recreate a complete new one).

    If yes, can you provides some instructions?

    Thanks

    opened by vd3d 0
  • PrimaryScrollController.of() was called with a context that does not contain a PrimaryScrollController widget thrown after flutter upgrade

    PrimaryScrollController.of() was called with a context that does not contain a PrimaryScrollController widget thrown after flutter upgrade

    Hi, I've just upgraded to Flutter 3.6.0-4.0.pre.2 • channel master After upgrade I get this message: I/flutter ( 8048): _ReorderableFlexContent(dirty, dependencies: [PrimaryScrollController], state: I/flutter ( 8048): _ReorderableFlexContentState#46973(tickers: tracking 2 tickers)) I/flutter ( 8048): I/flutter ( 8048): The relevant error-causing widget was: I/flutter ( 8048): _ReorderableFlexContent I/flutter ( 8048): _ReorderableFlexContent:file:///C:/Users/oreznik/AppData/Local/Pub/Cache/hosted/pub.dev/reorderables-0.5.1/lib/src/widgets/reorderable_flex.dart:139:16 I/flutter ( 8048): I/flutter ( 8048): When the exception was thrown, this was the stack: I/flutter ( 8048): #0 PrimaryScrollController.of.<anonymous closure> (package:flutter/src/widgets/primary_scroll_controller.dart:158:9) I/flutter ( 8048): #1 PrimaryScrollController.of (package:flutter/src/widgets/primary_scroll_controller.dart:170:6) I/flutter ( 8048): #2 _ReorderableFlexContentState.build (package:reorderables/src/widgets/reorderable_flex.dart:885:33)

    I was using reorderables: ^0.5.1 and ^0.5.0 flutter doctor is fine This is my code:

    final ScrollController reorderScrollController = ScrollController(); List<Widget> _row=[....]; @override Widget build(BuildContext context) { return ReorderableColumn( children: _rows, onReorder: _onReorder, //Error is not changed if I add this parameter scrollController: reorderScrollController , ); }

    opened by Orlyga01 1
Owner
Hansheng
Consultant for all things tech - AI, ML, Cloud, BigData, Mobile App, and more
Hansheng
scroll to index with fixed/variable row height inside Flutter scrollable widget

scroll-to-index This package provides the scroll to index mechanism for fixed/variable row height for Flutter scrollable widget. Getting Started In th

Quire 415 Jan 6, 2023
Easily make Flutter apps responsive. Automatically adapt UI to different screen sizes. Responsiveness made simple. Demo: https://gallery.codelessly.com/flutterwebsites/minimal/

Responsive Framework Responsiveness made simple Responsive Framework adapts your UI to different screen sizes automatically. Create your UI once and h

Codelessly 931 Dec 25, 2022
A Flutter package that builds a list view and notifies when the widgets are on screen.

inview_notifier_list A Flutter package that builds a ListView or CustomScrollView and notifies when the widgets are on screen within a provided area.

Vamsi Krishna 511 Dec 21, 2022
Flutter plugin that allows you to showcase your features on iOS and Android. 👌🔝🎉

ShowCaseView A Flutter package allows you to Showcase/Highlight your widgets step by step. It is inspired from Fluttery's Flutter challange. Preview I

Simform Solutions 1.1k Jan 7, 2023
Compare your design and current flutter layout.

pixel_perfect Put a semi-transparent image with the design over the top of the developed layout. It helps you to compare original design and current p

Kherel 45 Oct 24, 2022
A flutter plugin for bluebooth ble device connect and control.

flutter_blue_elves A flutter plugin witch includes platform-specific implementation code for Android and/or iOS to connect and control bluetooth ble d

PineappleOilPrince 29 Dec 30, 2022
🎥 Movie app which is developed using flutter and powered by tmdb.

Fluttery Filmy ?? Movie app which is developed using flutter and powered by tmdb. Preview Screenshot Listing Screen Detail Screen What's next? Movies

Bhavik Makwana 197 Dec 28, 2022
This library allows you to create editable tables and spreadsheets with ease, either by providing initial row and column count to display an empty table or use it with predefined rows and column data sets.

Editable ⚡️ A highly customizable, editable table package for Flutter projects. Specs This package allows you to create editable tables and spreadshee

Godwin Asuquo 94 Dec 7, 2022
Easily add staggered animations to your ListView, GridView, Column and Row children.

Flutter Staggered Animations Easily add staggered animations to your ListView, GridView, Column and Row children as shown in Material Design guideline

null 1.2k Jan 6, 2023
Pub Release is a package to assist in publishing dart/flutter packages to pub.dev.

description Pub Release is a package that automates publishing dart/flutter packages to pub.dev. README Pub Release is a package that automates publis

Noojee I.T. Pty Ltd 16 Oct 13, 2022
Flutter Image add drag sort, Image add drag sort, support click event, delete, add, long press drag sort.

flutter_image_add_drag_sort Flutter Image add drag sort, Image add drag sort, support click event, delete, add, long press drag sort, support video fi

null 5 Jun 23, 2020
Sliver bar chart - A package that supports Bar Chart in a Flutter Sliver

Sliver bar chart - A package that supports Bar Chart in a Flutter Sliver. This Package allows us to add Bar Chart in Sliver and sets a Bar Chart as a Header on Slivers Scroll.

MindInventory 19 Oct 11, 2022
Build basic Flutter layouts and widgets with the help of Row, Column, Stack, Expanded, Container, ListView, and GridView in Flutter.

Build basic Flutter layouts and widgets with the help of Row, Column, Stack, Expanded, Container, ListView, and GridView in Flutter.

Johannes Milke 28 Mar 30, 2022
The FlexGrid control provides a powerful and quickly way to display data in a tabular format. It is including that frozened column/row,loading more, high performance and better experience in TabBarView/PageView.

flex_grid Language: English| 中文简体 The FlexGrid control provides a powerful and quickly way to display data in a tabular format. It is including that f

FlutterCandies 39 Nov 8, 2022
A flutter plugin for improved row and column widgets with added spacing and optional interleaved dividers

flutter_series A flutter plugin for improved row and column widgets with added s

null 0 Nov 1, 2021
A Flutter Widget that create a horizontal table with fixed column on left hand side.

horizontal_data_table A Flutter Widget that create a horizontal table with fixed column on left hand side. Installation This package is starting to su

May Lau 204 Dec 27, 2022
Flutter Login interface using basic widgets such as Row, Column

Login UI - Flutter Descrição do Projeto ?? Interface de login utilizando widgets

null 2 Oct 25, 2022
A iOS like table view including section, row, section header and divider

flutter_section_table_view A iOS like table view including section, row, section header and divider Support both Android and iOS Support drop-down ref

刘彦博 73 Nov 4, 2022
Flutter package: Json Table Widget to create table from json array

Json Table Widget ?? Proudly Sponsored by FieldAssist Request a Demo This Flutter package provides a Json Table Widget for directly showing table from

Ayush P Gupta 193 Jan 7, 2023
Flutter-sorted-chips-row - Flutter library for rendering a row of Material "Chip" buttons that gets sorted according to the given function

sorted_chips_row A Flutter Widget displaying a row of Material Chips, sorted according to the provided comparison function. How to use Adding dependen

Callstack Incubator 29 Jul 29, 2021