From 16c2189838635812c34a8d876ee3c87cecb4ba65 Mon Sep 17 00:00:00 2001 From: Dennis Elsinga Date: Sat, 18 Nov 2023 17:20:24 +0100 Subject: [PATCH 1/3] Introduce disabled options --- resources/css/custom.css | 10 +++++++++- resources/dist/custom.css | 2 +- src/SelectTree.php | 17 ++++++++++++++++- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/resources/css/custom.css b/resources/css/custom.css index 1cf64f2..97b9a7f 100644 --- a/resources/css/custom.css +++ b/resources/css/custom.css @@ -183,7 +183,7 @@ html.dark .treeselect-list__item-checkbox-container { } .treeselect-input__tags-element:hover .treeselect-input__tags-cross svg { - stroke: rgba(var(--gray-950),var(--tw-text-opacity)); + stroke: rgba(var(--gray-950), var(--tw-text-opacity)); } html.dark .treeselect-input__tags-element:hover .treeselect-input__tags-cross svg { @@ -238,3 +238,11 @@ html.dark .treeselect--disabled { .treeselect--disabled .treeselect-input__clear { display: none; } + +.treeselect-list__item--disabled { + cursor: not-allowed !important; +} + +html.dark .treeselect-list__item--disabled .treeselect-list__item-checkbox-container { + background-color: hsl(0deg 0% 30.77% / 5%); +} diff --git a/resources/dist/custom.css b/resources/dist/custom.css index 4eeb274..108da52 100644 --- a/resources/dist/custom.css +++ b/resources/dist/custom.css @@ -1 +1 @@ -.treeselect-input{background:transparent;border-style:none;color:rgba(var(--gray-950),var(--tw-text-opacity));font-size:.875rem;line-height:1.5rem;outline:2px solid transparent;outline-offset:2px;transition-duration:75ms}.treeselect{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);--tw-ring-color:rgba(var(--gray-950),0.1);background:#fff;border-radius:.5rem!important;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}html.dark .treeselect{--tw-text-opacity:1;--tw-ring-color:hsla(0,0%,100%,.2);background-color:hsla(0,0%,100%,.05)}html.dark .treeselect>.treeselect-input{color:rgb(255 255 255/var(--tw-text-opacity))!important}.treeselect-input--opened.treeselect-input--bottom{border:inherit;border-radius:inherit}.treeselect-input__edit{background:transparent}.treeselect-input__tags-count{margin-left:9px}.treeselect-list{--tw-bg-opacity:1;--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--tw-ring-color:rgba(var(--gray-950),0.05);background-color:rgb(255 255 255/var(--tw-bg-opacity));border:none;border-radius:.5rem;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);font-size:.875rem;line-height:1.25rem;margin-top:.5rem;padding:.25rem}.treeselect-input--focused,.treeselect-list{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.treeselect-input--focused{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) rgba(var(--primary-600),var(--tw-text-opacity))}.treeselect-list__item{border-radius:.475rem;padding:1.1rem}.treeselect-list.treeselect-list--single-select .treeselect-list__item--single-selected,.treeselect-list__item--focused,.treeselect-list__item:hover{--tw-bg-opacity:1;background-color:rgba(var(--gray-50),var(--tw-bg-opacity))!important}.treeselect-list.treeselect-list--single-select .treeselect-list__item--single-selected{font-weight:500}html.dark .treeselect-list{-tw-bg-opacity:1;--tw-ring-color:hsla(0,0%,100%,.1);background-color:rgba(var(--gray-900),var(--tw-bg-opacity))}.treeselect-input__edit{--tw-ring-color:none!important;--tw-ring-shadow:none!important;border:transparent!important}html.dark .treeselect-list.treeselect-list--single-select .treeselect-list__item--single-selected,html.dark .treeselect-list.treeselect-list--single-select html.dark.treeselect-list__item--single-selected,html.dark .treeselect-list__item--focused,html.dark .treeselect-list__item:hover{background-color:hsla(0,0%,100%,.05)!important}.treeselect-list__item--checked,html.dark .treeselect-list__item--checked{background:transparent}.treeselect-input__tags-element{--tw-bg-opacity:1;--tw-text-opacity:1;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--tw-ring-inset:inset;--tw-ring-color:rgba(var(--primary-600),0.1);align-items:center;background-color:rgba(var(--primary-50),var(--tw-bg-opacity));border-radius:.375rem;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);display:inline-flex;font-size:.75rem;font-weight:500;gap:.25rem;line-height:1rem;padding:.25rem .5rem;word-break:break-all}html.dark .treeselect-input__tags-element{--tw-text-opacity:1;--tw-ring-color:rgba(var(--primary-400),0.3);background-color:rgba(var(--primary-400),.1)}.treeselect-list__item-checkbox-container{border-radius:.25rem;height:16px;min-width:16px;width:16px}.treeselect-list__item--checked .treeselect-list__item-checkbox-container,.treeselect-list__item--partial-checked .treeselect-list__item-checkbox-container{background-color:rgba(var(--primary-600),var(--tw-text-opacity))}.treeselect-list__item-checkbox{background-color:transparent!important;border:none;transition-duration:75ms}.treeselect-list__item-checkbox-container{background-color:#f8f5f5;border:none}html.dark .treeselect-list__item-checkbox-container{background-color:hsla(0,0%,100%,.05);border:rgb(255 255 255/var(--tw-text-opacity))}.treeselect-list__item-checkbox-icon{height:80%;left:.1rem;top:.1rem;width:80%}.treeselect-input__tags-element:hover{background-color:rgba(var(--primary-50),var(--tw-bg-opacity))}.treeselect-input__tags-element:hover .treeselect-input__tags-cross svg{stroke:rgba(var(--gray-950),var(--tw-text-opacity))}html.dark .treeselect-input__tags-element:hover .treeselect-input__tags-cross svg{stroke:rgb(255 255 255/var(--tw-text-opacity))}.treeselect-input__tags-element{color:rgba(var(--primary-600),var(--tw-text-opacity))}html.dark .treeselect-input__tags-element{color:rgba(var(--primary-400),var(--tw-text-opacity))}html.dark .treeselect-input__tags-cross svg{stroke-width:3px;stroke:rgb(255 255 255/var(--tw-text-opacity));opacity:.5}html.dark .treeselect-input__tags-element:hover svg{opacity:.6}.treeselect-input__clear svg{opacity:.5}.treeselect-input__tags{margin-left:3px}html.dark .treeselect--disabled{background-color:#09090b}.treeselect--disabled{background-color:#fafafa}.treeselect--disabled .treeselect-input__arrow,.treeselect--disabled .treeselect-input__clear,.treeselect--disabled .treeselect-input__tags-cross{display:none} \ No newline at end of file +.treeselect-input{background:transparent;border-style:none;color:rgba(var(--gray-950),var(--tw-text-opacity));font-size:.875rem;line-height:1.5rem;outline:2px solid transparent;outline-offset:2px;transition-duration:75ms}.treeselect{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);--tw-ring-color:rgba(var(--gray-950),0.1);background:#fff;border-radius:.5rem!important;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}html.dark .treeselect{--tw-text-opacity:1;--tw-ring-color:hsla(0,0%,100%,.2);background-color:hsla(0,0%,100%,.05)}html.dark .treeselect>.treeselect-input{color:rgb(255 255 255/var(--tw-text-opacity))!important}.treeselect-input--opened.treeselect-input--bottom{border:inherit;border-radius:inherit}.treeselect-input__edit{background:transparent}.treeselect-input__tags-count{margin-left:9px}.treeselect-list{--tw-bg-opacity:1;--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--tw-ring-color:rgba(var(--gray-950),0.05);background-color:rgb(255 255 255/var(--tw-bg-opacity));border:none;border-radius:.5rem;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);font-size:.875rem;line-height:1.25rem;margin-top:.5rem;padding:.25rem}.treeselect-input--focused,.treeselect-list{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.treeselect-input--focused{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) rgba(var(--primary-600),var(--tw-text-opacity))}.treeselect-list__item{border-radius:.475rem;padding:1.1rem}.treeselect-list.treeselect-list--single-select .treeselect-list__item--single-selected,.treeselect-list__item--focused,.treeselect-list__item:hover{--tw-bg-opacity:1;background-color:rgba(var(--gray-50),var(--tw-bg-opacity))!important}.treeselect-list.treeselect-list--single-select .treeselect-list__item--single-selected{font-weight:500}html.dark .treeselect-list{-tw-bg-opacity:1;--tw-ring-color:hsla(0,0%,100%,.1);background-color:rgba(var(--gray-900),var(--tw-bg-opacity))}.treeselect-input__edit{--tw-ring-color:none!important;--tw-ring-shadow:none!important;border:transparent!important}html.dark .treeselect-list.treeselect-list--single-select .treeselect-list__item--single-selected,html.dark .treeselect-list.treeselect-list--single-select html.dark.treeselect-list__item--single-selected,html.dark .treeselect-list__item--focused,html.dark .treeselect-list__item:hover{background-color:hsla(0,0%,100%,.05)!important}.treeselect-list__item--checked,html.dark .treeselect-list__item--checked{background:transparent}.treeselect-input__tags-element{--tw-bg-opacity:1;--tw-text-opacity:1;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--tw-ring-inset:inset;--tw-ring-color:rgba(var(--primary-600),0.1);align-items:center;background-color:rgba(var(--primary-50),var(--tw-bg-opacity));border-radius:.375rem;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);display:inline-flex;font-size:.75rem;font-weight:500;gap:.25rem;line-height:1rem;padding:.25rem .5rem;word-break:break-all}html.dark .treeselect-input__tags-element{--tw-text-opacity:1;--tw-ring-color:rgba(var(--primary-400),0.3);background-color:rgba(var(--primary-400),.1)}.treeselect-list__item-checkbox-container{border-radius:.25rem;height:16px;min-width:16px;width:16px}.treeselect-list__item--checked .treeselect-list__item-checkbox-container,.treeselect-list__item--partial-checked .treeselect-list__item-checkbox-container{background-color:rgba(var(--primary-600),var(--tw-text-opacity))}.treeselect-list__item-checkbox{background-color:transparent!important;border:none;transition-duration:75ms}.treeselect-list__item-checkbox-container{background-color:#f8f5f5;border:none}html.dark .treeselect-list__item-checkbox-container{background-color:hsla(0,0%,100%,.05);border:rgb(255 255 255/var(--tw-text-opacity))}.treeselect-list__item-checkbox-icon{height:80%;left:.1rem;top:.1rem;width:80%}.treeselect-input__tags-element:hover{background-color:rgba(var(--primary-50),var(--tw-bg-opacity))}.treeselect-input__tags-element:hover .treeselect-input__tags-cross svg{stroke:rgba(var(--gray-950),var(--tw-text-opacity))}html.dark .treeselect-input__tags-element:hover .treeselect-input__tags-cross svg{stroke:rgb(255 255 255/var(--tw-text-opacity))}.treeselect-input__tags-element{color:rgba(var(--primary-600),var(--tw-text-opacity))}html.dark .treeselect-input__tags-element{color:rgba(var(--primary-400),var(--tw-text-opacity))}html.dark .treeselect-input__tags-cross svg{stroke-width:3px;stroke:rgb(255 255 255/var(--tw-text-opacity));opacity:.5}html.dark .treeselect-input__tags-element:hover svg{opacity:.6}.treeselect-input__clear svg{opacity:.5}.treeselect-input__tags{margin-left:3px}html.dark .treeselect--disabled{background-color:#09090b}.treeselect--disabled{background-color:#fafafa}.treeselect--disabled .treeselect-input__arrow,.treeselect--disabled .treeselect-input__clear,.treeselect--disabled .treeselect-input__tags-cross{display:none}.treeselect-list__item--disabled{cursor:not-allowed!important}html.dark .treeselect-list__item--disabled .treeselect-list__item-checkbox-container{background-color:rgba(78,78,78,.05)} \ No newline at end of file diff --git a/src/SelectTree.php b/src/SelectTree.php index 12a432f..9905cc0 100644 --- a/src/SelectTree.php +++ b/src/SelectTree.php @@ -49,6 +49,8 @@ class SelectTree extends Field protected string $direction = 'auto'; + protected array $disabledOptions = []; + protected function setUp(): void { // Load the state from relationships using a callback function. @@ -118,7 +120,7 @@ private function buildTreeFromResults($results, $parent = null): Collection // Group results by their parent IDs foreach ($results as $result) { $parentId = $result->{$this->getParentAttribute()}; - if (! isset($resultMap[$parentId])) { + if (!isset($resultMap[$parentId])) { $resultMap[$parentId] = []; } $resultMap[$parentId][] = $result; @@ -141,6 +143,7 @@ private function buildNode($result, $resultMap): array $node = [ 'name' => $result->{$this->getTitleAttribute()}, 'value' => $result->id, + 'disabled' => in_array($result->id, $this->getDisabledOptions()) ]; // Check if the result has children @@ -251,6 +254,13 @@ public function independent(bool $independent = true): static return $this; } + public function disabledOptions(array $disabledOptions = []): static + { + $this->disabledOptions = $disabledOptions; + + return $this; + } + public function alwaysOpen(bool $alwaysOpen = true): static { $this->alwaysOpen = $alwaysOpen; @@ -324,4 +334,9 @@ public function getDirection(): string { return $this->evaluate($this->direction); } + + public function getDisabledOptions(): array + { + return $this->evaluate($this->disabledOptions); + } } From 7ec22792d8477680c6b202e735175593570162b0 Mon Sep 17 00:00:00 2001 From: CodeWithDennis Date: Sat, 18 Nov 2023 16:20:55 +0000 Subject: [PATCH 2/3] Fix styling --- src/SelectTree.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SelectTree.php b/src/SelectTree.php index 9905cc0..7760e57 100644 --- a/src/SelectTree.php +++ b/src/SelectTree.php @@ -120,7 +120,7 @@ private function buildTreeFromResults($results, $parent = null): Collection // Group results by their parent IDs foreach ($results as $result) { $parentId = $result->{$this->getParentAttribute()}; - if (!isset($resultMap[$parentId])) { + if (! isset($resultMap[$parentId])) { $resultMap[$parentId] = []; } $resultMap[$parentId][] = $result; @@ -143,7 +143,7 @@ private function buildNode($result, $resultMap): array $node = [ 'name' => $result->{$this->getTitleAttribute()}, 'value' => $result->id, - 'disabled' => in_array($result->id, $this->getDisabledOptions()) + 'disabled' => in_array($result->id, $this->getDisabledOptions()), ]; // Check if the result has children From 93c8035c91c861eeb349d0b782607c6998c16ee9 Mon Sep 17 00:00:00 2001 From: Dennis Elsinga Date: Sat, 18 Nov 2023 17:27:57 +0100 Subject: [PATCH 3/3] Add documentation --- README.md | 16 ++++++++++++++++ src/SelectTree.php | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 823835e..e01a55d 100644 --- a/README.md +++ b/README.md @@ -156,6 +156,22 @@ Activate the search functionality ->searchable(); ``` +Disable specific options in the tree + +```PHP +->disabledOptions([2, 3, 4]) +``` + +```PHP +->disabledOptions(function () { + return Category::where('is_disabled', true) + ->get() + ->pluck('id') + ->toArray(); +}) +``` + + ## Screenshots light diff --git a/src/SelectTree.php b/src/SelectTree.php index 7760e57..dea857f 100644 --- a/src/SelectTree.php +++ b/src/SelectTree.php @@ -49,7 +49,7 @@ class SelectTree extends Field protected string $direction = 'auto'; - protected array $disabledOptions = []; + protected Closure|array $disabledOptions = []; protected function setUp(): void { @@ -254,7 +254,7 @@ public function independent(bool $independent = true): static return $this; } - public function disabledOptions(array $disabledOptions = []): static + public function disabledOptions(Closure|array $disabledOptions): static { $this->disabledOptions = $disabledOptions;