diff --git a/database/sqlite.database b/database/database.sqlite
similarity index 87%
rename from database/sqlite.database
rename to database/database.sqlite
index 51e3c6632..1a9e27435 100644
Binary files a/database/sqlite.database and b/database/database.sqlite differ
diff --git a/docs/column-types/icon_column.md b/docs/column-types/icon_column.md
new file mode 100644
index 000000000..28c74458f
--- /dev/null
+++ b/docs/column-types/icon_column.md
@@ -0,0 +1,87 @@
+---
+title: Icon Columns (beta)
+weight: 10
+---
+
+Icon columns provide a way to display icons in your table without having to use `format()` or partial views.
+
+### setIcon
+setIcon requires a valid path to an SVG (Directly or via a Library), it receives the $row, and $value (if available) to help you customise which icon to use
+```php
+IconColumn::make('Icon', 'status')
+ ->setIcon(function ($row, $value) {
+ if($value == 1) {
+ return "heroicon-o-check-circle";
+ }
+ else
+ {
+ return "heroicon-o-x-circle";
+ }
+ }),
+```
+
+### attributes
+Attributes receives the $row, and $value (if available) to help you customise which attributes to apply, you may pass both classes, and other SVG specific attributes.
+```php
+IconColumn::make('Icon', 'status')
+ ->setIcon(function ($row, $value) { if($value == 1) { return "heroicon-o-check-circle"; } else { return "heroicon-o-x-circle"; } })
+ ->attributes(function ($row, $value) {
+ if($value == 1) {
+ return [
+ 'class' => 'w-6 h-6',
+ 'stroke' => '#008000'
+ ];
+ }
+ else
+ {
+ return [
+ 'class' => 'w-3 h-3',
+ 'stroke' => '#FF0000'
+ ];
+ }
+ }),
+```
+
+For example:
+### Example
+```php
+IconColumn::make('Icon', 'status')
+ ->setIcon(function ($row, $value) { if($value == 1) { return "heroicon-o-check-circle"; } else { return "heroicon-o-x-circle"; } })
+ ->attributes(function ($row, $value) {
+ if($value == 3) {
+ return [
+ 'class' => 'w-3 h-3',
+ 'stroke' => '#008000'
+ ];
+ }
+ else if($value == 2) {
+ return [
+ 'class' => 'w-3 h-3',
+ 'stroke' => '#0000FF'
+ ];
+ }
+ else
+ {
+ return [
+ 'class' => 'w-3 h-3',
+ 'stroke' => '#FF0000'
+ ];
+ }
+ }),
+```
+
+Please also see the following for other available methods:
+
\ No newline at end of file
diff --git a/docs/column-types/image_columns.md b/docs/column-types/image_columns.md
index 5e6868792..4225593b3 100644
--- a/docs/column-types/image_columns.md
+++ b/docs/column-types/image_columns.md
@@ -1,6 +1,6 @@
---
title: Image Columns
-weight: 10
+weight: 11
---
Image columns provide a way to display images in your table without having to use `format()` or partial views:
diff --git a/docs/column-types/link_columns.md b/docs/column-types/link_columns.md
index e3f3120a4..1e4aa7fa1 100644
--- a/docs/column-types/link_columns.md
+++ b/docs/column-types/link_columns.md
@@ -1,6 +1,6 @@
---
title: Link Columns
-weight: 11
+weight: 12
---
Link columns provide a way to display HTML links in your table without having to use `format()` or partial views:
diff --git a/docs/column-types/livewire_component_column.md b/docs/column-types/livewire_component_column.md
index b12ada72e..9b1851299 100644
--- a/docs/column-types/livewire_component_column.md
+++ b/docs/column-types/livewire_component_column.md
@@ -1,6 +1,6 @@
---
title: Livewire Component (beta)
-weight: 12
+weight: 13
---
Livewire Component Columns allow for the use of a Livewire Component as a Column.
diff --git a/docs/column-types/sum_column.md b/docs/column-types/sum_column.md
index d63aa8f47..b15288ef2 100644
--- a/docs/column-types/sum_column.md
+++ b/docs/column-types/sum_column.md
@@ -1,6 +1,6 @@
---
title: Sum Columns (beta)
-weight: 13
+weight: 14
---
Sum columns provide an easy way to display the "Sum" of a field on a relation.
diff --git a/docs/column-types/view_component_column.md b/docs/column-types/view_component_column.md
index 4b1b9a033..f3dd04276 100644
--- a/docs/column-types/view_component_column.md
+++ b/docs/column-types/view_component_column.md
@@ -1,6 +1,6 @@
---
title: View Component Columns
-weight: 14
+weight: 15
---
View Component columns let you specify a component name and attributes and provide attributes to the View Component. This will render the View Component in it's entirety.
diff --git a/docs/column-types/wire_link_column.md b/docs/column-types/wire_link_column.md
index 9abf15aac..253544cd0 100644
--- a/docs/column-types/wire_link_column.md
+++ b/docs/column-types/wire_link_column.md
@@ -1,6 +1,6 @@
---
title: Wire Link Column (beta)
-weight: 15
+weight: 16
---
WireLink columns provide a way to display Wired Links in your table without having to use `format()` or partial views, with or without a Confirmation Message
diff --git a/docs/columns/other-column-types.md b/docs/columns/other-column-types.md
index c3a8bd154..f12adf6e7 100644
--- a/docs/columns/other-column-types.md
+++ b/docs/columns/other-column-types.md
@@ -28,6 +28,9 @@ weight: 4
Date Columns
+
+ [Icon Columns (Beta)](../column-types/icon_columns)
+
Image Columns
diff --git a/resources/views/includes/columns/icon.blade.php b/resources/views/includes/columns/icon.blade.php
new file mode 100644
index 000000000..0f8298c03
--- /dev/null
+++ b/resources/views/includes/columns/icon.blade.php
@@ -0,0 +1,7 @@
+
+ @svg(
+ $icon,
+ $classes,
+ $attributes,
+ )
+
\ No newline at end of file
diff --git a/src/Views/Columns/IconColumn.php b/src/Views/Columns/IconColumn.php
new file mode 100644
index 000000000..3d37dbc10
--- /dev/null
+++ b/src/Views/Columns/IconColumn.php
@@ -0,0 +1,43 @@
+label(fn () => null);
+ }
+
+ $this->html();
+ }
+
+ public function getContents(Model $row): null|string|\Illuminate\Support\HtmlString|DataTableConfigurationException|\Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
+ {
+ $attributeBag = $this->getAttributeBag($row);
+
+ return view($this->getView())
+ ->withIsTailwind($this->isTailwind())
+ ->withIsBootstrap($this->isBootstrap())
+ ->withIcon($this->getIcon($row))
+ ->withClasses($attributeBag['class'])
+ ->withAttributes(collect($attributeBag)->except('class')->toArray());
+ }
+}
diff --git a/src/Views/Traits/Configuration/IconColumnConfiguration.php b/src/Views/Traits/Configuration/IconColumnConfiguration.php
new file mode 100644
index 000000000..f52bc9e2e
--- /dev/null
+++ b/src/Views/Traits/Configuration/IconColumnConfiguration.php
@@ -0,0 +1,13 @@
+iconCallback = $callback;
+
+ return $this;
+ }
+}
diff --git a/src/Views/Traits/Core/HasAttributes.php b/src/Views/Traits/Core/HasAttributes.php
index 76220d4bc..5ddd4653b 100644
--- a/src/Views/Traits/Core/HasAttributes.php
+++ b/src/Views/Traits/Core/HasAttributes.php
@@ -31,7 +31,7 @@ public function hasAttributesCallback(): bool
// TODO: Test
public function getAttributeBag(Model $row): ComponentAttributeBag
{
- return new ComponentAttributeBag($this->hasAttributesCallback() ? app()->call($this->getAttributesCallback(), ['row' => $row]) : []);
+ return new ComponentAttributeBag($this->hasAttributesCallback() ? app()->call($this->getAttributesCallback(), ['row' => $row, 'value' => $this->getValue($row)]) : []);
}
/**
diff --git a/src/Views/Traits/Helpers/IconColumnHelpers.php b/src/Views/Traits/Helpers/IconColumnHelpers.php
new file mode 100644
index 000000000..ceb8f9439
--- /dev/null
+++ b/src/Views/Traits/Helpers/IconColumnHelpers.php
@@ -0,0 +1,27 @@
+hasIconCallback() ? app()->call($this->getIconCallback(), ['row' => $row, 'value' => $this->getValue($row) ?? '']) : ($this->getValue($row));
+ }
+
+ public function getIconCallback(): ?callable
+ {
+ return $this->iconCallback;
+ }
+
+ public function hasIconCallback(): bool
+ {
+ return isset($this->iconCallback);
+ }
+}
diff --git a/tests/TestCase.php b/tests/TestCase.php
index d930575f7..0bf3aa3e2 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -193,10 +193,10 @@ public function getEnvironmentSetUp($app): void
$app['config']->set('view.cache', false);
$app['config']->set('view.compiled', realpath(storage_path('framework/views')).'/'.rand(0, 100));
- if (file_exists(__DIR__.'/../database/sqlite.database')) {
+ if (file_exists(__DIR__.'/../database/database.sqlite')) {
$app['config']->set('database.connections.sqlite', [
'driver' => 'sqlite',
- 'database' => __DIR__.'/../database/sqlite.database',
+ 'database' => __DIR__.'/../database/database.sqlite',
'prefix' => '',
]);
} else {
diff --git a/tests/Traits/Visuals/Columns/IconColumnVisualsTest.php b/tests/Traits/Visuals/Columns/IconColumnVisualsTest.php
new file mode 100644
index 000000000..68d3c80fb
--- /dev/null
+++ b/tests/Traits/Visuals/Columns/IconColumnVisualsTest.php
@@ -0,0 +1,64 @@
+setPrimaryKey('id');
+ }
+
+ public function columns(): array
+ {
+ return [
+ \Rappasoft\LaravelLivewireTables\Views\Column::make('Name')->searchable(),
+ \Rappasoft\LaravelLivewireTables\Views\Columns\IconColumn::make('Old Age', 'age')
+ ->setIcon(function (\Rappasoft\LaravelLivewireTables\Tests\Models\Pet $row, int $value) {
+ if ($value >= 5) {
+ return 'heroicon-o-check-circle';
+ } else {
+ return 'heroicon-o-x-circle';
+ }
+ }),
+ ];
+ }
+
+ public function filters(): array
+ {
+ return [];
+ }
+ })
+ ->call('setSearch', 'Cartman')
+ ->assertSeeHtmlInOrder([
+ '',
+ ])
+ ->assertDontSeeHtml('')
+ ->call('setSearch', 'May')
+ ->assertDontSeeHtml('')
+ ->assertSeeHtmlInOrder([
+ '',
+ ]);
+
+ }
+}
diff --git a/tests/Views/Columns/IconColumnTest.php b/tests/Views/Columns/IconColumnTest.php
new file mode 100644
index 000000000..3ac423234
--- /dev/null
+++ b/tests/Views/Columns/IconColumnTest.php
@@ -0,0 +1,108 @@
+assertSame('Icon Column 1', $column->getTitle());
+ }
+
+ public function test_can_get_the_column_view(): void
+ {
+ $column = IconColumn::make('Icon Column 1', 'favorite_color');
+
+ $this->assertSame('livewire-tables::includes.columns.icon', $column->getView());
+ $column->setView('test-icon-column');
+ $this->assertSame('test-icon-column', $column->getView());
+
+ }
+
+ public function test_can_infer_field_name_from_title_if_no_from(): void
+ {
+ $column = IconColumn::make('Icon Column 1');
+
+ $this->assertNull($column->getField());
+ }
+
+ public function test_can_setup_column_correctly(): void
+ {
+ $column = IconColumn::make('Icon Column 1')
+ ->setIcon(function ($row, $value) {
+ if ($value == 1) {
+ return 'heroicon-o-check-circle';
+ } else {
+ return 'heroicon-o-x-circle';
+ }
+ });
+
+ $this->assertNotEmpty($column);
+ }
+
+ public function test_icons_correctly_via_value(): void
+ {
+ $rows = $this->basicTable->getRows();
+ $column = IconColumn::make('Old Age', 'age')
+ ->setIcon(function (Pet $row, int $value) {
+ if ($value >= 5) {
+ return 'heroicon-o-check-circle';
+ } else {
+ return 'heroicon-o-x-circle';
+ }
+ });
+
+ $this->assertSame('heroicon-o-check-circle', $column->getIcon(Pet::where('age', '>', 5)->first()));
+ $this->assertSame('heroicon-o-x-circle', $column->getIcon(Pet::where('age', '<', 4)->first()));
+ }
+
+ public function test_icons_correctly_via_row(): void
+ {
+ $rows = $this->basicTable->getRows();
+ $column = IconColumn::make('Old Age', 'age')
+ ->setIcon(function (Pet $row) {
+ if ($row->age >= 7) {
+ return 'old-icon';
+ } else {
+ return 'young-icon';
+ }
+ });
+
+ $this->assertSame('old-icon', $column->getIcon(Pet::where('age', '>', 9)->first()));
+ $this->assertSame('young-icon', $column->getIcon(Pet::where('age', '<', 4)->first()));
+ }
+
+ public function test_renders_correctly(): void
+ {
+ $rows = $this->basicTable->getRows();
+ $row1 = $rows->first();
+ $column = IconColumn::make('Old Age', 'age')
+ ->setIcon(function (Pet $row, int $value) {
+ if ($value >= 5) {
+ return 'heroicon-o-check-circle';
+ } else {
+ return 'heroicon-o-x-circle';
+ }
+ });
+ $youngString = '';
+ $oldString = '';
+ $firstLine = str_replace(' ', ' ', str_replace(["\r", "\n"], '', $column->getContents(Pet::where('age', '<', 4)->first())));
+ $firstLine = str_replace('> <', '><', $firstLine);
+ $firstLine = str_replace('> <', '><', $firstLine);
+
+ $this->assertSame($oldString, $firstLine);
+
+ $lastLine = str_replace(' ', ' ', str_replace(["\r", "\n"], '', $column->getContents(Pet::where('age', '>', 5)->first())));
+ $lastLine = str_replace('> <', '><', $lastLine);
+ $lastLine = str_replace('> <', '><', $lastLine);
+
+ $this->assertSame($youngString, $lastLine);
+ }
+}