// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';

// A generic widget for a list of selectable colors.
@immutable
class ColorPicker extends StatelessWidget {
  const ColorPicker({
    Key? key,
    required this.colors,
    required this.selectedColor,
    this.onColorSelection,
  }) : super(key: key);

  final Set<Color> colors;
  final Color selectedColor;
  final ValueChanged<Color>? onColorSelection;

  @override
  Widget build (BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: colors.map((Color color) {
        return _ColorPickerSwatch(
          color: color,
          selected: color == selectedColor,
          onTap: () {
            onColorSelection?.call(color);
          },
        );
      }).toList(),
    );
  }
}

// A single selectable color widget in the ColorPicker.
@immutable
class _ColorPickerSwatch extends StatelessWidget {
  const _ColorPickerSwatch({
    required this.color,
    required this.selected,
    this.onTap,
  });

  final Color color;
  final bool selected;
  final Function? onTap;

  @override
  Widget build (BuildContext context) {
    return Container(
      width: 60.0,
      height: 60.0,
      padding: const EdgeInsets.fromLTRB(2.0, 0.0, 2.0, 0.0),
      child: RawMaterialButton(
        fillColor: color,
        onPressed: () {
          onTap?.call();
        },
        child: !selected ? null : const Icon(
          Icons.check,
          color: Colors.white,
        ),
      ),
    );
  }
}
