diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 5f45153..8c1f079 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -119,6 +119,21 @@ public function getTreeRecordIcon(?Model $record = null): ?string } ``` +**Toolbar Actions**: Add global actions displayed above the tree: + +```php +protected function getTreeToolbarActions(): array +{ + return [ + CreateAction::make(), + ExportAction::make(), + ImportAction::make(), + ]; +} +``` + +> **Note**: Toolbar actions are only supported in version 3.1.0 and later. + ## Key File Locations - Models: Add `ModelTree` trait to any hierarchical model diff --git a/README.md b/README.md index f14ea25..58c83bf 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ > [!IMPORTANT] -> Please note that we will only be updating to version 2.x or 3.x, excluding any bug fixes. +> Please note that we will only be updating to version 3.x, excluding any bug fixes. # Filament Tree @@ -544,6 +544,34 @@ class ProductCategoryWidget extends BaseWidget } ``` +#### Toolbar Actions + +You can add global actions that appear in the toolbar above the tree by implementing the `getTreeToolbarActions()` method. These actions are displayed alongside the default expand/collapse and save buttons: + +```php +protected function getTreeToolbarActions(): array +{ + return [ + \SolutionForest\FilamentTree\Actions\CreateAction::make() + ->label('Add Category') + ->icon('heroicon-o-plus') + ->color('primary'), + \Filament\Actions\ExportAction::make() + ->label('Export Tree') + ->icon('heroicon-o-document-arrow-down'), + \Filament\Actions\ImportAction::make() + ->label('Import Tree') + ->icon('heroicon-o-document-arrow-up'), + ]; +} +``` + +![Tree toolbar actions](https://github.com/user-attachments/assets/6d2e29c0-caa3-432c-8a7f-00ae7d7265ba) + +The toolbar actions are automatically generated by the Artisan command and include a `CreateAction` by default for tree widgets, but return an empty array for tree pages. You can customize this method to add any actions you need. + +> **Note**: Toolbar actions are only supported in version 3.1.0 and later. + ### Pages This plugin enables you to create tree pages in the admin panel. To create a tree page for a model, use the `make:filament-tree-page` command. For example, to create a tree page for the ProductCategory model, you can run: diff --git a/resources/css/custom-nestable-item.css b/resources/css/custom-nestable-item.css index 6b68177..32dd8da 100644 --- a/resources/css/custom-nestable-item.css +++ b/resources/css/custom-nestable-item.css @@ -106,5 +106,15 @@ } .filament-tree-component .nestable-menu { - @apply flex gap-2 mb-4; + @apply mb-4; +} +.filament-tree-component .nestable-menu, +.filament-tree-component .nestable-menu .toolbar-btns { + @apply flex items-center gap-2; +} +.filament-tree-component .nestable-menu { + @apply justify-between; +} +.filament-tree-component .nestable-menu .toolbar-btns.main { + @apply flex-1; } \ No newline at end of file diff --git a/resources/dist/filament-tree.css b/resources/dist/filament-tree.css index 4163f8d..c092440 100644 --- a/resources/dist/filament-tree.css +++ b/resources/dist/filament-tree.css @@ -1,2 +1,2 @@ -/*! tailwindcss v4.1.11 | MIT License | https://tailwindcss.com */ -@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-gray-50:oklch(98.5% .002 247.839);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-950:oklch(13% .028 261.692);--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-medium:500;--radius-lg:.5rem;--radius-xl:.75rem;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.collapse{visibility:collapse}.mb-2{margin-bottom:calc(var(--spacing)*2)}.ml-4{margin-left:calc(var(--spacing)*4)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.hidden{display:none}.h-4{height:calc(var(--spacing)*4)}.w-4{width:calc(var(--spacing)*4)}.w-full{width:100%}.cursor-wait{cursor:wait}.items-center{align-items:center}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.overflow-hidden{overflow:hidden}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-gray-300{border-color:var(--color-gray-300)}.bg-white{background-color:var(--color-white)}.px-5{padding-inline:calc(var(--spacing)*5)}.py-2{padding-block:calc(var(--spacing)*2)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.opacity-70{opacity:.7}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}@media (prefers-color-scheme:dark){.dark\:border-gray-600{border-color:var(--color-gray-600)}.dark\:bg-gray-500\/10{background-color:#6a72821a}@supports (color:color-mix(in lab, red, red)){.dark\:bg-gray-500\/10{background-color:color-mix(in oklab,var(--color-gray-500)10%,transparent)}}}}.dd{max-width:600px;margin:0;padding:0;font-size:13px;line-height:20px;list-style:none;display:block;position:relative}.dd-list{margin:0;padding:0;list-style:none;display:block;position:relative}.dd-list .dd-list{padding-left:30px}[dir=rtl] .dd-list .dd-list{padding-left:unset!important;padding-right:30px!important}.dd-empty,.dd-item,.dd-placeholder{min-height:20px;margin:0;padding:0;font-size:13px;line-height:20px;display:block;position:relative}.dd-item>button{cursor:pointer;float:left;white-space:nowrap;text-align:center;background:0 0;border:0;width:25px;height:20px;margin:5px 0;padding:0;font-size:12px;font-weight:700;line-height:1;position:relative;overflow:hidden}[dir=rtl] .dd-item>button{float:right}.dd-item>button:before{text-align:center;text-indent:0;width:100%;display:block;position:absolute}.dd-item>button.dd-expand:before{content:"+"}.dd-item>button.dd-collapse:before{content:"-"}.dd-expand,.dd-collapsed .dd-collapse,.dd-collapsed .dd-list{display:none}.dd-collapsed .dd-expand{display:block}.dd-empty,.dd-placeholder{box-sizing:border-box;background:#f2fbff;border:1px dashed #b6bcbf;min-height:30px;margin:5px 0;padding:0}:is(.dd-empty,.dd-placeholder):is(.dark *){background:#1f2937;border-color:#4b5563}.dd-empty{background-color:#e5e5e5;background-position:0 0,30px 30px;background-size:60px 60px;border:1px dashed #bbb;min-height:100px}.dd-dragel{pointer-events:none;z-index:9999;position:absolute}.dd-dragel>.dd-item .dd-handle{margin-top:0}.dd-dragel .dd-handle{background-color:#fffc;height:40px;padding:4px;box-shadow:2px 4px 6px #0000001a}.dd-dragel .dd-handle:is(.dark *){background-color:#1f2937cc}.dd-nochildren .dd-placeholder{display:none}.dd{max-width:initial}.dd-handle{height:55px}.dd-item>button{height:45px}.btn-group{gap:1px;display:flex}.btn-group button{border-radius:0}[dir=ltr] .btn-group button:first-of-type{border-top-left-radius:.5rem;border-bottom-left-radius:.5rem}[dir=ltr] .btn-group button:last-of-type,[dir=rtl] .btn-group button:first-of-type{border-top-right-radius:.5rem;border-bottom-right-radius:.5rem}[dir=rtl] .btn-group button:last-of-type{border-top-left-radius:.5rem;border-bottom-left-radius:.5rem}.btn-group button:first-of-type{border-radius:.5rem 0 0 .5rem}[dir=rtl] .btn-group button:first-of-type,.btn-group button:last-of-type{border-radius:0 .5rem .5rem 0}[dir=rtl] .btn-group button:last-of-type{border-radius:.5rem 0 0 .5rem}.btn-group button:only-of-type{border-radius:.5rem!important}.filament-tree .dd-item .dd-handle,.filament-tree .dd-item>.loading-indicator,.dd-dragel .dd-handle{margin-bottom:calc(var(--spacing)*2);height:calc(var(--spacing)*10);border-radius:var(--radius-lg);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-gray-300)}:is(.filament-tree .dd-item .dd-handle,.filament-tree .dd-item>.loading-indicator,.dd-dragel .dd-handle):is(.dark *){border-color:var(--color-gray-700)}.filament-tree .dd-placeholder{align-items:center;width:100%;display:flex}.filament-tree .dd-item .dd-handle{background-color:#fff;align-items:center;width:100%;display:flex}.filament-tree .dd-item .dd-handle:is(.dark *){background-color:var(--color-gray-950)}.filament-tree .dd-item .dd-handle>button{border-top-left-radius:var(--radius-lg);border-bottom-left-radius:var(--radius-lg);border-right-style:var(--tw-border-style);border-right-width:1px;align-items:center;height:100%;padding-inline:1px;display:flex}.filament-tree .dd-item .dd-handle>button:where(:dir(rtl),[dir=rtl],[dir=rtl] *){border-right-style:var(--tw-border-style);border-right-width:0;border-left-style:var(--tw-border-style);border-left-width:1px;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.filament-tree .dd-item .dd-handle>button{background-color:var(--color-gray-50);border-color:var(--color-gray-300)}.filament-tree .dd-item .dd-handle>button:is(.dark *){background-color:var(--color-gray-700);border-color:var(--color-gray-700)}.filament-tree .dd-item .dd-handle>button svg{height:calc(var(--spacing)*4);width:calc(var(--spacing)*4)}.filament-tree .dd-item .dd-handle>button svg:first-child{margin-right:calc(var(--spacing)*-2)}.filament-tree .dd-item .dd-handle>button svg:first-child:where(:dir(rtl),[dir=rtl],[dir=rtl] *){margin-right:calc(var(--spacing)*0);margin-left:calc(var(--spacing)*-2)}.filament-tree .dd-item .dd-handle>button svg{color:var(--color-gray-400)}.filament-tree .dd-item .dd-handle>button svg:is(.dark *){color:#fff}.dd-dragel .dd-content{height:100%}.dd-dragel .dd-handle>button,.dd-dragel .fi-tree-actions-ctn{display:none}.filament-tree .dd-item .dd-content,.dd-dragel .dd-content{gap:calc(var(--spacing)*1);display:flex}.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display{margin-left:calc(var(--spacing)*1);align-items:center;gap:calc(var(--spacing)*1);flex:1;display:flex}:is(.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display):where(:dir(rtl),[dir=rtl],[dir=rtl] *){margin-right:calc(var(--spacing)*1)}.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display{width:100%;max-width:150px}@media (min-width:48rem){.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display{max-width:155px}}@media (min-width:64rem){.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display{max-width:200px}}@media (min-width:80rem){.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display{max-width:350px}}:is(.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display) .icon-ctn svg{height:calc(var(--spacing)*4);width:calc(var(--spacing)*4)}:is(.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display) .item-content-ctn{min-width:calc(var(--spacing)*0);max-width:var(--container-xs);flex-direction:column;flex:1;display:flex}:is(.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display) .item-content-ctn .item-title{text-overflow:ellipsis;white-space:nowrap;--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);overflow:hidden}:is(.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display) .item-content-ctn .item-description{text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--color-gray-500);overflow:hidden}:is(.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display) .item-content-ctn .item-description:is(.dark *){color:var(--color-gray-400)}:is(.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display):not(:has(.icon-ctn)) .item-content-ctn{margin-left:calc(var(--spacing)*4)}:is(.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display):not(:has(.icon-ctn)) .item-content-ctn:where(:dir(rtl),[dir=rtl],[dir=rtl] *){margin-right:calc(var(--spacing)*4)}.filament-tree .dd-item .dd-content .dd-item-btns{flex:1;justify-content:center;align-items:center;display:flex}.filament-tree .dd-item .dd-content .dd-item-btns button svg{height:calc(var(--spacing)*4);width:calc(var(--spacing)*4);color:var(--color-gray-400)}.filament-tree .dd-item:not(:has(.dd-list)) .dd-item-btns{display:none}.filament-tree .dd-item .fi-tree-actions-ctn{margin-right:calc(var(--spacing)*4);margin-left:auto}.filament-tree .dd-item .fi-tree-actions-ctn:where(:dir(rtl),[dir=rtl],[dir=rtl] *){margin-right:auto;margin-left:calc(var(--spacing)*4)}.filament-tree .dd-item .fi-tree-actions-ctn .fi-tree-actions{align-items:center;gap:calc(var(--spacing)*3);flex-shrink:0;display:flex}.filament-tree .dd-item>.loading-indicator{animation:var(--animate-pulse);background-color:var(--color-gray-300);display:none}.filament-tree .dd-item>.loading-indicator:is(.dark *){background-color:var(--color-gray-600)}.filament-tree-component .nestable-menu{margin-bottom:calc(var(--spacing)*4);gap:calc(var(--spacing)*2);display:flex}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@keyframes pulse{50%{opacity:.5}} \ No newline at end of file +/*! tailwindcss v4.1.13 | MIT License | https://tailwindcss.com */ +@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-gray-50:oklch(98.5% .002 247.839);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-950:oklch(13% .028 261.692);--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-medium:500;--radius-lg:.5rem;--radius-xl:.75rem;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.collapse{visibility:collapse}.mb-2{margin-bottom:calc(var(--spacing)*2)}.ml-4{margin-left:calc(var(--spacing)*4)}.ml-auto{margin-left:auto}.flex{display:flex}.hidden{display:none}.h-4{height:calc(var(--spacing)*4)}.w-4{width:calc(var(--spacing)*4)}.w-full{width:100%}.cursor-wait{cursor:wait}.items-center{align-items:center}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.overflow-hidden{overflow:hidden}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-gray-300{border-color:var(--color-gray-300)}.bg-white{background-color:var(--color-white)}.px-5{padding-inline:calc(var(--spacing)*5)}.py-2{padding-block:calc(var(--spacing)*2)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.opacity-70{opacity:.7}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}@media (prefers-color-scheme:dark){.dark\:border-gray-600{border-color:var(--color-gray-600)}.dark\:bg-gray-500\/10{background-color:#6a72821a}@supports (color:color-mix(in lab, red, red)){.dark\:bg-gray-500\/10{background-color:color-mix(in oklab,var(--color-gray-500)10%,transparent)}}}}.dd{max-width:600px;margin:0;padding:0;font-size:13px;line-height:20px;list-style:none;display:block;position:relative}.dd-list{margin:0;padding:0;list-style:none;display:block;position:relative}.dd-list .dd-list{padding-left:30px}[dir=rtl] .dd-list .dd-list{padding-left:unset!important;padding-right:30px!important}.dd-empty,.dd-item,.dd-placeholder{min-height:20px;margin:0;padding:0;font-size:13px;line-height:20px;display:block;position:relative}.dd-item>button{cursor:pointer;float:left;white-space:nowrap;text-align:center;background:0 0;border:0;width:25px;height:20px;margin:5px 0;padding:0;font-size:12px;font-weight:700;line-height:1;position:relative;overflow:hidden}[dir=rtl] .dd-item>button{float:right}.dd-item>button:before{text-align:center;text-indent:0;width:100%;display:block;position:absolute}.dd-item>button.dd-expand:before{content:"+"}.dd-item>button.dd-collapse:before{content:"-"}.dd-expand,.dd-collapsed .dd-collapse,.dd-collapsed .dd-list{display:none}.dd-collapsed .dd-expand{display:block}.dd-empty,.dd-placeholder{box-sizing:border-box;background:#f2fbff;border:1px dashed #b6bcbf;min-height:30px;margin:5px 0;padding:0}:is(.dd-empty,.dd-placeholder):is(.dark *){background:#1f2937;border-color:#4b5563}.dd-empty{background-color:#e5e5e5;background-position:0 0,30px 30px;background-size:60px 60px;border:1px dashed #bbb;min-height:100px}.dd-dragel{pointer-events:none;z-index:9999;position:absolute}.dd-dragel>.dd-item .dd-handle{margin-top:0}.dd-dragel .dd-handle{background-color:#fffc;height:40px;padding:4px;box-shadow:2px 4px 6px #0000001a}.dd-dragel .dd-handle:is(.dark *){background-color:#1f2937cc}.dd-nochildren .dd-placeholder{display:none}.dd{max-width:initial}.dd-handle{height:55px}.dd-item>button{height:45px}.btn-group{gap:1px;display:flex}.btn-group button{border-radius:0}[dir=ltr] .btn-group button:first-of-type{border-top-left-radius:.5rem;border-bottom-left-radius:.5rem}[dir=ltr] .btn-group button:last-of-type,[dir=rtl] .btn-group button:first-of-type{border-top-right-radius:.5rem;border-bottom-right-radius:.5rem}[dir=rtl] .btn-group button:last-of-type{border-top-left-radius:.5rem;border-bottom-left-radius:.5rem}.btn-group button:first-of-type{border-radius:.5rem 0 0 .5rem}[dir=rtl] .btn-group button:first-of-type,.btn-group button:last-of-type{border-radius:0 .5rem .5rem 0}[dir=rtl] .btn-group button:last-of-type{border-radius:.5rem 0 0 .5rem}.btn-group button:only-of-type{border-radius:.5rem!important}.filament-tree .dd-item .dd-handle,.filament-tree .dd-item>.loading-indicator,.dd-dragel .dd-handle{margin-bottom:calc(var(--spacing)*2);height:calc(var(--spacing)*10);border-radius:var(--radius-lg);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-gray-300)}:is(.filament-tree .dd-item .dd-handle,.filament-tree .dd-item>.loading-indicator,.dd-dragel .dd-handle):is(.dark *){border-color:var(--color-gray-700)}.filament-tree .dd-placeholder{align-items:center;width:100%;display:flex}.filament-tree .dd-item .dd-handle{background-color:#fff;align-items:center;width:100%;display:flex}.filament-tree .dd-item .dd-handle:is(.dark *){background-color:var(--color-gray-950)}.filament-tree .dd-item .dd-handle>button{border-top-left-radius:var(--radius-lg);border-bottom-left-radius:var(--radius-lg);border-right-style:var(--tw-border-style);border-right-width:1px;align-items:center;height:100%;padding-inline:1px;display:flex}.filament-tree .dd-item .dd-handle>button:where(:dir(rtl),[dir=rtl],[dir=rtl] *){border-right-style:var(--tw-border-style);border-right-width:0;border-left-style:var(--tw-border-style);border-left-width:1px;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.filament-tree .dd-item .dd-handle>button{background-color:var(--color-gray-50);border-color:var(--color-gray-300)}.filament-tree .dd-item .dd-handle>button:is(.dark *){background-color:var(--color-gray-700);border-color:var(--color-gray-700)}.filament-tree .dd-item .dd-handle>button svg{height:calc(var(--spacing)*4);width:calc(var(--spacing)*4)}.filament-tree .dd-item .dd-handle>button svg:first-child{margin-right:calc(var(--spacing)*-2)}.filament-tree .dd-item .dd-handle>button svg:first-child:where(:dir(rtl),[dir=rtl],[dir=rtl] *){margin-right:calc(var(--spacing)*0);margin-left:calc(var(--spacing)*-2)}.filament-tree .dd-item .dd-handle>button svg{color:var(--color-gray-400)}.filament-tree .dd-item .dd-handle>button svg:is(.dark *){color:#fff}.dd-dragel .dd-content{height:100%}.dd-dragel .dd-handle>button,.dd-dragel .fi-tree-actions-ctn{display:none}.filament-tree .dd-item .dd-content,.dd-dragel .dd-content{gap:calc(var(--spacing)*1);display:flex}.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display{margin-left:calc(var(--spacing)*1);align-items:center;gap:calc(var(--spacing)*1);flex:1;display:flex}:is(.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display):where(:dir(rtl),[dir=rtl],[dir=rtl] *){margin-right:calc(var(--spacing)*1)}.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display{width:100%;max-width:150px}@media (min-width:48rem){.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display{max-width:155px}}@media (min-width:64rem){.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display{max-width:200px}}@media (min-width:80rem){.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display{max-width:350px}}:is(.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display) .icon-ctn svg{height:calc(var(--spacing)*4);width:calc(var(--spacing)*4)}:is(.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display) .item-content-ctn{min-width:calc(var(--spacing)*0);max-width:var(--container-xs);flex-direction:column;flex:1;display:flex}:is(.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display) .item-content-ctn .item-title{text-overflow:ellipsis;white-space:nowrap;--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);overflow:hidden}:is(.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display) .item-content-ctn .item-description{text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--color-gray-500);overflow:hidden}:is(.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display) .item-content-ctn .item-description:is(.dark *){color:var(--color-gray-400)}:is(.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display):not(:has(.icon-ctn)) .item-content-ctn{margin-left:calc(var(--spacing)*4)}:is(.filament-tree .dd-item .dd-content>.tree-item-display,.dd-dragel .tree-item-display):not(:has(.icon-ctn)) .item-content-ctn:where(:dir(rtl),[dir=rtl],[dir=rtl] *){margin-right:calc(var(--spacing)*4)}.filament-tree .dd-item .dd-content .dd-item-btns{flex:1;justify-content:center;align-items:center;display:flex}.filament-tree .dd-item .dd-content .dd-item-btns button svg{height:calc(var(--spacing)*4);width:calc(var(--spacing)*4);color:var(--color-gray-400)}.filament-tree .dd-item:not(:has(.dd-list)) .dd-item-btns{display:none}.filament-tree .dd-item .fi-tree-actions-ctn{margin-right:calc(var(--spacing)*4);margin-left:auto}.filament-tree .dd-item .fi-tree-actions-ctn:where(:dir(rtl),[dir=rtl],[dir=rtl] *){margin-right:auto;margin-left:calc(var(--spacing)*4)}.filament-tree .dd-item .fi-tree-actions-ctn .fi-tree-actions{align-items:center;gap:calc(var(--spacing)*3);flex-shrink:0;display:flex}.filament-tree .dd-item>.loading-indicator{animation:var(--animate-pulse);background-color:var(--color-gray-300);display:none}.filament-tree .dd-item>.loading-indicator:is(.dark *){background-color:var(--color-gray-600)}.filament-tree-component .nestable-menu{margin-bottom:calc(var(--spacing)*4)}.filament-tree-component .nestable-menu,.filament-tree-component .nestable-menu .toolbar-btns{align-items:center;gap:calc(var(--spacing)*2);display:flex}.filament-tree-component .nestable-menu{justify-content:space-between}.filament-tree-component .nestable-menu .toolbar-btns.main{flex:1}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@keyframes pulse{50%{opacity:.5}} \ No newline at end of file diff --git a/resources/views/actions/button-action.blade.php b/resources/views/actions/button-action.blade.php index 890c97d..d345f22 100644 --- a/resources/views/actions/button-action.blade.php +++ b/resources/views/actions/button-action.blade.php @@ -1,12 +1 @@ - - {{ $getLabel() }} - - +{{-- Deprecated with filament v4 --}} \ No newline at end of file diff --git a/resources/views/actions/group.blade.php b/resources/views/actions/group.blade.php index 0f0b2ef..d345f22 100644 --- a/resources/views/actions/group.blade.php +++ b/resources/views/actions/group.blade.php @@ -1,9 +1 @@ - +{{-- Deprecated with filament v4 --}} \ No newline at end of file diff --git a/resources/views/actions/grouped-action.blade.php b/resources/views/actions/grouped-action.blade.php index 6ddf219..d345f22 100644 --- a/resources/views/actions/grouped-action.blade.php +++ b/resources/views/actions/grouped-action.blade.php @@ -1,8 +1 @@ - - {{ $getLabel() }} - +{{-- Deprecated with filament v4 --}} \ No newline at end of file diff --git a/resources/views/actions/icon-button-action.blade.php b/resources/views/actions/icon-button-action.blade.php index ed6802f..d345f22 100644 --- a/resources/views/actions/icon-button-action.blade.php +++ b/resources/views/actions/icon-button-action.blade.php @@ -1,6 +1 @@ - +{{-- Deprecated with filament v4 --}} \ No newline at end of file diff --git a/resources/views/actions/link-action.blade.php b/resources/views/actions/link-action.blade.php index 6c4d4ac..d345f22 100644 --- a/resources/views/actions/link-action.blade.php +++ b/resources/views/actions/link-action.blade.php @@ -1,9 +1 @@ - - {{ $getLabel() }} - +{{-- Deprecated with filament v4 --}} \ No newline at end of file diff --git a/resources/views/actions/modal/actions/button-action.blade.php b/resources/views/actions/modal/actions/button-action.blade.php index 092a3d0..d345f22 100644 --- a/resources/views/actions/modal/actions/button-action.blade.php +++ b/resources/views/actions/modal/actions/button-action.blade.php @@ -1,280 +1 @@ -@if ($this instanceof \Filament\Actions\Contracts\HasActions && (! $this->hasActionsModalRendered)) -
- @php - $action = $this->getMountedAction(); - @endphp - - - @if ($action) - {{ $action->getModalContent() }} - - @if (count(($infolist = $action->getInfolist())?->getComponents() ?? [])) - {{ $infolist }} - @elseif ($this->mountedActionHasForm()) - {{ $this->getMountedActionForm() }} - @endif - - {{ $action->getModalContentFooter() }} - @endif - -
- - @php - $this->hasActionsModalRendered = true; - @endphp -@endif - -@if ($this instanceof \Filament\Infolists\Contracts\HasInfolists && (! $this->hasInfolistsModalRendered)) -
- @php - $action = $this->getMountedInfolistAction(); - @endphp - - - @if ($action) - {{ $action->getModalContent() }} - - @if (count(($infolist = $action->getInfolist())?->getComponents() ?? [])) - {{ $infolist }} - @elseif ($this->mountedInfolistActionHasForm()) - {{ $this->getMountedInfolistActionForm() }} - @endif - - {{ $action->getModalContentFooter() }} - @endif - -
- - @php - $this->hasInfolistsModalRendered = true; - @endphp -@endif - -@if ($this instanceof \Filament\Tables\Contracts\HasTable && (! $this->hasTableModalRendered)) -
- @php - $action = $this->getMountedTableAction(); - @endphp - - - @if ($action) - {{ $action->getModalContent() }} - - @if (count(($infolist = $action->getInfolist())?->getComponents() ?? [])) - {{ $infolist }} - @elseif ($this->mountedTableActionHasForm()) - {{ $this->getMountedTableActionForm() }} - @endif - - {{ $action->getModalContentFooter() }} - @endif - -
- -
- @php - $action = $this->getMountedTableBulkAction(); - @endphp - - - @if ($action) - {{ $action->getModalContent() }} - - @if (count(($infolist = $action->getInfolist())?->getComponents() ?? [])) - {{ $infolist }} - @elseif ($this->mountedTableBulkActionHasForm()) - {{ $this->getMountedTableBulkActionForm() }} - @endif - - {{ $action->getModalContentFooter() }} - @endif - -
- - @php - $this->hasTableModalRendered = true; - @endphp -@endif - -@if (! $this->hasFormsModalRendered) - @php - $action = $this->getMountedFormComponentAction(); - @endphp - -
- - @if ($action) - {{ $action->getModalContent() }} - - @if (count(($infolist = $action->getInfolist())?->getComponents() ?? [])) - {{ $infolist }} - @elseif ($this->mountedFormComponentActionHasForm()) - {{ $this->getMountedFormComponentActionForm() }} - @endif - - {{ $action->getModalContentFooter() }} - @endif - -
- - @php - $this->hasFormsModalRendered = true; - @endphp -@endif \ No newline at end of file +{{-- Deprecated with filament v4 --}} \ No newline at end of file diff --git a/resources/views/components/actions/index.blade.php b/resources/views/components/actions/index.blade.php index d99f54f..8854887 100644 --- a/resources/views/components/actions/index.blade.php +++ b/resources/views/components/actions/index.blade.php @@ -21,4 +21,4 @@ function ($action) use ($record): bool { ); @endphp - \ No newline at end of file + \ No newline at end of file diff --git a/resources/views/components/modal/actions.blade.php b/resources/views/components/modal/actions.blade.php index 9b25347..4c6ab9a 100644 --- a/resources/views/components/modal/actions.blade.php +++ b/resources/views/components/modal/actions.blade.php @@ -1,7 +1,9 @@ - {{ $slot }} - + \ No newline at end of file diff --git a/resources/views/components/modal/heading.blade.php b/resources/views/components/modal/heading.blade.php index 6e2bc87..b184a14 100644 --- a/resources/views/components/modal/heading.blade.php +++ b/resources/views/components/modal/heading.blade.php @@ -1,6 +1,6 @@ - {{ $slot }} - + \ No newline at end of file diff --git a/resources/views/components/modal/index.blade.php b/resources/views/components/modal/index.blade.php index 8bec0df..9030b4b 100644 --- a/resources/views/components/modal/index.blade.php +++ b/resources/views/components/modal/index.blade.php @@ -1,19 +1,32 @@ -@captureSlots([ - 'actions', - 'content', - 'footer', - 'header', - 'heading', - 'subheading', - 'trigger', -]) - - {{ $slot }} - + \ No newline at end of file diff --git a/resources/views/components/modal/subheading.blade.php b/resources/views/components/modal/subheading.blade.php index 50c60ae..bb45a4a 100644 --- a/resources/views/components/modal/subheading.blade.php +++ b/resources/views/components/modal/subheading.blade.php @@ -1,6 +1,6 @@ - {{ $slot }} - + \ No newline at end of file diff --git a/resources/views/components/tree/index.blade.php b/resources/views/components/tree/index.blade.php index f7ef417..638b716 100644 --- a/resources/views/components/tree/index.blade.php +++ b/resources/views/components/tree/index.blade.php @@ -2,7 +2,7 @@ $containerKey = 'filament_tree_container_' . $this->getId(); $maxDepth = $getMaxDepth() ?? 1; $records = collect($this->getRootLayerRecords() ?? []); - + $toolbarActions = $tree->getToolbarActions() ?? []; @endphp
- + + + {{ ($this->displayTreeTitle() ?? false) ? $this->getTreeTitle() : null }} + -
- - {{ __('filament-tree::filament-tree.button.expand_all') }} - - - {{ __('filament-tree::filament-tree.button.collapse_all') }} - +
+
+ + {{ __('filament-tree::filament-tree.button.expand_all') }} + + + {{ __('filament-tree::filament-tree.button.collapse_all') }} + +
+
+ + + + {{ __('filament-tree::filament-tree.button.save') }} + + +
-
- - - - {{ __('filament-tree::filament-tree.button.save') }} - - -
+ @if (is_array($toolbarActions) && count($toolbarActions)) + + @endif
diff --git a/src/Actions/Action.php b/src/Actions/Action.php index 8059d64..733f6bf 100644 --- a/src/Actions/Action.php +++ b/src/Actions/Action.php @@ -3,81 +3,12 @@ namespace SolutionForest\FilamentTree\Actions; use Filament\Actions\Action as BaseAction; -use Illuminate\Database\Eloquent\Model; use SolutionForest\FilamentTree\Concern\Actions\HasTree; +use SolutionForest\FilamentTree\Concern\Actions\TreeActionTrait; use SolutionForest\FilamentTree\Concern\BelongsToTree; class Action extends BaseAction implements HasTree { use BelongsToTree; - - public function getLivewireClickHandler(): ?string - { - if (! $this->isLivewireClickHandlerEnabled()) { - return null; - } - - if (is_string($this->action)) { - return $this->action; - } - - if ($record = $this->getRecord()) { - $recordKey = $this->getLivewire()->getRecordKey($record); - - return "mountTreeAction('{$this->getName()}', '{$recordKey}')"; - } - - return "mountTreeAction('{$this->getName()}')"; - } - - /** - * @return array - */ - protected function resolveDefaultClosureDependencyForEvaluationByName(string $parameterName): array - { - return match ($parameterName) { - 'tree' => [$this->getTree()], - default => parent::resolveDefaultClosureDependencyForEvaluationByName($parameterName), - }; - } - - public function getRecordTitle(?Model $record = null): string - { - $record ??= $this->getRecord(); - - return $this->getCustomRecordTitle($record) ?? $this->getLivewire()->getTreeRecordTitle($record); - } - - public function getRecordTitleAttribute(): ?string - { - return $this->getCustomRecordTitleAttribute() ?? $this->getTree()->getRecordTitleAttribute(); - } - - public function getModelLabel(): string - { - return $this->getCustomModelLabel() ?? $this->getTree()->getModelLabel(); - } - - public function getPluralModelLabel(): string - { - return $this->getCustomPluralModelLabel() ?? $this->getTree()->getPluralModelLabel(); - } - - public function getModel(bool $withDefault = true): ?string - { - return $this->getCustomModel() ?? $this->getLivewire()->getModel(); - } - - public function prepareModalAction(BaseAction $action): BaseAction - { - $action = parent::prepareModalAction($action); - - if (! $action instanceof Action) { - return $action; - } - - return $action - ->tree($this->getTree()) - ->record($this->getRecord()); - } + use TreeActionTrait; } diff --git a/src/Actions/CreateAction.php b/src/Actions/CreateAction.php new file mode 100644 index 0000000..5827b9d --- /dev/null +++ b/src/Actions/CreateAction.php @@ -0,0 +1,11 @@ +label(__('filament-actions::delete.single.label')); - - $this->modalHeading(fn (): string => __('filament-actions::delete.single.modal.heading', ['label' => $this->getRecordTitle()])); - - $this->modalSubmitActionLabel(__('filament-actions::delete.single.modal.actions.delete.label')); - - $this->successNotificationTitle(__('filament-actions::delete.single.notifications.deleted.title')); - - $this->color('danger'); - - $this->icon('heroicon-m-trash'); - - $this->requiresConfirmation(); - - $this->modalSubheading(function (Model $record) { - if (collect($record->children)->isNotEmpty()) { - return __('filament-tree::filament-tree.actions.delete.confirmation.with_children'); - - } else { - return __('filament-actions::modal.confirmation'); - - } - }); - - $this->modalIcon('heroicon-o-trash'); - - $this->hidden(static function (Model $record): bool { - if (! method_exists($record, 'trashed')) { - return false; - } - - return $record->trashed(); - }); - - $this->action(function (): void { - $result = $this->process(static fn (Model $record) => $record->delete()); - - if (! $result) { - $this->failure(); - - return; - } - - $this->success(); - }); - } + use TreeActionTrait; } diff --git a/src/Actions/EditAction.php b/src/Actions/EditAction.php index 9b2c873..c78c3ef 100644 --- a/src/Actions/EditAction.php +++ b/src/Actions/EditAction.php @@ -2,81 +2,10 @@ namespace SolutionForest\FilamentTree\Actions; -use Closure; -use Filament\Actions\Concerns\CanCustomizeProcess; -use Illuminate\Database\Eloquent\Model; -use SolutionForest\FilamentTree\Components\Tree; +use Filament\Actions\EditAction as BaseEditAction; +use SolutionForest\FilamentTree\Concern\Actions\TreeActionTrait; -class EditAction extends Action +class EditAction extends BaseEditAction { - use CanCustomizeProcess; - - protected ?Closure $mutateRecordDataUsing = null; - - protected ?Closure $mutateFormDataBeforeSaveUsing = null; - - public static function getDefaultName(): ?string - { - return 'edit'; - } - - protected function setUp(): void - { - parent::setUp(); - - $this->label(__('filament-actions::edit.single.label')); - - $this->modalHeading(fn (): string => __('filament-actions::edit.single.modal.heading', ['label' => $this->getRecordTitle()])); - - $this->modalSubmitActionLabel(__('filament-actions::edit.single.modal.actions.save.label')); - - $this->successNotificationTitle(__('filament-actions::edit.single.notifications.saved.title')); - - $this->icon('heroicon-m-pencil-square'); - - $this->fillForm(function (Model $record, Tree $tree): array { - if ($translatableContentDriver = $tree->makeFilamentTranslatableContentDriver()) { - $data = $translatableContentDriver->getRecordAttributesToArray($record); - } else { - $data = $record->attributesToArray(); - } - - if ($this->mutateRecordDataUsing) { - $data = $this->evaluate($this->mutateRecordDataUsing, ['data' => $data, 'record' => $record]); - } - - return $data; - }); - - $this->action(function (): void { - $this->process(function (array $data, Model $record, Tree $tree) { - if ($translatableContentDriver = $tree->makeFilamentTranslatableContentDriver()) { - $translatableContentDriver->updateRecord($record, $data); - } else { - $record->update($data); - } - }); - - $this->success(); - }); - } - - public function mutateRecordDataUsing(?Closure $callback): static - { - $this->mutateRecordDataUsing = $callback; - - return $this; - } - - public function mutateFormDataBeforeSaveUsing(?Closure $callback): static - { - $this->mutateFormDataBeforeSaveUsing = $callback; - - return $this; - } - - public function getMutateFormDataBeforeSave(): ?Closure - { - return $this->mutateFormDataBeforeSaveUsing; - } + use TreeActionTrait; } diff --git a/src/Actions/ViewAction.php b/src/Actions/ViewAction.php index 4421c0c..7bda96c 100644 --- a/src/Actions/ViewAction.php +++ b/src/Actions/ViewAction.php @@ -2,57 +2,10 @@ namespace SolutionForest\FilamentTree\Actions; -use Closure; -use Illuminate\Database\Eloquent\Model; -use SolutionForest\FilamentTree\Components\Tree; +use Filament\Actions\ViewAction as BaseViewAction; +use SolutionForest\FilamentTree\Concern\Actions\TreeActionTrait; -class ViewAction extends Action +class ViewAction extends BaseViewAction { - protected ?Closure $mutateRecordDataUsing = null; - - public static function getDefaultName(): ?string - { - return 'view'; - } - - protected function setUp(): void - { - parent::setUp(); - - $this->label(__('filament-actions::view.single.label')); - - $this->modalHeading(fn (): string => __('filament-actions::view.single.modal.heading', ['label' => $this->getRecordTitle()])); - - $this->modalSubmitAction(false); - $this->modalCancelAction(fn (\Filament\Actions\Action $action) => $action->label(__('filament-actions::view.single.modal.actions.close.label'))); - - $this->color('gray'); - - $this->icon('heroicon-m-eye'); - - $this->disabledForm(); - - $this->fillForm(function (Model $record, Tree $tree): array { - if ($translatableContentDriver = $tree->makeFilamentTranslatableContentDriver()) { - $data = $translatableContentDriver->getRecordAttributesToArray($record); - } else { - $data = $record->attributesToArray(); - } - - if ($this->mutateRecordDataUsing) { - $data = $this->evaluate($this->mutateRecordDataUsing, ['data' => $data, 'record' => $record]); - } - - return $data; - }); - - $this->action(static function (): void {}); - } - - public function mutateRecordDataUsing(?Closure $callback): static - { - $this->mutateRecordDataUsing = $callback; - - return $this; - } + use TreeActionTrait; } diff --git a/src/Commands/FileGenerators/Concerns/CanGenerateTreeMethods.php b/src/Commands/FileGenerators/Concerns/CanGenerateTreeMethods.php index 0ba4b49..f8bc1f6 100644 --- a/src/Commands/FileGenerators/Concerns/CanGenerateTreeMethods.php +++ b/src/Commands/FileGenerators/Concerns/CanGenerateTreeMethods.php @@ -25,6 +25,26 @@ protected function addGetTreeActionsMethodToClass(ClassType $class): void protected function configureGetTreeActionsMethod(Method $method): void {} + protected function addGetTreeToolbarActionsMethodToClass(ClassType $class, bool $preset = false): void + { + $body = $preset ? <<addMethod('getTreeToolbarActions') + ->setProtected() + ->setReturnType('array') + ->setBody($body); + + $this->configureGetTreeToolbarActionsMethod($method); + } + + protected function configureGetTreeToolbarActionsMethod(Method $method): void {} + protected function addGetFormSchemaMethodToClass(ClassType $class): void { $method = $class->addMethod('getFormSchema') diff --git a/src/Commands/FileGenerators/ResourceTreePageClassGenerator.php b/src/Commands/FileGenerators/ResourceTreePageClassGenerator.php index f89f319..9dd01d2 100644 --- a/src/Commands/FileGenerators/ResourceTreePageClassGenerator.php +++ b/src/Commands/FileGenerators/ResourceTreePageClassGenerator.php @@ -62,6 +62,7 @@ protected function addPropertiesToClass(ClassType $class): void protected function addMethodsToClass(ClassType $class): void { + $this->addGetTreeToolbarActionsMethodToClass($class); $this->addGetTreeActionsMethodToClass($class); $this->addHasDeleteActionMethodToClass($class); $this->addHasEditActionMethodToClass($class); diff --git a/src/Commands/FileGenerators/TreePageClassGenerator.php b/src/Commands/FileGenerators/TreePageClassGenerator.php index c9492e6..fee4534 100644 --- a/src/Commands/FileGenerators/TreePageClassGenerator.php +++ b/src/Commands/FileGenerators/TreePageClassGenerator.php @@ -69,6 +69,7 @@ protected function addPropertiesToClass(ClassType $class): void protected function addMethodsToClass(ClassType $class): void { + $this->addGetTreeToolbarActionsMethodToClass($class); $this->addGetTreeActionsMethodToClass($class); $this->addGetFormSchemaMethodToClass($class); $this->addHasDeleteActionMethodToClass($class); diff --git a/src/Commands/FileGenerators/TreeWidgetClassGenerator.php b/src/Commands/FileGenerators/TreeWidgetClassGenerator.php index c9491ef..9c20957 100644 --- a/src/Commands/FileGenerators/TreeWidgetClassGenerator.php +++ b/src/Commands/FileGenerators/TreeWidgetClassGenerator.php @@ -69,6 +69,7 @@ protected function addMethodsToClass(ClassType $class): void { $this->addGetFormSchemaMethodToClass($class); $this->addGetViewFormSchemaMethodToClass($class); + $this->addGetTreeToolbarActionsMethodToClass($class, true); } public function generate(): string diff --git a/src/Components/Tree.php b/src/Components/Tree.php index 2508931..1bb9344 100644 --- a/src/Components/Tree.php +++ b/src/Components/Tree.php @@ -2,9 +2,10 @@ namespace SolutionForest\FilamentTree\Components; -use Filament\Schemas\Schema; +use Filament\Actions\ActionGroup as FilamentActionsActionGroup; use Filament\Support\Components\ViewComponent; use Illuminate\Database\Eloquent\Model; +use SolutionForest\FilamentTree\Actions\ActionGroup; use SolutionForest\FilamentTree\Concern\BelongsToLivewire; use SolutionForest\FilamentTree\Contract\HasTree; use SolutionForest\FilamentTree\Support\Utils; @@ -21,6 +22,8 @@ class Tree extends ViewComponent protected array $actions = []; + protected array $toolbarActions = []; + public const LOADING_TARGETS = ['activeLocale']; public function __construct(HasTree $livewire) @@ -51,6 +54,13 @@ public function actions(array $actions): static return $this; } + public function toolbarActions(array $actions): static + { + $this->toolbarActions = $actions; + + return $this; + } + public function getMaxDepth(): int { return $this->maxDepth; @@ -64,9 +74,40 @@ public function getActions(): array public function getAction($name) { foreach ($this->actions as $action) { - if ($action instanceof \Filament\Actions\ActionGroup) { - return collect($action->getFlatActions())->get($name); + + if ($action instanceof FilamentActionsActionGroup || $action instanceof ActionGroup) { + if ($groupedAction = collect($action->getFlatActions())->get($name)) { + return $groupedAction; + } else { + continue; + } } + + if ($action->getName() === $name) { + return $action; + } + } + + return null; + } + + public function getToolbarActions(): array + { + return $this->toolbarActions; + } + + public function getToolbarAction($name) + { + foreach ($this->toolbarActions as $action) { + + if ($action instanceof FilamentActionsActionGroup || $action instanceof ActionGroup) { + if ($groupedAction = collect($action->getFlatActions())->get($name)) { + return $groupedAction; + } else { + continue; + } + } + if ($action->getName() === $name) { return $action; } @@ -97,9 +138,4 @@ public function getParentKey(?Model $record): ?string return $record->getAttributeValue((method_exists($record, 'determineParentKey') ? $record->determineParentColumnName() : Utils::parentColumnName())); } - - public function getMountedActionForm(): ?Schema - { - return $this->getLivewire()->getMountedTreeActionForm(); - } } diff --git a/src/Concern/Actions/TreeActionTrait.php b/src/Concern/Actions/TreeActionTrait.php new file mode 100644 index 0000000..9b99500 --- /dev/null +++ b/src/Concern/Actions/TreeActionTrait.php @@ -0,0 +1,58 @@ +isLivewireClickHandlerEnabled()) { + return null; + } + + if (is_string($this->action)) { + return $this->action; + } + + $arguments = Js::from($this->getArguments()); + + if ($record = $this->getRecord()) { + $recordKey = $this->getLivewire()->getRecordKey($record); + + return "mountTreeAction('{$this->getName()}', '{$recordKey}', {$arguments})"; + } + + return "mountTreeAction('{$this->getName()}', null, {$arguments})"; + } + + /** + * @return array + */ + protected function resolveDefaultClosureDependencyForEvaluationByName(string $parameterName): array + { + return match ($parameterName) { + 'tree' => [$this->getTree()], + default => parent::resolveDefaultClosureDependencyForEvaluationByName($parameterName), + }; + } + + public function prepareModalAction(BaseAction $action): BaseAction + { + $action = parent::prepareModalAction($action); + + if (! $action instanceof Action) { + return $action; + } + + return $action + ->tree($this->getTree()) + ->record($this->getRecord()); + } +} diff --git a/src/Concern/HasActions.php b/src/Concern/HasActions.php index 58e153c..57eacd3 100644 --- a/src/Concern/HasActions.php +++ b/src/Concern/HasActions.php @@ -13,23 +13,42 @@ trait HasActions { + protected array $cachedTreeToolbarActions = []; + protected array $cachedTreeActions = []; protected function resolveAction(array $action, array $parentActions): ?FilamentActionsAction { - if ($this instanceof HasTree && filled($action['context']['tree'] ?? null)) { + if ($this instanceof HasTree) { $resolvedAction = null; - $resolvedAction = $this->getCachedTree()?->getAction($action['name']) ?? throw new ActionNotResolvableException("Action [{$action['name']}] not found on tree."); + if ( + filled($action['context']['tree'] ?? null) || + filled($action['arguments']['treeToolbar'] ?? null) + ) { - if (filled($action['context']['recordKey'] ?? null)) { - $record = $this->getTreeRecord($action['context']['recordKey']); + if (! isset($action['name']) || empty($action['name'])) { + throw new ActionNotResolvableException('Action name is not specified.'); + } - $resolvedAction->getRootGroup()?->record($record) ?? $resolvedAction->record($record); - } + if (($action['arguments']['treeToolbar'] ?? false) === true) { + $resolvedAction = $this->cachedTreeToolbarActions[$action['name']] ?? null; + } else { + $resolvedAction = $this->cachedTreeActions[$action['name']] ?? null; + } + + if ($resolvedAction) { + + if (filled($action['context']['recordKey'] ?? null)) { + $record = $this->getTreeRecord($action['context']['recordKey']); - return $resolvedAction; + $resolvedAction->getRootGroup()?->record($record) ?? $resolvedAction->record($record); + } + + return $resolvedAction; + } + } } @@ -39,30 +58,60 @@ protected function resolveAction(array $action, array $parentActions): ?Filament public function cacheTreeActions(): void { $this->cachedTreeActions = []; + $this->cachedTreeToolbarActions = []; - $actions = Action::configureUsing( - Closure::fromCallable([$this, 'configureTreeAction']), - fn (): array => $this->getTreeActions(), - ); + $configuringTreeActions = function ($actions, $extraArgs = []) { - foreach ($actions as $index => $action) { - if ($action instanceof ActionGroup) { - foreach ($action->getActions() as $groupedAction) { - $groupedAction->tree($this->getCachedTree()); - } + $configureResolvedAction = function ($action) use ($extraArgs) { - $this->cachedTreeActions[$index] = $action; + if (! empty($extraArgs) && method_exists($action, 'arguments')) { + $action = $action->arguments($extraArgs); + } - continue; - } + // Set tree on action + if (method_exists($action, 'tree')) { + $action = $action->tree($this->getCachedTree()); + } + // Set livewire on action + else { + $action = $action->livewire($this); + } - $action->tree($this->getCachedTree()); + return $action; + }; + + return collect($actions) + ->whereInstanceOf([ + ActionGroup::class, + Action::class, + FilamentActionsAction::class, + ]) + ->flatMap(function (ActionGroup|Action|FilamentActionsAction $action) { + if ($action instanceof ActionGroup) { + return $action->getFlatActions(); + } + + return [$action]; + }) + // Configure action + ->map(fn (Action|FilamentActionsAction $action) => $action->configureUsing( + Closure::fromCallable([$this, 'configureTreeAction']), + fn () => $action->configure(), + ) + ) + // Key by action name (resolve used) + ->mapWithKeys(fn (Action|FilamentActionsAction $action) => [ + $action->getName() => $configureResolvedAction($action), + ]) + ->all(); + }; + + $this->cachedTreeActions = $configuringTreeActions($this->getCachedTree()->getActions()); + $this->cachedTreeToolbarActions = $configuringTreeActions($this->getCachedTree()->getToolbarActions(), ['treeToolbar' => true]); - $this->cachedTreeActions[$action->getName()] = $action; - } } - protected function configureTreeAction(Action $action): void {} + protected function configureTreeAction(Action|FilamentActionsAction $action): void {} /** * @deprecated Use `callMountedAction()` instead. @@ -98,6 +147,11 @@ public function getCachedTreeActions(): array return $this->cachedTreeActions; } + public function getCachedTreeToolbarActions(): array + { + return $this->cachedTreeToolbarActions; + } + /** * @deprecated Use `getMountedAction()` instead. */ @@ -232,6 +286,11 @@ protected function getTreeActions(): array return []; } + protected function getTreeToolbarActions(): array + { + return []; + } + protected function getTreeActionsPosition(): ?string { return null; diff --git a/src/Concern/InteractWithTree.php b/src/Concern/InteractWithTree.php index 6edf38d..e31163f 100644 --- a/src/Concern/InteractWithTree.php +++ b/src/Concern/InteractWithTree.php @@ -16,28 +16,33 @@ trait InteractWithTree use HasHeading; use HasRecords; - protected bool $hasMounted = false; + // protected bool $hasMounted = false; protected Tree $tree; public function bootInteractWithTree() { - $tree = $this->getTree(); - $this->tree = $tree->configureUsing( + $this->tree = Tree::configureUsing( Closure::fromCallable([static::class, 'tree']), - fn (): Tree => static::tree($tree)->maxDepth(static::getMaxDepth()), + fn (): Tree => $this->makeTree() + ->maxDepth(static::getMaxDepth()) ); - $this->cacheTreeActions(); - $this->cacheTreeEmptyStateActions(); + // Fill actions and toolbar actions if not set in the tree configurator + if (empty($this->tree->getActions())) { + $this->tree->actions($this->getTreeActions()); + } + if (empty($this->tree->getToolbarActions())) { + $this->tree->toolbarActions($this->getTreeToolbarActions()); + } - $this->tree->actions(array_values($this->getCachedTreeActions())); + $this->cacheTreeActions(); - if ($this->hasMounted) { - return; - } + // if ($this->hasMounted) { + // return; + // } - $this->hasMounted = true; + // $this->hasMounted = true; } public function mountInteractsWithTree(): void {} @@ -47,7 +52,15 @@ protected function getCachedTree(): Tree return $this->tree; } + /** + * @deprecated Use makeTree() instead. + */ protected function getTree(): Tree + { + return $this->makeTree(); + } + + protected function makeTree(): Tree { return Tree::make($this); } diff --git a/src/Concern/TreePageTrait.php b/src/Concern/TreePageTrait.php index ae8e364..564b36f 100644 --- a/src/Concern/TreePageTrait.php +++ b/src/Concern/TreePageTrait.php @@ -5,7 +5,7 @@ use Filament\Actions\Action as FilamentActionsAction; use Filament\Actions\CreateAction; use Filament\Schemas\Components\Component; -use SolutionForest\FilamentTree\Actions; +use SolutionForest\FilamentTree\Actions\Action; use SolutionForest\FilamentTree\Actions\DeleteAction; use SolutionForest\FilamentTree\Actions\EditAction; use SolutionForest\FilamentTree\Actions\ViewAction; @@ -96,7 +96,7 @@ protected function configureAction(FilamentActionsAction $action): void }; } - protected function configureTreeAction(Actions\Action $action): void + protected function configureTreeAction(Action|FilamentActionsAction $action): void { match (true) { $action instanceof DeleteAction => $this->configureDeleteAction($action), @@ -127,9 +127,9 @@ protected function configureCreateAction(CreateAction $action): CreateAction protected function configureDeleteAction(DeleteAction $action): DeleteAction { - $action->tree($this->getCachedTree()); + // $action->tree($this->getCachedTree()); - $action->iconButton(); + $action->iconButton()->icon(fn () => $action->getGroupedIcon()); $this->afterConfiguredDeleteAction($action); @@ -138,9 +138,9 @@ protected function configureDeleteAction(DeleteAction $action): DeleteAction protected function configureEditAction(EditAction $action): EditAction { - $action->tree($this->getCachedTree()); + // $action->tree($this->getCachedTree()); - $action->iconButton(); + $action->iconButton()->icon(fn () => $action->getGroupedIcon()); $schema = $this->getEditFormSchema(); @@ -152,7 +152,7 @@ protected function configureEditAction(EditAction $action): EditAction $action->model($this->getModel()); - $action->mutateFormDataBeforeSaveUsing(fn (array $data) => $this->mutateFormDataBeforeSave($data)); + // $action->mutateFormDataBeforeSaveUsing(fn (array $data) => $this->mutateFormDataBeforeSave($data)); $this->afterConfiguredEditAction($action); @@ -161,9 +161,9 @@ protected function configureEditAction(EditAction $action): EditAction protected function configureViewAction(ViewAction $action): ViewAction { - $action->tree($this->getCachedTree()); + // $action->tree($this->getCachedTree()); - $action->iconButton(); + $action->iconButton()->icon(fn () => $action->getGroupedIcon()); $schema = $this->getViewFormSchema(); @@ -242,10 +242,10 @@ protected function getActions(): array ); } - protected function mutateFormDataBeforeSave(array $data): array - { - return $data; - } + // protected function mutateFormDataBeforeSave(array $data): array + // { + // return $data; + // } // protected function callHook(string $hook): void // { diff --git a/src/Widgets/Tree.php b/src/Widgets/Tree.php index a905a53..73ab3a3 100644 --- a/src/Widgets/Tree.php +++ b/src/Widgets/Tree.php @@ -2,9 +2,12 @@ namespace SolutionForest\FilamentTree\Widgets; +use Filament\Actions\Action as FilamentActionsAction; +use Filament\Actions\CreateAction as FilamentActionsCreateAction; use Filament\Support\Contracts\TranslatableContentDriver; use Illuminate\Database\Eloquent\Model; use SolutionForest\FilamentTree\Actions\Action; +use SolutionForest\FilamentTree\Actions\CreateAction; use SolutionForest\FilamentTree\Actions\DeleteAction; use SolutionForest\FilamentTree\Actions\EditAction; use SolutionForest\FilamentTree\Actions\ViewAction; @@ -49,6 +52,11 @@ protected function getFormSchema(): array return []; } + protected function getCreateFormSchema(): array + { + return []; + } + protected function getViewFormSchema(): array { return []; @@ -68,9 +76,11 @@ protected function getTreeActions(): array ); } - protected function configureTreeAction(Action $action): void + protected function configureTreeAction(Action|FilamentActionsAction $action): void { match (true) { + $action instanceof CreateAction, => $this->configureCreateAction($action), + $action instanceof FilamentActionsCreateAction => $this->configureCreateAction($action), $action instanceof DeleteAction => $this->configureDeleteAction($action), $action instanceof EditAction => $this->configureEditAction($action), $action instanceof ViewAction => $this->configureViewAction($action), @@ -110,20 +120,37 @@ protected function getViewAction(): ViewAction protected function configureDeleteAction(DeleteAction $action): DeleteAction { - $action->tree($this->getCachedTree()); + // $action->tree($this->getCachedTree()); - $action->iconButton(); + $action->iconButton()->icon(fn () => $action->getGroupedIcon()); $this->afterConfiguredDeleteAction($action); return $action; } + protected function configureCreateAction(FilamentActionsCreateAction|CreateAction $action): FilamentActionsCreateAction|CreateAction + { + $schema = $this->getCreateFormSchema(); + + if (empty($schema)) { + $schema = $this->getFormSchema(); + } + + $action->schema($schema); + + $action->model($this->getModel()); + + $this->afterConfiguredCreateAction($action); + + return $action; + } + protected function configureEditAction(EditAction $action): EditAction { - $action->tree($this->getCachedTree()); + // $action->tree($this->getCachedTree()); - $action->iconButton(); + $action->iconButton()->icon(fn () => $action->getGroupedIcon()); $schema = $this->getEditFormSchema(); @@ -142,9 +169,9 @@ protected function configureEditAction(EditAction $action): EditAction protected function configureViewAction(ViewAction $action): ViewAction { - $action->tree($this->getCachedTree()); + // $action->tree($this->getCachedTree()); - $action->iconButton(); + $action->iconButton()->icon(fn () => $action->getGroupedIcon()); $schema = $this->getViewFormSchema(); @@ -172,6 +199,11 @@ protected function afterConfiguredDeleteAction(DeleteAction $action): DeleteActi return $action; } + protected function afterConfiguredCreateAction(FilamentActionsCreateAction|CreateAction $action): FilamentActionsCreateAction|CreateAction + { + return $action; + } + protected function afterConfiguredEditAction(EditAction $action): EditAction { return $action;