├── .github └── dependabot.yml ├── .gitignore ├── README.md ├── composer.json ├── composer.lock ├── config └── tallcraftui.php ├── license.md ├── routes └── web.php └── src ├── Console └── Commands │ └── InstallTallcraftuiCommand.php ├── Enums ├── BorderRadius.php ├── DropdownAnimation.php ├── DropdownPosition.php ├── Position.php ├── Shadow.php ├── Size.php ├── ToastPosition.php └── Width.php ├── Helpers ├── BorderRadiusHelper.php ├── HeightHelper.php ├── ShadowHelper.php └── WidthHelper.php ├── TallCraftUiServiceProvider.php ├── Traits ├── AvatarTrait.php ├── AvatarsTrait.php ├── Borders │ └── HasInputBorders.php ├── CardTrait.php ├── Colors │ ├── HasAlertColors.php │ ├── HasBadgeColors.php │ ├── HasButtonColors.php │ ├── HasCheckboxColors.php │ ├── HasColorAttributes.php │ ├── HasProgressColors.php │ ├── HasProgressRadialColors.php │ ├── HasRadioColors.php │ ├── HasRangeColors.php │ └── HasStatColors.php ├── HasDropdownPosition.php ├── HasMarkdownImages.php ├── ModalTrait.php ├── Sizes │ ├── HasBadgeSizes.php │ ├── HasButtonSizes.php │ ├── HasCheckboxSizes.php │ ├── HasDrawerSizes.php │ ├── HasInputSizes.php │ ├── HasNativeSelectSizes.php │ ├── HasProgressRadialSizes.php │ ├── HasProgressSizes.php │ ├── HasRadioSizes.php │ ├── HasRatingSizes.php │ └── HasSelectSizes.php ├── SpinnerTrait.php ├── ToggleTrait.php ├── WithTcTable.php └── WithTcToast.php ├── View └── Components │ ├── Accordion │ ├── Accordion.php │ └── AccordionItem.php │ ├── Alert.php │ ├── Avatar.php │ ├── Avatars.php │ ├── Badge.php │ ├── Breadcrumb.php │ ├── BreadcrumbItem.php │ ├── Button.php │ ├── Card │ ├── Card.php │ ├── CardContent.php │ ├── CardFigure.php │ ├── CardFooter.php │ └── CardHeader.php │ ├── Checkbox.php │ ├── Clipboard.php │ ├── ColorPicker.php │ ├── Drawer.php │ ├── Dropdown.php │ ├── DropdownItem.php │ ├── Hint.php │ ├── Icon.php │ ├── Input.php │ ├── Label.php │ ├── Markdown.php │ ├── Menu.php │ ├── MenuItem.php │ ├── Modal.php │ ├── NativeSelect.php │ ├── Password.php │ ├── Progress.php │ ├── ProgressRadial.php │ ├── Radio.php │ ├── Range.php │ ├── Rating.php │ ├── Select.php │ ├── Separator.php │ ├── Spinner.php │ ├── Stat.php │ ├── Tab │ ├── Tab.php │ ├── TabContent.php │ └── TabItem.php │ ├── Table │ ├── Index.php │ ├── NotFound.php │ ├── Td.php │ ├── Th.php │ └── Tr.php │ ├── Textarea.php │ ├── Toast.php │ ├── Toggle.php │ └── Tooltip.php └── resources └── css └── tallcraftui.css /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "composer" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | TODO.md -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Screenshot](https://tallcraftui.developermithu.com/assets/img/tallcraftui-website.png "Official Documentation Site")](https://tallcraftui.developermithu.com) 2 | 3 |

4 | Latest Version on Packagist 5 | Total Downloads 6 | GitHub license 7 |

8 | 9 | 10 | ## 🚀 Introduction 11 | 12 | [TallCraftUI](https://tallcraftui.developermithu.com) is a Laravel blade UI components library built on the [TALL Stack](https://tallstack.dev), providing **pre-built**, **customizable components** that seamlessly integrate with [Livewire](https://livewire.laravel.com) to create modern, responsive applications with **minimal effort**. 13 | 14 | 15 | ## 📚 Documentation 16 | 17 | For complete documentation, please visit the official [TallCraftUI](https://tallcraftui.developermithu.com) website. 18 | 19 | 20 | ## 🔗 Discord 21 | 22 | Join our [Discord](https://discord.gg/gmFTB9YRV6) community. 23 | 24 | ## 🔧 Contributing 25 | We appreciate your willingness to contribute to **TallCraftUI**. You can find the contribution guidelines in the [documentation site](https://tallcraftui.developermithu.com/docs/how-to-contribute). 26 | 27 | ## 📝 License 28 | 29 | TallCraftUI is open-sourced software licensed under the [MIT license](https://github.com/developermithu/tallcraftui?tab=MIT-1-ov-file) 30 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "developermithu/tallcraftui", 3 | "description": "TallCraftUI is a Laravel blade UI components library built on TALL stack", 4 | "type": "library", 5 | "license": "MIT", 6 | "keywords": [ 7 | "tallcraftui", 8 | "laravel", 9 | "livewire", 10 | "livewire 3", 11 | "tailwindcss", 12 | "alpinejs", 13 | "tallstackui", 14 | "tallstack ui components", 15 | "blade components", 16 | "blade ui components", 17 | "laravel blade ui components", 18 | "livewire ui components", 19 | "livewire packages", 20 | "livewire ui library", 21 | "laravel ui library", 22 | "ui components" 23 | ], 24 | "authors": [ 25 | { 26 | "name": "developermithu", 27 | "email": "developermithu@gmail.com", 28 | "homepage": "https://github.com/developermithu" 29 | } 30 | ], 31 | "homepage": "https://tallcraftui.developermithu.com", 32 | "require": { 33 | "illuminate/support": "^10.0|^11.0|^12.0", 34 | "blade-ui-kit/blade-heroicons": "^2.6", 35 | "gehrisandro/tailwind-merge-laravel": "^1.3" 36 | }, 37 | "require-dev": { 38 | "laravel/pint": "^1.21" 39 | }, 40 | "autoload": { 41 | "psr-4": { 42 | "Developermithu\\Tallcraftui\\": "src/" 43 | } 44 | }, 45 | "extra": { 46 | "laravel": { 47 | "providers": [ 48 | "Developermithu\\Tallcraftui\\TallCraftUiServiceProvider" 49 | ] 50 | } 51 | }, 52 | "minimum-stability": "dev", 53 | "prefer-stable": true 54 | } 55 | -------------------------------------------------------------------------------- /config/tallcraftui.php: -------------------------------------------------------------------------------- 1 | '' // 25 | * 'prefix' => 'tc-' // 26 | */ 27 | 'prefix' => env('TALLCRAFTUI_PREFIX', ''), 28 | 29 | /** 30 | * -------------------------------------------------------------------------- 31 | * Route Prefix 32 | * -------------------------------------------------------------------------- 33 | */ 34 | 'route_prefix' => env('TALLCRAFTUI_ROUTE_PREFIX', 'tallcraftui'), 35 | 36 | /** 37 | * -------------------------------------------------------------------------- 38 | * Icon Configuration 39 | * -------------------------------------------------------------------------- 40 | * 41 | * The default icon settings for the components. You can specify the type 42 | * and style of icons that should be used. 43 | * 44 | * type => Allowed: heroicons 45 | * style => Allowed: outline, solid 46 | */ 47 | 'icons' => [ 48 | 'type' => 'heroicons', 49 | 'style' => 'outline', 50 | ], 51 | 52 | /** 53 | * -------------------------------------------------------------------------- 54 | * UI Components 55 | * -------------------------------------------------------------------------- 56 | * 57 | * Configure the appearance and behavior of ui components. 58 | */ 59 | 'avatar' => [ 60 | 'border-radius' => BorderRadius::RoundedFull->value, 61 | ], 62 | 63 | 'alert' => [ 64 | 'border-radius' => BorderRadius::RoundedSm->value, 65 | ], 66 | 67 | 'badge' => [ 68 | 'border-radius' => BorderRadius::RoundedSm->value, 69 | ], 70 | 71 | 'breadcrumb' => [ 72 | 'border-radius' => BorderRadius::RoundedSm->value, 73 | ], 74 | 75 | 'button' => [ 76 | 'size' => Size::MD->value, 77 | 'border-radius' => BorderRadius::RoundedSm->value, 78 | ], 79 | 80 | 'card' => [ 81 | 'shadow' => Shadow::ShadowXs->value, 82 | 'border-radius' => BorderRadius::RoundedLg->value, 83 | ], 84 | 85 | 'dropdown' => [ 86 | 'width' => Width::W48->value, 87 | 'shadow' => Shadow::ShadowSm->value, 88 | 'position' => DropdownPosition::BOTTOM_END->value, 89 | 'animation' => DropdownAnimation::FADE->value, 90 | 'border-radius' => BorderRadius::RoundedSm->value, 91 | ], 92 | 93 | 'drawer' => [ 94 | 'width' => 'lg', // Allowed: sm, md, lg, xl, 2xl, 3xl, 4xl, 5xl, 6xl, 7xl, full 95 | 'blur' => false, 96 | 'trap-focus' => true, 97 | ], 98 | 99 | 'modal' => [ 100 | 'size' => Size::LG->value, 101 | 'blur' => false, // Allowed: true, false 102 | 'trap-focus' => true, // Allowed: true, false 103 | 'position' => Position::TOP->value, 104 | 'border-radius' => BorderRadius::RoundedLg->value, 105 | ], 106 | 107 | 'progress' => [ 108 | 'size' => Size::MD->value, 109 | ], 110 | 111 | 'stat' => [ 112 | 'border-radius' => BorderRadius::RoundedLg->value, 113 | ], 114 | 115 | 'table' => [ 116 | 'shadow' => Shadow::ShadowNone->value, 117 | 'border-radius' => BorderRadius::RoundedLg->value, 118 | ], 119 | 120 | 'tooltip' => [ 121 | 'position' => Position::TOP->value, 122 | 'gradient' => false, 123 | 'noArrow' => false, 124 | 'noTransition' => false, 125 | ], 126 | 127 | 'toast' => [ 128 | 'position' => ToastPosition::BOTTOM_RIGHT->value, 129 | 'showCloseIcon' => false, 130 | 'showProgress' => false, 131 | 'timeout' => 3000, 132 | ], 133 | 134 | 'menu' => [ 135 | 'width' => Width::W56->value, 136 | 'shadow' => Shadow::ShadowSm->value, 137 | 'border-radius' => BorderRadius::RoundedMd->value, 138 | ], 139 | 140 | /** 141 | * -------------------------------------------------------------------------- 142 | * Form Components 143 | * -------------------------------------------------------------------------- 144 | * 145 | * Configure the appearance and behavior of form components. 146 | */ 147 | 'checkbox' => [ 148 | 'size' => Size::MD->value, 149 | 'border-radius' => BorderRadius::RoundedSm->value, 150 | ], 151 | 152 | 'input' => [ 153 | 'size' => Size::MD->value, 154 | 'border-radius' => BorderRadius::RoundedSm->value, 155 | ], 156 | 157 | 'native-select' => [ 158 | 'size' => Size::MD->value, 159 | 'border-radius' => BorderRadius::RoundedSm->value, 160 | ], 161 | 162 | 'select' => [ 163 | 'size' => Size::MD->value, 164 | ], 165 | 166 | 'radio' => [ 167 | 'size' => Size::MD->value, 168 | ], 169 | 170 | 'rating' => [ 171 | 'size' => Size::MD->value, 172 | ], 173 | 174 | 'textarea' => [ 175 | 'border-radius' => BorderRadius::RoundedSm->value, 176 | ], 177 | 178 | 'toggle' => [ 179 | 'border-radius' => BorderRadius::RoundedSm->value, 180 | ], 181 | 182 | 'markdown' => [ 183 | 'config' => [ 184 | 'spellChecker' => false, 185 | 'autofocus' => false, 186 | 'uploadImage' => false, // add drag & drop image upload feature 187 | 'imageAccept' => 'image/png, image/jpeg, image/gif, image/avif', 188 | 'minHeight' => '150px', 189 | 'maxHeight' => '400px', 190 | 'toolbar' => [ 191 | 'bold', 192 | 'italic', 193 | 'heading', 194 | '|', 195 | 'quote', 196 | 'unordered-list', 197 | 'ordered-list', 198 | '|', 199 | 'link', 200 | // 'image', // display image markdown syntax 201 | 'upload-image', // open browser file window to upload image 202 | 'table', 203 | '|', 204 | 'preview', 205 | 'side-by-side', 206 | 'fullscreen', 207 | '|', 208 | 'guide', 209 | ], 210 | ], 211 | ], 212 | ]; 213 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Developer Mithu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /routes/web.php: -------------------------------------------------------------------------------- 1 | group(function () { 8 | // Authenticated Web Routes 9 | Route::middleware(['web', 'auth'])->group(function () { 10 | Route::post('/upload', function (Request $request) { 11 | $file = $request->file('file'); 12 | $path = $file->store($request->folder, $request->disk); 13 | 14 | return response()->json([ 15 | 'location' => Storage::disk($request->disk)->url($path), 16 | ]); 17 | })->name('tallcraftui.upload'); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /src/Enums/BorderRadius.php: -------------------------------------------------------------------------------- 1 | get('rounded-sm') => 'rounded-sm', 13 | $attributes->get('rounded-xs') => 'rounded-xs', 14 | $attributes->get('rounded-md') => 'rounded-md', 15 | $attributes->get('rounded-lg') => 'rounded-lg', 16 | $attributes->get('rounded-xl') => 'rounded-xl', 17 | $attributes->get('rounded-2xl') => 'rounded-2xl', 18 | $attributes->get('rounded-3xl') => 'rounded-3xl', 19 | $attributes->get('rounded-full') => 'rounded-full', 20 | $attributes->get('rounded-none') => 'rounded-none', 21 | default => config("tallcraftui.{$componentName}.border-radius", 'rounded-sm'), 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Helpers/HeightHelper.php: -------------------------------------------------------------------------------- 1 | get('h-20') => 'min-h-20!', 13 | $attributes->get('h-24') => 'min-h-24!', 14 | $attributes->get('h-28') => 'min-h-28!', 15 | $attributes->get('h-32') => 'min-h-32!', 16 | $attributes->get('h-36') => 'min-h-36!', 17 | $attributes->get('h-40') => 'min-h-40!', 18 | $attributes->get('h-44') => 'min-h-44!', 19 | $attributes->get('h-48') => 'min-h-48!', 20 | $attributes->get('h-52') => 'min-h-52!', 21 | $attributes->get('h-56') => 'min-h-56!', 22 | $attributes->get('h-60') => 'min-h-60!', 23 | $attributes->get('h-64') => 'min-h-64!', 24 | $attributes->get('h-72') => 'min-h-72!', 25 | $attributes->get('h-80') => 'min-h-80!', 26 | $attributes->get('h-96') => 'min-h-96!', 27 | $attributes->get('h-full') => 'h-full!', 28 | default => config("tallcraftui.{$componentName}.height", 'h-64!'), 29 | }; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Helpers/ShadowHelper.php: -------------------------------------------------------------------------------- 1 | get('shadow-sm') => 'shadow-sm', 13 | $attributes->get('shadow-xs') => 'shadow-xs', 14 | $attributes->get('shadow-md') => 'shadow-md', 15 | $attributes->get('shadow-lg') => 'shadow-lg', 16 | $attributes->get('shadow-xl') => 'shadow-xl', 17 | $attributes->get('shadow-2xl') => 'shadow-2xl', 18 | $attributes->get('shadow-none') => 'shadow-none', 19 | default => config("tallcraftui.{$componentName}.shadow", 'shadow-sm'), 20 | }; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Helpers/WidthHelper.php: -------------------------------------------------------------------------------- 1 | get('w-20') => 'w-20', 13 | $attributes->get('w-24') => 'w-24', 14 | $attributes->get('w-28') => 'w-28', 15 | $attributes->get('w-32') => 'w-32', 16 | $attributes->get('w-36') => 'w-36', 17 | $attributes->get('w-40') => 'w-40', 18 | $attributes->get('w-44') => 'w-44', 19 | $attributes->get('w-48') => 'w-48', 20 | $attributes->get('w-52') => 'w-52', 21 | $attributes->get('w-56') => 'w-56', 22 | $attributes->get('w-60') => 'w-60', 23 | $attributes->get('w-64') => 'w-64', 24 | $attributes->get('w-72') => 'w-72', 25 | $attributes->get('w-80') => 'w-80', 26 | $attributes->get('w-96') => 'w-96', 27 | $attributes->get('w-full') => 'w-full', 28 | default => config("tallcraftui.{$componentName}.width", 'w-48'), 29 | }; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Traits/AvatarTrait.php: -------------------------------------------------------------------------------- 1 | attributes); 12 | } 13 | 14 | public function getAvatarBaseClasses(): string 15 | { 16 | $sizeClasses = match (true) { 17 | $this->attributes->get('sm') => 'size-8 text-xs', 18 | $this->attributes->get('md') => 'size-[38px] text-sm', 19 | $this->attributes->get('lg') => 'size-[46px] text-base', 20 | $this->attributes->get('xl') => 'size-[62px] text-lg', 21 | default => 'size-[38px] text-sm', 22 | }; 23 | 24 | return "{$sizeClasses}"; 25 | } 26 | 27 | public function getBadgeClasses(): string 28 | { 29 | $badgeColors = match (true) { 30 | $this->badgeColor === 'primary' => 'bg-primary', 31 | $this->badgeColor === 'secondary' => 'bg-secondary', 32 | $this->badgeColor === 'black' => 'bg-black', 33 | $this->badgeColor === 'white' => 'bg-white', 34 | $this->badgeColor === 'slate' => 'bg-slate-500', 35 | $this->badgeColor === 'gray' => 'bg-gray-500', 36 | $this->badgeColor === 'zinc' => 'bg-zinc-500', 37 | $this->badgeColor === 'neutral' => 'bg-neutral-500', 38 | $this->badgeColor === 'stone' => 'bg-stone-500', 39 | $this->badgeColor === 'red' => 'bg-red-500', 40 | $this->badgeColor === 'orange' => 'bg-orange-500', 41 | $this->badgeColor === 'amber' => 'bg-amber-500', 42 | $this->badgeColor === 'yellow' => 'bg-yellow-500', 43 | $this->badgeColor === 'lime' => 'bg-lime-500', 44 | $this->badgeColor === 'green' => 'bg-green-500', 45 | $this->badgeColor === 'emerald' => 'bg-emerald-500', 46 | $this->badgeColor === 'teal' => 'bg-teal-500', 47 | $this->badgeColor === 'cyan' => 'bg-cyan-500', 48 | $this->badgeColor === 'sky' => 'bg-sky-500', 49 | $this->badgeColor === 'blue' => 'bg-blue-500', 50 | $this->badgeColor === 'indigo' => 'bg-indigo-500', 51 | $this->badgeColor === 'violet' => 'bg-violet-500', 52 | $this->badgeColor === 'purple' => 'bg-purple-500', 53 | $this->badgeColor === 'fuchsia' => 'bg-fuchsia-500', 54 | $this->badgeColor === 'pink' => 'bg-pink-500', 55 | $this->badgeColor === 'rose' => 'bg-rose-500', 56 | default => 'bg-primary', 57 | }; 58 | 59 | $sizeClasses = match (true) { 60 | $this->attributes->get('sm') => 'size-1.5', 61 | $this->attributes->get('md') => 'size-2.5', 62 | $this->attributes->get('lg') => 'size-3', 63 | $this->attributes->get('xl') => 'size-3.5', 64 | default => 'size-2.5', 65 | }; 66 | 67 | return "absolute block {$sizeClasses} rounded-full {$badgeColors} ring-2"; 68 | } 69 | 70 | public function getRingColor(): string 71 | { 72 | return match ($this->ringColor) { 73 | 'primary' => 'ring-primary', 74 | 'secondary' => 'ring-secondary', 75 | 'black' => 'ring-black', 76 | 'white' => 'ring-white', 77 | 'slate' => 'ring-slate-400', 78 | 'gray' => 'ring-gray-400', 79 | 'zinc' => 'ring-zinc-400', 80 | 'neutral' => 'ring-neutral-400', 81 | 'stone' => 'ring-stone-400', 82 | 'red' => 'ring-red-400', 83 | 'orange' => 'ring-orange-400', 84 | 'amber' => 'ring-amber-400', 85 | 'yellow' => 'ring-yellow-400', 86 | 'lime' => 'ring-lime-400', 87 | 'green' => 'ring-green-400', 88 | 'emerald' => 'ring-emerald-400', 89 | 'teal' => 'ring-teal-400', 90 | 'cyan' => 'ring-cyan-400', 91 | 'sky' => 'ring-sky-400', 92 | 'blue' => 'ring-blue-400', 93 | 'indigo' => 'ring-indigo-400', 94 | 'violet' => 'ring-violet-400', 95 | 'purple' => 'ring-purple-400', 96 | 'fuchsia' => 'ring-fuchsia-400', 97 | 'pink' => 'ring-pink-400', 98 | 'rose' => 'ring-rose-400', 99 | default => 'ring-primary', 100 | }; 101 | } 102 | 103 | public function getBadgePosition(): string 104 | { 105 | $isSquare = $this->roundedClass() !== 'rounded-full'; 106 | 107 | return match ($this->badgePosition) { 108 | 'top' => $isSquare 109 | ? 'top-0 end-0 transform -translate-y-1/2 translate-x-1/2' 110 | : 'top-0 end-0', 111 | 'bottom' => $isSquare 112 | ? 'bottom-0 end-0 transform translate-y-1/2 translate-x-1/2' 113 | : 'bottom-0 end-0', 114 | default => 'top-0 end-0', 115 | }; 116 | } 117 | } -------------------------------------------------------------------------------- /src/Traits/AvatarsTrait.php: -------------------------------------------------------------------------------- 1 | attributes->get('sm') => 'size-8 text-xs', 13 | $this->attributes->get('md') => 'size-[38px] text-sm', 14 | $this->attributes->get('lg') => 'size-[46px] text-base', 15 | $this->attributes->get('xl') => 'size-[62px] text-lg', 16 | default => 'size-[38px] text-sm', 17 | }; 18 | 19 | return "{$sizeClasses}"; 20 | } 21 | 22 | public function getRingColor(): string 23 | { 24 | return match ($this->ringColor) { 25 | 'primary' => 'ring-primary', 26 | 'secondary' => 'ring-secondary', 27 | 'black' => 'ring-black', 28 | 'white' => 'ring-white', 29 | 'slate' => 'ring-slate-400', 30 | 'gray' => 'ring-gray-400', 31 | 'zinc' => 'ring-zinc-400', 32 | 'neutral' => 'ring-neutral-400', 33 | 'stone' => 'ring-stone-400', 34 | 'red' => 'ring-red-400', 35 | 'orange' => 'ring-orange-400', 36 | 'amber' => 'ring-amber-400', 37 | 'yellow' => 'ring-yellow-400', 38 | 'lime' => 'ring-lime-400', 39 | 'green' => 'ring-green-400', 40 | 'emerald' => 'ring-emerald-400', 41 | 'teal' => 'ring-teal-400', 42 | 'cyan' => 'ring-cyan-400', 43 | 'sky' => 'ring-sky-400', 44 | 'blue' => 'ring-blue-400', 45 | 'indigo' => 'ring-indigo-400', 46 | 'violet' => 'ring-violet-400', 47 | 'purple' => 'ring-purple-400', 48 | 'fuchsia' => 'ring-fuchsia-400', 49 | 'pink' => 'ring-pink-400', 50 | 'rose' => 'ring-rose-400', 51 | default => 'ring-primary', 52 | }; 53 | } 54 | 55 | public function roundedClass(): string 56 | { 57 | return BorderRadiusHelper::getRoundedClass('avatar', $this->attributes); 58 | } 59 | } -------------------------------------------------------------------------------- /src/Traits/Borders/HasInputBorders.php: -------------------------------------------------------------------------------- 1 | attributes); 12 | } 13 | 14 | public function getPrefixRoundClasses() 15 | { 16 | return match (true) { 17 | $this->attributes->get('rounded-none') => 'rounded-s-none', 18 | $this->attributes->get('rounded-xs') => 'rounded-s-sm', 19 | $this->attributes->get('rounded-md') => 'rounded-s-md', 20 | $this->attributes->get('rounded-lg') => 'rounded-s-lg', 21 | $this->attributes->get('rounded-xl') => 'rounded-s-xl', 22 | $this->attributes->get('rounded-2xl') => 'rounded-s-2xl', 23 | $this->attributes->get('rounded-3xl') => 'rounded-s-3xl', 24 | $this->attributes->get('rounded-full') => 'rounded-s-full', 25 | default => 'rounded-s', 26 | }; 27 | } 28 | 29 | public function getSuffixRoundClasses() 30 | { 31 | return match (true) { 32 | $this->attributes->get('rounded-none') => 'rounded-e-none', 33 | $this->attributes->get('rounded-xs') => 'rounded-e-sm', 34 | $this->attributes->get('rounded-md') => 'rounded-e-md', 35 | $this->attributes->get('rounded-lg') => 'rounded-e-lg', 36 | $this->attributes->get('rounded-xl') => 'rounded-e-xl', 37 | $this->attributes->get('rounded-2xl') => 'rounded-e-2xl', 38 | $this->attributes->get('rounded-3xl') => 'rounded-e-3xl', 39 | $this->attributes->get('rounded-full') => 'rounded-e-full', 40 | default => 'rounded-e', 41 | }; 42 | } 43 | } -------------------------------------------------------------------------------- /src/Traits/CardTrait.php: -------------------------------------------------------------------------------- 1 | 'rounded-sm', 15 | $default === 'rounded-xs' => 'rounded-xs', 16 | $default === 'rounded-md' => 'rounded-md', 17 | $default === 'rounded-lg' => 'rounded-lg', 18 | $default === 'rounded-xl' => 'rounded-xl', 19 | $default === 'rounded-2xl' => 'rounded-2xl', 20 | $default === 'rounded-3xl' => 'rounded-3xl', 21 | $default === 'rounded-full' => 'rounded-full', 22 | $default === 'rounded-none' => 'rounded-none', 23 | default => 'rounded-lg', 24 | }; 25 | } 26 | 27 | public function shadowClass(): string 28 | { 29 | return ShadowHelper::getShadowClass('card', $this->attributes); 30 | } 31 | } -------------------------------------------------------------------------------- /src/Traits/Colors/HasCheckboxColors.php: -------------------------------------------------------------------------------- 1 | attributes->get('secondary') => 'text-secondary focus:ring-secondary', 13 | $this->attributes->get('black') => 'text-black focus:ring-black', 14 | $this->attributes->get('white') => 'text-white focus:ring-white border-gray-200', 15 | $this->attributes->get('slate') => 'text-slate-600 focus:ring-slate-500', 16 | $this->attributes->get('gray') => 'text-gray-600 focus:ring-gray-500', 17 | $this->attributes->get('zinc') => 'text-zinc-600 focus:ring-zinc-500', 18 | $this->attributes->get('neutral') => 'text-neutral-600 focus:ring-neutral-500', 19 | $this->attributes->get('stone') => 'text-stone-600 focus:ring-stone-500', 20 | $this->attributes->get('red') => 'text-red-600 focus:ring-red-500', 21 | $this->attributes->get('orange') => 'text-orange-600 focus:ring-orange-500', 22 | $this->attributes->get('amber') => 'text-amber-600 focus:ring-amber-500', 23 | $this->attributes->get('yellow') => 'text-yellow-600 focus:ring-yellow-500', 24 | $this->attributes->get('lime') => 'text-lime-600 focus:ring-lime-500', 25 | $this->attributes->get('green') => 'text-green-600 focus:ring-green-500', 26 | $this->attributes->get('emerald') => 'text-emerald-600 focus:ring-emerald-500', 27 | $this->attributes->get('teal') => 'text-teal-600 focus:ring-teal-500', 28 | $this->attributes->get('cyan') => 'text-cyan-600 focus:ring-cyan-500', 29 | $this->attributes->get('sky') => 'text-sky-600 focus:ring-sky-500', 30 | $this->attributes->get('blue') => 'text-blue-600 focus:ring-blue-500', 31 | $this->attributes->get('indigo') => 'text-indigo-600 focus:ring-indigo-500', 32 | $this->attributes->get('violet') => 'text-violet-600 focus:ring-violet-500', 33 | $this->attributes->get('purple') => 'text-purple-600 focus:ring-purple-500', 34 | $this->attributes->get('fuchsia') => 'text-fuchsia-600 focus:ring-fuchsia-500', 35 | $this->attributes->get('pink') => 'text-pink-600 focus:ring-pink-500', 36 | $this->attributes->get('rose') => 'text-rose-600 focus:ring-rose-500', 37 | default => 'text-primary focus:ring-primary', // primary 38 | }; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Traits/Colors/HasColorAttributes.php: -------------------------------------------------------------------------------- 1 | attributes->get('secondary') => 'bg-secondary', 13 | $this->attributes->get('black') => 'bg-black', 14 | $this->attributes->get('white') => 'bg-white', 15 | $this->attributes->get('slate') => 'bg-slate-500', 16 | $this->attributes->get('gray') => 'bg-gray-500', 17 | $this->attributes->get('zinc') => 'bg-zinc-500', 18 | $this->attributes->get('neutral') => 'bg-neutral-500', 19 | $this->attributes->get('stone') => 'bg-stone-500', 20 | $this->attributes->get('red') => 'bg-red-500', 21 | $this->attributes->get('orange') => 'bg-orange-500', 22 | $this->attributes->get('amber') => 'bg-amber-500', 23 | $this->attributes->get('yellow') => 'bg-yellow-500', 24 | $this->attributes->get('lime') => 'bg-lime-500', 25 | $this->attributes->get('green') => 'bg-green-500', 26 | $this->attributes->get('emerald') => 'bg-emerald-500', 27 | $this->attributes->get('teal') => 'bg-teal-500', 28 | $this->attributes->get('cyan') => 'bg-cyan-500', 29 | $this->attributes->get('sky') => 'bg-sky-500', 30 | $this->attributes->get('blue') => 'bg-blue-500', 31 | $this->attributes->get('indigo') => 'bg-indigo-500', 32 | $this->attributes->get('violet') => 'bg-violet-500', 33 | $this->attributes->get('purple') => 'bg-purple-500', 34 | $this->attributes->get('fuchsia') => 'bg-fuchsia-500', 35 | $this->attributes->get('pink') => 'bg-pink-500', 36 | $this->attributes->get('rose') => 'bg-rose-500', 37 | default => 'bg-primary' 38 | }; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Traits/Colors/HasProgressRadialColors.php: -------------------------------------------------------------------------------- 1 | attributes->get('secondary') => 'stroke-secondary', 13 | $this->attributes->get('black') => 'stroke-black', 14 | $this->attributes->get('white') => 'stroke-white', 15 | $this->attributes->get('slate') => 'stroke-slate-500', 16 | $this->attributes->get('gray') => 'stroke-gray-500', 17 | $this->attributes->get('zinc') => 'stroke-zinc-500', 18 | $this->attributes->get('neutral') => 'stroke-neutral-500', 19 | $this->attributes->get('stone') => 'stroke-stone-500', 20 | $this->attributes->get('red') => 'stroke-red-500', 21 | $this->attributes->get('orange') => 'stroke-orange-500', 22 | $this->attributes->get('amber') => 'stroke-amber-500', 23 | $this->attributes->get('yellow') => 'stroke-yellow-500', 24 | $this->attributes->get('lime') => 'stroke-lime-500', 25 | $this->attributes->get('green') => 'stroke-green-500', 26 | $this->attributes->get('emerald') => 'stroke-emerald-500', 27 | $this->attributes->get('teal') => 'stroke-teal-500', 28 | $this->attributes->get('cyan') => 'stroke-cyan-500', 29 | $this->attributes->get('sky') => 'stroke-sky-500', 30 | $this->attributes->get('blue') => 'stroke-blue-500', 31 | $this->attributes->get('indigo') => 'stroke-indigo-500', 32 | $this->attributes->get('violet') => 'stroke-violet-500', 33 | $this->attributes->get('purple') => 'stroke-purple-500', 34 | $this->attributes->get('fuchsia') => 'stroke-fuchsia-500', 35 | $this->attributes->get('pink') => 'stroke-pink-500', 36 | $this->attributes->get('rose') => 'stroke-rose-500', 37 | default => 'stroke-primary' 38 | }; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Traits/Colors/HasRadioColors.php: -------------------------------------------------------------------------------- 1 | attributes->get('secondary') => 'text-secondary focus:ring-secondary', 13 | $this->attributes->get('black') => 'text-black focus:ring-black', 14 | $this->attributes->get('white') => 'text-white focus:ring-white border-gray-200', 15 | $this->attributes->get('slate') => 'text-slate-600 focus:ring-slate-500', 16 | $this->attributes->get('gray') => 'text-gray-600 focus:ring-gray-500', 17 | $this->attributes->get('zinc') => 'text-zinc-600 focus:ring-zinc-500', 18 | $this->attributes->get('neutral') => 'text-neutral-600 focus:ring-neutral-500', 19 | $this->attributes->get('stone') => 'text-stone-600 focus:ring-stone-500', 20 | $this->attributes->get('red') => 'text-red-600 focus:ring-red-500', 21 | $this->attributes->get('orange') => 'text-orange-600 focus:ring-orange-500', 22 | $this->attributes->get('amber') => 'text-amber-600 focus:ring-amber-500', 23 | $this->attributes->get('yellow') => 'text-yellow-600 focus:ring-yellow-500', 24 | $this->attributes->get('lime') => 'text-lime-600 focus:ring-lime-500', 25 | $this->attributes->get('green') => 'text-green-600 focus:ring-green-500', 26 | $this->attributes->get('emerald') => 'text-emerald-600 focus:ring-emerald-500', 27 | $this->attributes->get('teal') => 'text-teal-600 focus:ring-teal-500', 28 | $this->attributes->get('cyan') => 'text-cyan-600 focus:ring-cyan-500', 29 | $this->attributes->get('sky') => 'text-sky-600 focus:ring-sky-500', 30 | $this->attributes->get('blue') => 'text-blue-600 focus:ring-blue-500', 31 | $this->attributes->get('indigo') => 'text-indigo-600 focus:ring-indigo-500', 32 | $this->attributes->get('violet') => 'text-violet-600 focus:ring-violet-500', 33 | $this->attributes->get('purple') => 'text-purple-600 focus:ring-purple-500', 34 | $this->attributes->get('fuchsia') => 'text-fuchsia-600 focus:ring-fuchsia-500', 35 | $this->attributes->get('pink') => 'text-pink-600 focus:ring-pink-500', 36 | $this->attributes->get('rose') => 'text-rose-600 focus:ring-rose-500', 37 | default => 'text-primary focus:ring-primary', // primary 38 | }; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Traits/Colors/HasRangeColors.php: -------------------------------------------------------------------------------- 1 | attributes->get('black') => '[&::-webkit-slider-thumb]:bg-gray-50 [&::-moz-range-thumb]:bg-gray-50 [&::-ms-thumb]:bg-gray-50 dark:[&::-webkit-slider-thumb]:bg-gray-300 dark:[&::-moz-range-thumb]:bg-gray-300 dark:[&::-ms-thumb]:bg-gray-300 [&::-moz-range-progress]:bg-gray-400 [&::-ms-fill-lower]:bg-gray-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#000000]', 13 | 14 | $this->attributes->get('slate') => '[&::-webkit-slider-thumb]:bg-slate-600 [&::-moz-range-thumb]:bg-slate-600 [&::-ms-thumb]:bg-slate-600 [&::-moz-range-progress]:bg-slate-400 [&::-ms-fill-lower]:bg-slate-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#94A3B8]', 15 | $this->attributes->get('gray') => '[&::-webkit-slider-thumb]:bg-gray-600 [&::-moz-range-thumb]:bg-gray-600 [&::-ms-thumb]:bg-gray-600 [&::-moz-range-progress]:bg-gray-400 [&::-ms-fill-lower]:bg-gray-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#9CA3AF]', 16 | $this->attributes->get('zinc') => '[&::-webkit-slider-thumb]:bg-zinc-600 [&::-moz-range-thumb]:bg-zinc-600 [&::-ms-thumb]:bg-zinc-600 [&::-moz-range-progress]:bg-zinc-400 [&::-ms-fill-lower]:bg-zinc-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#A1A1AA]', 17 | $this->attributes->get('neutral') => '[&::-webkit-slider-thumb]:bg-neutral-600 [&::-moz-range-thumb]:bg-neutral-600 [&::-ms-thumb]:bg-neutral-600 [&::-moz-range-progress]:bg-neutral-400 [&::-ms-fill-lower]:bg-neutral-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#A3A3A3]', 18 | $this->attributes->get('stone') => '[&::-webkit-slider-thumb]:bg-stone-600 [&::-moz-range-thumb]:bg-stone-600 [&::-ms-thumb]:bg-stone-600 [&::-moz-range-progress]:bg-stone-400 [&::-ms-fill-lower]:bg-stone-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#A8A29E]', 19 | $this->attributes->get('red') => '[&::-webkit-slider-thumb]:bg-red-600 [&::-moz-range-thumb]:bg-red-600 [&::-ms-thumb]:bg-red-600 [&::-moz-range-progress]:bg-red-400 [&::-ms-fill-lower]:bg-red-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#F87171]', 20 | $this->attributes->get('orange') => '[&::-webkit-slider-thumb]:bg-orange-600 [&::-moz-range-thumb]:bg-orange-600 [&::-ms-thumb]:bg-orange-600 [&::-moz-range-progress]:bg-orange-400 [&::-ms-fill-lower]:bg-orange-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#FB923C]', 21 | $this->attributes->get('amber') => '[&::-webkit-slider-thumb]:bg-amber-600 [&::-moz-range-thumb]:bg-amber-600 [&::-ms-thumb]:bg-amber-600 [&::-moz-range-progress]:bg-amber-400 [&::-ms-fill-lower]:bg-amber-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#FBBF24]', 22 | $this->attributes->get('yellow') => '[&::-webkit-slider-thumb]:bg-yellow-600 [&::-moz-range-thumb]:bg-yellow-600 [&::-ms-thumb]:bg-yellow-600 [&::-moz-range-progress]:bg-yellow-400 [&::-ms-fill-lower]:bg-yellow-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#FACC15]', 23 | $this->attributes->get('lime') => '[&::-webkit-slider-thumb]:bg-lime-600 [&::-moz-range-thumb]:bg-lime-600 [&::-ms-thumb]:bg-lime-600 [&::-moz-range-progress]:bg-lime-400 [&::-ms-fill-lower]:bg-lime-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#A3E635]', 24 | $this->attributes->get('green') => '[&::-webkit-slider-thumb]:bg-green-600 [&::-moz-range-thumb]:bg-green-600 [&::-ms-thumb]:bg-green-600 [&::-moz-range-progress]:bg-green-400 [&::-ms-fill-lower]:bg-green-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#4ADE80]', 25 | $this->attributes->get('emerald') => '[&::-webkit-slider-thumb]:bg-emerald-600 [&::-moz-range-thumb]:bg-emerald-600 [&::-ms-thumb]:bg-emerald-600 [&::-moz-range-progress]:bg-emerald-400 [&::-ms-fill-lower]:bg-emerald-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#34D399]', 26 | $this->attributes->get('teal') => '[&::-webkit-slider-thumb]:bg-teal-600 [&::-moz-range-thumb]:bg-teal-600 [&::-ms-thumb]:bg-teal-600 [&::-moz-range-progress]:bg-teal-400 [&::-ms-fill-lower]:bg-teal-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#2DD4BF]', 27 | $this->attributes->get('cyan') => '[&::-webkit-slider-thumb]:bg-cyan-600 [&::-moz-range-thumb]:bg-cyan-600 [&::-ms-thumb]:bg-cyan-600 [&::-moz-range-progress]:bg-cyan-400 [&::-ms-fill-lower]:bg-cyan-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#22D3EE]', 28 | $this->attributes->get('sky') => '[&::-webkit-slider-thumb]:bg-sky-600 [&::-moz-range-thumb]:bg-sky-600 [&::-ms-thumb]:bg-sky-600 [&::-moz-range-progress]:bg-sky-400 [&::-ms-fill-lower]:bg-sky-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#38BDF8]', 29 | $this->attributes->get('blue') => '[&::-webkit-slider-thumb]:bg-blue-600 [&::-moz-range-thumb]:bg-blue-600 [&::-ms-thumb]:bg-blue-600 [&::-moz-range-progress]:bg-blue-400 [&::-ms-fill-lower]:bg-blue-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#60A5FA]', 30 | $this->attributes->get('indigo') => '[&::-webkit-slider-thumb]:bg-indigo-600 [&::-moz-range-thumb]:bg-indigo-600 [&::-ms-thumb]:bg-indigo-600 [&::-moz-range-progress]:bg-indigo-400 [&::-ms-fill-lower]:bg-indigo-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#818CF8]', 31 | $this->attributes->get('violet') => '[&::-webkit-slider-thumb]:bg-violet-600 [&::-moz-range-thumb]:bg-violet-600 [&::-ms-thumb]:bg-violet-600 [&::-moz-range-progress]:bg-violet-400 [&::-ms-fill-lower]:bg-violet-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#A78BFA]', 32 | $this->attributes->get('purple') => '[&::-webkit-slider-thumb]:bg-purple-600 [&::-moz-range-thumb]:bg-purple-600 [&::-ms-thumb]:bg-purple-600 [&::-moz-range-progress]:bg-purple-400 [&::-ms-fill-lower]:bg-purple-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#C084FC]', 33 | $this->attributes->get('fuchsia') => '[&::-webkit-slider-thumb]:bg-fuchsia-600 [&::-moz-range-thumb]:bg-fuchsia-600 [&::-ms-thumb]:bg-fuchsia-600 [&::-moz-range-progress]:bg-fuchsia-400 [&::-ms-fill-lower]:bg-fuchsia-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#E879F9]', 34 | $this->attributes->get('pink') => '[&::-webkit-slider-thumb]:bg-pink-600 [&::-moz-range-thumb]:bg-pink-600 [&::-ms-thumb]:bg-pink-600 [&::-moz-range-progress]:bg-pink-400 [&::-ms-fill-lower]:bg-pink-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#F472B6]', 35 | $this->attributes->get('rose') => '[&::-webkit-slider-thumb]:bg-rose-600 [&::-moz-range-thumb]:bg-rose-600 [&::-ms-thumb]:bg-rose-600 [&::-moz-range-progress]:bg-rose-400 [&::-ms-fill-lower]:bg-rose-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#FB7185]', 36 | 37 | default => '[&::-webkit-slider-thumb]:bg-blue-600 [&::-moz-range-thumb]:bg-blue-600 [&::-ms-thumb]:bg-blue-600 [&::-moz-range-progress]:bg-blue-400 [&::-ms-fill-lower]:bg-blue-400 [&::-webkit-slider-thumb]:shadow-[-999px_0px_0px_990px_#60A5FA]', 38 | }; 39 | } 40 | } -------------------------------------------------------------------------------- /src/Traits/Colors/HasStatColors.php: -------------------------------------------------------------------------------- 1 | attributes->get('primary') => 'border-primary/40', 13 | $this->attributes->get('secondary') => 'border-secondary/40', 14 | $this->attributes->get('black') => 'border-black-500/40', 15 | $this->attributes->get('white') => 'border-white-500/40', 16 | $this->attributes->get('slate') => 'border-slate-500/40', 17 | $this->attributes->get('gray') => 'border-gray-500/40', 18 | $this->attributes->get('zinc') => 'border-zinc-500/40', 19 | $this->attributes->get('neutral') => 'border-neutral-500/40', 20 | $this->attributes->get('stone') => 'border-stone-500/40', 21 | $this->attributes->get('red') => 'border-red-500/40', 22 | $this->attributes->get('orange') => 'border-orange-500/40', 23 | $this->attributes->get('amber') => 'border-amber-500/40', 24 | $this->attributes->get('yellow') => 'border-yellow-500/40', 25 | $this->attributes->get('lime') => 'border-lime-500/40', 26 | $this->attributes->get('green') => 'border-green-500/40', 27 | $this->attributes->get('emerald') => 'border-emerald-500/40', 28 | $this->attributes->get('teal') => 'border-teal-500/40', 29 | $this->attributes->get('cyan') => 'border-cyan-500/40', 30 | $this->attributes->get('sky') => 'border-sky-500/40', 31 | $this->attributes->get('blue') => 'border-blue-500/40', 32 | $this->attributes->get('indigo') => 'border-indigo-500/40', 33 | $this->attributes->get('violet') => 'border-violet-500/40', 34 | $this->attributes->get('purple') => 'border-purple-500/40', 35 | $this->attributes->get('fuchsia') => 'border-fuchsia-500/40', 36 | $this->attributes->get('pink') => 'border-pink-500/40', 37 | $this->attributes->get('rose') => 'border-rose-500/40', 38 | default => 'border-gray-200 dark:border-gray-600', 39 | }; 40 | } 41 | 42 | public function getIconBgColor(): string 43 | { 44 | return match (true) { 45 | $this->attributes->get('primary') => 'bg-primary/20 dark:bg-primary/50 dark:text-gray-200', 46 | $this->attributes->get('secondary') => 'bg-secondary/20 dark:bg-secondary/50 dark:text-gray-200', 47 | $this->attributes->get('black') => 'bg-black-500/20 dark:bg-black-500/50 dark:text-gray-200', 48 | $this->attributes->get('white') => 'bg-white-500/20 dark:bg-white-500/50 dark:text-gray-200', 49 | $this->attributes->get('slate') => 'bg-slate-500/20 dark:bg-slate-500/50 dark:text-gray-200', 50 | $this->attributes->get('gray') => 'bg-gray-500/20 dark:bg-gray-500/50 dark:text-gray-200', 51 | $this->attributes->get('zinc') => 'bg-zinc-500/20 dark:bg-zinc-500/50 dark:text-gray-200', 52 | $this->attributes->get('neutral') => 'bg-neutral-500/20 dark:bg-neutral-500/50 dark:text-gray-200', 53 | $this->attributes->get('stone') => 'bg-stone-500/20 dark:bg-stone-500/50 dark:text-gray-200', 54 | $this->attributes->get('red') => 'bg-red-500/20 dark:bg-red-500/50 dark:text-gray-200', 55 | $this->attributes->get('orange') => 'bg-orange-500/20 dark:bg-orange-500/50 dark:text-gray-200', 56 | $this->attributes->get('amber') => 'bg-amber-500/20 dark:bg-amber-500/50 dark:text-gray-200', 57 | $this->attributes->get('yellow') => 'bg-yellow-500/20 dark:bg-yellow-500/50 dark:text-gray-200', 58 | $this->attributes->get('lime') => 'bg-lime-500/20 dark:bg-lime-500/50 dark:text-gray-200', 59 | $this->attributes->get('green') => 'bg-green-500/20 dark:bg-green-500/50 dark:text-gray-200', 60 | $this->attributes->get('emerald') => 'bg-emerald-500/20 dark:bg-emerald-500/50 dark:text-gray-200', 61 | $this->attributes->get('teal') => 'bg-teal-500/20 dark:bg-teal-500/50 dark:text-gray-200', 62 | $this->attributes->get('cyan') => 'bg-cyan-500/20 dark:bg-cyan-500/50 dark:text-gray-200', 63 | $this->attributes->get('sky') => 'bg-sky-500/20 dark:bg-sky-500/50 dark:text-gray-200', 64 | $this->attributes->get('blue') => 'bg-blue-500/20 dark:bg-blue-500/50 dark:text-gray-200', 65 | $this->attributes->get('indigo') => 'bg-indigo-500/20 dark:bg-indigo-500/50 dark:text-gray-200', 66 | $this->attributes->get('violet') => 'bg-violet-500/20 dark:bg-violet-500/50 dark:text-gray-200', 67 | $this->attributes->get('purple') => 'bg-purple-500/20 dark:bg-purple-500/50 dark:text-gray-200', 68 | $this->attributes->get('fuchsia') => 'bg-fuchsia-500/20 dark:bg-fuchsia-500/50 dark:text-gray-200', 69 | $this->attributes->get('pink') => 'bg-pink-500/20 dark:bg-pink-500/50 dark:text-gray-200', 70 | $this->attributes->get('rose') => 'bg-rose-500/20 dark:bg-rose-500/50 dark:text-gray-200', 71 | default => 'border-gray-200 dark:border-gray-600', 72 | }; 73 | } 74 | } -------------------------------------------------------------------------------- /src/Traits/HasDropdownPosition.php: -------------------------------------------------------------------------------- 1 | attributes->get('top') => 'top', 13 | $this->attributes->get('top-start') => 'top-start', 14 | $this->attributes->get('top-end') => 'top-end', 15 | $this->attributes->get('bottom') => 'bottom', 16 | $this->attributes->get('bottom-start') => 'bottom-start', 17 | $this->attributes->get('bottom-end') => 'bottom-end', 18 | $this->attributes->get('left') => 'left', 19 | $this->attributes->get('left-start') => 'left-start', 20 | $this->attributes->get('left-end') => 'left-end', 21 | $this->attributes->get('right') => 'right', 22 | $this->attributes->get('right-start') => 'right-start', 23 | $this->attributes->get('right-end') => 'right-end', 24 | default => $defaultPosition, 25 | }; 26 | 27 | return match ($basePosition) { 28 | 'top' => 'x-anchor.top.offset.14', 29 | 'top-start' => 'x-anchor.top-start.offset.14', 30 | 'top-end' => 'x-anchor.top-end.offset.14', 31 | 'bottom' => 'x-anchor.bottom.offset.14', 32 | 'bottom-start' => 'x-anchor.bottom-start.offset.14', 33 | 'bottom-end' => 'x-anchor.bottom-end.offset.14', 34 | 'left' => 'x-anchor.left.offset.14', 35 | 'left-start' => 'x-anchor.left-start.offset.14', 36 | 'left-end' => 'x-anchor.left-end.offset.14', 37 | 'right' => 'x-anchor.right.offset.14', 38 | 'right-start' => 'x-anchor.right-start.offset.14', 39 | 'right-end' => 'x-anchor.right-end.offset.14', 40 | default => 'x-anchor.bottom-end.offset.14', 41 | }; 42 | } 43 | } -------------------------------------------------------------------------------- /src/Traits/HasMarkdownImages.php: -------------------------------------------------------------------------------- 1 | isDirty($model->getMarkdownColumn())) { 13 | $oldImages = self::extractImageUrls($model->getOriginal($model->getMarkdownColumn())); 14 | $newImages = self::extractImageUrls($model->{$model->getMarkdownColumn()}); 15 | 16 | $model->deleteMarkdownImageUrls(array_diff($oldImages, $newImages)); 17 | } 18 | }); 19 | 20 | static::deleting(function ($model) { 21 | $model->deleteMarkdownImages($model->{$model->getMarkdownColumn()}); 22 | }); 23 | } 24 | 25 | protected function getMarkdownColumn(): string 26 | { 27 | return $this->markdownColumn ?? 'content'; 28 | } 29 | 30 | protected function getMarkdownImageDisk(): string 31 | { 32 | return $this->markdownImageDisk ?? 'public'; 33 | } 34 | 35 | protected function deleteMarkdownImages(?string $content): void 36 | { 37 | if (empty($content)) { 38 | return; 39 | } 40 | $this->deleteMarkdownImageUrls(self::extractImageUrls($content)); 41 | } 42 | 43 | protected function deleteMarkdownImageUrls(array $urls): void 44 | { 45 | foreach ($urls as $imageUrl) { 46 | $path = parse_url($imageUrl, PHP_URL_PATH); 47 | if ($path) { 48 | $path = str_replace('/storage/', '', $path); 49 | if (Storage::disk($this->getMarkdownImageDisk())->exists($path)) { 50 | Storage::disk($this->getMarkdownImageDisk())->delete($path); 51 | } 52 | } 53 | } 54 | } 55 | 56 | protected static function extractImageUrls(?string $content): array 57 | { 58 | if (empty($content)) { 59 | return []; 60 | } 61 | preg_match_all('/!\[.*?\]\((.*?)\)/', $content, $matches); 62 | 63 | return $matches[1] ?? []; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Traits/ModalTrait.php: -------------------------------------------------------------------------------- 1 | 'w-full sm:max-w-sm', 13 | 'md' => 'w-full sm:max-w-md', 14 | 'lg' => 'w-full sm:max-w-lg', 15 | 'xl' => 'w-full sm:max-w-xl', 16 | '2xl' => 'w-full sm:max-w-2xl', 17 | '3xl' => 'w-full sm:mx-6 md:mx-8 lg:mx-0 sm:max-w-3xl', 18 | '4xl' => 'w-full sm:mx-6 md:mx-8 lg:mx-0 sm:max-w-4xl', 19 | '5xl' => 'w-full sm:mx-6 md:mx-8 lg:mx-0 sm:max-w-5xl', 20 | '6xl' => 'w-full sm:mx-6 md:mx-8 xl:mx-0 sm:max-w-6xl', 21 | '7xl' => 'w-full sm:mx-6 md:mx-8 2xl:mx-0 sm:max-w-7xl', 22 | 'full' => 'fixed inset-0 w-screen h-screen', 23 | ]; 24 | 25 | foreach ($sizes as $key => $class) { 26 | if ($this->attributes->has($key)) { 27 | return $class; 28 | } 29 | } 30 | 31 | $defaultSize = config('tallcraftui.modal.size', 'lg'); 32 | 33 | return $sizes[$defaultSize] ?? $sizes['lg']; 34 | } 35 | 36 | public function getBgBlurClasses(): string 37 | { 38 | $isDefaultBlur = config('tallcraftui.modal.blur', false); 39 | 40 | return match (true) { 41 | $this->attributes->get('blur-sm') => 'backdrop-blur-sm', 42 | $this->attributes->get('blur-xs') => 'backdrop-blur-xs', 43 | $this->attributes->get('blur-md') => 'backdrop-blur-md', 44 | $this->attributes->get('blur-lg') => 'backdrop-blur-lg', 45 | $this->attributes->get('blur-xl') => 'backdrop-blur-xl', 46 | $this->attributes->get('blur-2xl') => 'backdrop-blur-2xl', 47 | $this->attributes->get('blur-3xl') => 'backdrop-blur-3xl', 48 | $this->attributes->get('blur-none') => 'backdrop-blur-none', 49 | 50 | default => match ($isDefaultBlur) { 51 | true => 'backdrop-blur-xs', 52 | default => '', 53 | }, 54 | }; 55 | } 56 | 57 | public function getModalPosition(): string 58 | { 59 | $positions = [ 60 | 'top' => 'flex items-start justify-center h-screen', 61 | 'bottom' => 'flex items-end justify-center h-screen', 62 | 'left' => 'flex items-center justify-start w-screen h-screen pl-10!', 63 | 'right' => 'flex items-center justify-end w-screen h-screen pr-10!', 64 | 'center' => 'flex items-center justify-center w-screen h-screen', 65 | ]; 66 | 67 | foreach ($positions as $key => $class) { 68 | if ($this->attributes->has($key)) { 69 | return $class; 70 | } 71 | } 72 | 73 | $defaultPosition = config('tallcraftui.modal.position', 'top'); 74 | 75 | return $positions[$defaultPosition] ?? $positions['top']; 76 | } 77 | 78 | public function getRoundedClasses(): string 79 | { 80 | return BorderRadiusHelper::getRoundedClass('modal', $this->attributes); 81 | } 82 | } -------------------------------------------------------------------------------- /src/Traits/Sizes/HasBadgeSizes.php: -------------------------------------------------------------------------------- 1 | attributes->get('sm') => 'text-xs px-1.5', 11 | $this->attributes->get('md') => 'text-xs px-2 py-0.5', 12 | $this->attributes->get('lg') => 'text-sm px-2.5 py-1', 13 | $this->attributes->get('xl') => 'text-base px-3 py-1.5', 14 | $this->attributes->get('2xl') => 'text-lg px-3.5 py-2', 15 | default => 'text-xs px-2 py-0.5', 16 | }; 17 | } 18 | 19 | public function getIconSize(): string 20 | { 21 | return match (true) { 22 | $this->attributes->get('sm') => 'size-3', 23 | $this->attributes->get('md') => 'size-3', 24 | $this->attributes->get('lg') => 'size-3.5', 25 | $this->attributes->get('xl') => 'size-4', 26 | $this->attributes->get('2xl') => 'size-[18px]', 27 | default => 'size-3', 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Traits/Sizes/HasButtonSizes.php: -------------------------------------------------------------------------------- 1 | 'px-2.5 py-1 text-xs', 11 | 'sm' => 'px-3 py-1.5 text-xs', 12 | 'md' => 'px-4 py-2 text-xs', 13 | 'lg' => 'px-5 py-2.5 text-sm', 14 | 'xl' => 'px-6 py-3 text-base', 15 | ]; 16 | 17 | foreach ($sizes as $key => $class) { 18 | if ($this->attributes->has($key)) { 19 | return $class; 20 | } 21 | } 22 | 23 | $defaultSize = config('tallcraftui.button.size', 'md'); 24 | 25 | return $sizes[$defaultSize] ?? $sizes['md']; 26 | } 27 | 28 | public function getCircleClasses(): string 29 | { 30 | $circleWithoutLabel = $this->attributes->get('circle') && !$this->label; 31 | 32 | return match (true) { 33 | $circleWithoutLabel && $this->attributes->get('xs') => 'rounded-full w-7 h-7 p-1.5 justify-center', 34 | $circleWithoutLabel && $this->attributes->get('sm') => 'rounded-full w-8 h-8 p-2 justify-center', 35 | $circleWithoutLabel && $this->attributes->get('md') => 'rounded-full w-10 h-10 p-2 justify-center', 36 | $circleWithoutLabel && $this->attributes->get('lg') => 'rounded-full w-12 h-12 p-2 justify-center', 37 | $circleWithoutLabel && $this->attributes->get('xl') => 'rounded-full w-14 h-14 p-2 justify-center', 38 | $circleWithoutLabel => 'rounded-full w-10 h-10 p-2 justify-center', // md 39 | default => '', 40 | }; 41 | } 42 | 43 | public function getIconSize(): string 44 | { 45 | return match (true) { 46 | $this->attributes->get('xs') => 'size-4', 47 | $this->attributes->get('sm') => 'size-4', 48 | $this->attributes->get('md') => 'size-4.5', 49 | $this->attributes->get('lg') => 'size-5', 50 | $this->attributes->get('xl') => 'size-5.5', 51 | default => 'size-4.5', 52 | }; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Traits/Sizes/HasCheckboxSizes.php: -------------------------------------------------------------------------------- 1 | 'size-4', 11 | 'md' => 'size-[18px]', 12 | 'lg' => 'size-6', 13 | 'xl' => 'size-7', 14 | '2xl' => 'size-8', 15 | ]; 16 | 17 | foreach ($sizes as $key => $class) { 18 | if ($this->attributes->has($key)) { 19 | return $class; 20 | } 21 | } 22 | 23 | $defaultSize = config('tallcraftui.checkbox.size', 'md'); 24 | 25 | return $sizes[$defaultSize] ?? $sizes['md']; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Traits/Sizes/HasDrawerSizes.php: -------------------------------------------------------------------------------- 1 | attributes); 12 | } 13 | 14 | public function getSizeClasses(): string 15 | { 16 | $widths = [ 17 | 'sm' => 'max-w-sm', 18 | 'md' => 'max-w-md', 19 | 'lg' => 'max-w-lg', 20 | 'xl' => 'max-w-xl', 21 | '2xl' => 'max-w-2xl', 22 | '3xl' => 'max-w-3xl', 23 | '4xl' => 'max-w-4xl', 24 | '5xl' => 'max-w-5xl', 25 | '6xl' => 'max-w-6xl', 26 | '7xl' => 'max-w-7xl', 27 | 'full' => 'max-w-full', 28 | ]; 29 | 30 | foreach ($widths as $key => $class) { 31 | if ($this->attributes->has($key)) { 32 | return $class; 33 | } 34 | } 35 | 36 | $defaultWidth = config('tallcraftui.drawer.width', 'lg'); 37 | 38 | return $widths[$defaultWidth] ?? $widths['lg']; 39 | } 40 | } -------------------------------------------------------------------------------- /src/Traits/Sizes/HasInputSizes.php: -------------------------------------------------------------------------------- 1 | 'py-1 text-xs', 11 | 'sm' => 'py-1.5 text-xs', 12 | 'md' => 'py-2 text-sm', 13 | 'lg' => 'py-2.5 text-base', 14 | 'xl' => 'py-3 text-lg', 15 | '2xl' => 'py-3.5 text-xl', 16 | ]; 17 | 18 | foreach ($sizes as $key => $class) { 19 | if ($this->attributes->has($key)) { 20 | return $class; 21 | } 22 | } 23 | 24 | $defaultSize = config('tallcraftui.input.size', 'md'); 25 | 26 | return $sizes[$defaultSize] ?? $sizes['md']; 27 | } 28 | 29 | public function getAddonSizeClasses(): string 30 | { 31 | $sizes = [ 32 | 'xs' => 'px-1.5 py-1 text-xs', 33 | 'sm' => 'px-2 py-1.5 text-xs', 34 | 'md' => 'px-3 py-2 text-sm', 35 | 'lg' => 'px-4 py-3 text-base', 36 | 'xl' => 'px-5 py-4 text-lg', 37 | '2xl' => 'px-6 py-3.5 text-xl', 38 | ]; 39 | 40 | foreach ($sizes as $key => $class) { 41 | if ($this->attributes->has($key)) { 42 | return $class; 43 | } 44 | } 45 | 46 | $defaultSize = config('tallcraftui.input.size', 'md'); 47 | 48 | return $sizes[$defaultSize] ?? $sizes['md']; 49 | } 50 | } -------------------------------------------------------------------------------- /src/Traits/Sizes/HasNativeSelectSizes.php: -------------------------------------------------------------------------------- 1 | 'py-1 text-xs', 11 | 'sm' => 'py-1.5 text-xs', 12 | 'md' => 'py-2 text-sm', 13 | 'lg' => 'py-2.5 text-base', 14 | 'xl' => 'py-3 text-lg', 15 | '2xl' => 'py-3.5 text-xl', 16 | ]; 17 | 18 | foreach ($sizes as $key => $class) { 19 | if ($this->attributes->has($key)) { 20 | return $class; 21 | } 22 | } 23 | 24 | $defaultSize = config('tallcraftui.native-select.size', 'md'); 25 | 26 | return $sizes[$defaultSize] ?? $sizes['md']; 27 | } 28 | } -------------------------------------------------------------------------------- /src/Traits/Sizes/HasProgressRadialSizes.php: -------------------------------------------------------------------------------- 1 | ['size' => 'h-16 w-16', 'text' => 'text-xs', 'stroke' => '3'], 11 | 'sm' => ['size' => 'h-20 w-20', 'text' => 'text-sm', 'stroke' => '4'], 12 | 'md' => ['size' => 'h-24 w-24', 'text' => 'text-base', 'stroke' => '5'], 13 | 'lg' => ['size' => 'h-32 w-32', 'text' => 'text-lg', 'stroke' => '6'], 14 | 'xl' => ['size' => 'h-40 w-40', 'text' => 'text-xl', 'stroke' => '8'], 15 | '2xl' => ['size' => 'h-48 w-48', 'text' => 'text-2xl', 'stroke' => '10'], 16 | ]; 17 | 18 | // Check for size props (xs, sm, md, lg, xl, 2xl) 19 | foreach ($sizes as $size => $classes) { 20 | if ($this->attributes->has($size)) { 21 | return $classes; 22 | } 23 | } 24 | 25 | // Default to md if no size prop is found 26 | return $sizes['md']; 27 | } 28 | 29 | public function getStrokeWidth(): string 30 | { 31 | // Use custom stroke if provided, otherwise use size-based stroke 32 | return (string) ($this->stroke ?? $this->getSizeClasses()['stroke']); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Traits/Sizes/HasProgressSizes.php: -------------------------------------------------------------------------------- 1 | 'h-1', 11 | 'sm' => 'h-2', 12 | 'md' => 'h-3', 13 | 'lg' => 'h-4', 14 | 'xl' => 'h-5', 15 | '2xl' => 'h-6', 16 | ]; 17 | 18 | foreach ($sizes as $key => $class) { 19 | if ($this->attributes->has($key)) { 20 | return $class; 21 | } 22 | } 23 | 24 | $defaultSize = config('tallcraftui.progress.size', 'md'); 25 | 26 | return $sizes[$defaultSize] ?? $sizes['md']; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Traits/Sizes/HasRadioSizes.php: -------------------------------------------------------------------------------- 1 | 'size-4', 11 | 'md' => 'size-[18px]', 12 | 'lg' => 'size-6', 13 | 'xl' => 'size-7', 14 | '2xl' => 'size-8', 15 | ]; 16 | 17 | foreach ($sizes as $key => $class) { 18 | if ($this->attributes->has($key)) { 19 | return $class; 20 | } 21 | } 22 | 23 | $defaultSize = config('tallcraftui.radio.size', 'md'); 24 | 25 | return $sizes[$defaultSize] ?? $sizes['md']; 26 | } 27 | } -------------------------------------------------------------------------------- /src/Traits/Sizes/HasRatingSizes.php: -------------------------------------------------------------------------------- 1 | 'size-4', 11 | 'md' => 'size-5', 12 | 'lg' => 'size-6', 13 | 'xl' => 'size-7', 14 | '2xl' => 'size-8', 15 | ]; 16 | 17 | foreach ($sizes as $key => $class) { 18 | if ($this->attributes->has($key)) { 19 | return $class; 20 | } 21 | } 22 | 23 | $defaultSize = config('tallcraftui.rating.size', 'lg'); 24 | 25 | return $sizes[$defaultSize] ?? $sizes['lg']; 26 | } 27 | } -------------------------------------------------------------------------------- /src/Traits/Sizes/HasSelectSizes.php: -------------------------------------------------------------------------------- 1 | 'py-1 text-xs', 11 | 'sm' => 'py-1.5 text-xs', 12 | 'md' => 'py-2 text-sm', 13 | 'lg' => 'py-2.5 text-base', 14 | 'xl' => 'py-3 text-lg', 15 | '2xl' => 'py-3.5 text-xl', 16 | ]; 17 | 18 | foreach ($sizes as $key => $class) { 19 | if ($this->attributes->has($key)) { 20 | return $class; 21 | } 22 | } 23 | 24 | $defaultSize = config('tallcraftui.select.size', 'md'); 25 | 26 | return $sizes[$defaultSize] ?? $sizes['md']; 27 | } 28 | } -------------------------------------------------------------------------------- /src/Traits/SpinnerTrait.php: -------------------------------------------------------------------------------- 1 | attributes->get('secondary') => 'text-secondary', 15 | $this->attributes->get('black') => 'text-gray-900', 16 | $this->attributes->get('white') => 'text-white', 17 | $this->attributes->get('slate') => 'text-slate-500', 18 | $this->attributes->get('gray') => 'text-gray-500', 19 | $this->attributes->get('zinc') => 'text-zinc-500', 20 | $this->attributes->get('neutral') => 'text-neutral-500', 21 | $this->attributes->get('stone') => 'text-stone-500', 22 | $this->attributes->get('red') => 'text-red-500', 23 | $this->attributes->get('orange') => 'text-orange-500', 24 | $this->attributes->get('amber') => 'text-amber-500', 25 | $this->attributes->get('yellow') => 'text-yellow-500', 26 | $this->attributes->get('lime') => 'text-lime-500', 27 | $this->attributes->get('green') => 'text-green-500', 28 | $this->attributes->get('emerald') => 'text-emerald-500', 29 | $this->attributes->get('teal') => 'text-teal-500', 30 | $this->attributes->get('cyan') => 'text-cyan-500', 31 | $this->attributes->get('sky') => 'text-sky-500', 32 | $this->attributes->get('blue') => 'text-blue-500', 33 | $this->attributes->get('indigo') => 'text-indigo-500', 34 | $this->attributes->get('violet') => 'text-violet-500', 35 | $this->attributes->get('purple') => 'text-purple-500', 36 | $this->attributes->get('fuchsia') => 'text-fuchsia-500', 37 | $this->attributes->get('pink') => 'text-pink-500', 38 | $this->attributes->get('rose') => 'text-rose-500', 39 | default => 'text-primary', 40 | }; 41 | } 42 | 43 | public function getSizeClasses(): string 44 | { 45 | return match (true) { 46 | $this->attributes->get('xs') => 'w-4 h-4', 47 | $this->attributes->get('sm') => 'w-6 h-6', 48 | $this->attributes->get('md') => 'w-8 h-8', 49 | $this->attributes->get('lg') => 'w-10 h-10', 50 | $this->attributes->get('xl') => 'w-12 h-12', 51 | default => 'w-8 h-8', // md 52 | }; 53 | } 54 | } -------------------------------------------------------------------------------- /src/Traits/ToggleTrait.php: -------------------------------------------------------------------------------- 1 | attributes->get('secondary') => 'peer-focus:ring-secondary dark:peer-focus:ring-secondary peer-checked:bg-secondary', 15 | $this->attributes->get('black') => 'peer-focus:ring-gray-900 dark:peer-focus:ring-gray-900 peer-checked:bg-gray-900', 16 | $this->attributes->get('white') => 'peer-focus:ring-gray-50 dark:peer-focus:ring-gray-50 peer-checked:bg-gray-50 dark:peer-checked:bg-gray-300', 17 | $this->attributes->get('slate') => 'peer-focus:ring-slate-500 dark:peer-focus:ring-slate-500 peer-checked:bg-slate-500', 18 | $this->attributes->get('gray') => 'peer-focus:ring-gray-500 dark:peer-focus:ring-gray-500 peer-checked:bg-gray-500', 19 | $this->attributes->get('zinc') => 'peer-focus:ring-zinc-500 dark:peer-focus:ring-zinc-500 peer-checked:bg-zinc-500', 20 | $this->attributes->get('neutral') => 'peer-focus:ring-neutral-500 dark:peer-focus:ring-neutral-500 peer-checked:bg-neutral-500', 21 | $this->attributes->get('stone') => 'peer-focus:ring-stone-500 dark:peer-focus:ring-stone-500 peer-checked:bg-stone-500', 22 | $this->attributes->get('red') => 'peer-focus:ring-red-500 dark:peer-focus:ring-red-500 peer-checked:bg-red-500', 23 | $this->attributes->get('orange') => 'peer-focus:ring-orange-500 dark:peer-focus:ring-orange-500 peer-checked:bg-orange-500', 24 | $this->attributes->get('amber') => 'peer-focus:ring-amber-500 dark:peer-focus:ring-amber-500 peer-checked:bg-amber-500', 25 | $this->attributes->get('yellow') => 'peer-focus:ring-yellow-500 dark:peer-focus:ring-yellow-500 peer-checked:bg-yellow-500', 26 | $this->attributes->get('lime') => 'peer-focus:ring-lime-500 dark:peer-focus:ring-lime-500 peer-checked:bg-lime-500', 27 | $this->attributes->get('green') => 'peer-focus:ring-green-500 dark:peer-focus:ring-green-500 peer-checked:bg-green-500', 28 | $this->attributes->get('emerald') => 'peer-focus:ring-emerald-500 dark:peer-focus:ring-emerald-500 peer-checked:bg-emerald-500', 29 | $this->attributes->get('teal') => 'peer-focus:ring-teal-500 dark:peer-focus:ring-teal-500 peer-checked:bg-teal-500', 30 | $this->attributes->get('cyan') => 'peer-focus:ring-cyan-500 dark:peer-focus:ring-cyan-500 peer-checked:bg-cyan-500', 31 | $this->attributes->get('sky') => 'peer-focus:ring-sky-500 dark:peer-focus:ring-sky-500 peer-checked:bg-sky-500', 32 | $this->attributes->get('blue') => 'peer-focus:ring-blue-500 dark:peer-focus:ring-blue-500 peer-checked:bg-blue-500', 33 | $this->attributes->get('indigo') => 'peer-focus:ring-indigo-500 dark:peer-focus:ring-indigo-500 peer-checked:bg-indigo-500', 34 | $this->attributes->get('violet') => 'peer-focus:ring-violet-500 dark:peer-focus:ring-violet-500 peer-checked:bg-violet-500', 35 | $this->attributes->get('purple') => 'peer-focus:ring-purple-500 dark:peer-focus:ring-purple-500 peer-checked:bg-purple-500', 36 | $this->attributes->get('fuchsia') => 'peer-focus:ring-fuchsia-500 dark:peer-focus:ring-fuchsia-500 peer-checked:bg-fuchsia-500', 37 | $this->attributes->get('pink') => 'peer-focus:ring-pink-500 dark:peer-focus:ring-pink-500 peer-checked:bg-pink-500', 38 | $this->attributes->get('rose') => 'peer-focus:ring-rose-500 dark:peer-focus:ring-rose-500 peer-checked:bg-rose-500', 39 | default => 'peer-focus:ring-primary dark:peer-focus:ring-primary peer-checked:bg-primary', // primary 40 | }; 41 | } 42 | 43 | public function getSizeClasses(): string 44 | { 45 | return match (true) { 46 | $this->attributes->get('sm') => 'w-9 h-5 after:h-4 after:w-4 after:start-[2px]', 47 | $this->attributes->get('md') => 'w-11 h-6 after:h-5 after:w-5 after:start-[2px]', 48 | $this->attributes->get('lg') => 'w-14 h-7 after:h-6 after:w-6 after:start-[4px]', 49 | default => 'w-11 h-6 after:h-5 after:w-5 after:start-[2px]', // md 50 | }; 51 | } 52 | } -------------------------------------------------------------------------------- /src/Traits/WithTcTable.php: -------------------------------------------------------------------------------- 1 | tcPerPage = session()->get('tcPerPage', $this->tcPerPage); 27 | } 28 | 29 | public function updated(string $propertyName) 30 | { 31 | if (in_array($propertyName, ['tcSearch', 'tcPerPage'])) { 32 | $this->resetPage(); 33 | 34 | // Save the current per-page count in the session 35 | if ($propertyName === 'tcPerPage') { 36 | session()->put('tcPerPage', $this->tcPerPage); 37 | } 38 | } 39 | } 40 | 41 | public function sortBy(string $column) 42 | { 43 | if ($this->sortCol === $column) { 44 | $this->sortAsc = ! $this->sortAsc; 45 | } else { 46 | $this->sortCol = $column; 47 | $this->sortAsc = false; 48 | } 49 | } 50 | 51 | public function tcApplySorting($query) 52 | { 53 | return $query->when($this->sortCol, function ($query) { 54 | // Handle Relationships Sorting 55 | if (str_contains($this->sortCol, '.')) { 56 | [$relation, $column] = explode('.', $this->sortCol); 57 | 58 | return $query->withAggregate($relation, $column) 59 | ->orderBy("{$relation}_{$column}", $this->sortAsc ? 'asc' : 'desc'); 60 | } 61 | 62 | // Default column sorting 63 | return $query->orderBy($this->sortCol, $this->sortAsc ? 'asc' : 'desc'); 64 | }); 65 | } 66 | 67 | public function resetProperty() 68 | { 69 | $this->tcSearch = null; 70 | $this->sortCol = null; 71 | $this->sortAsc = false; 72 | } 73 | 74 | public function clearSearch() 75 | { 76 | $this->tcSearch = null; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/Traits/WithTcToast.php: -------------------------------------------------------------------------------- 1 | 'text-green-500', 13 | 'warning' => 'text-yellow-500', 14 | 'error' => 'text-red-500', 15 | 'info' => 'text-blue-500', 16 | default => 'text-gray-500', 17 | }; 18 | } 19 | 20 | public function toast( 21 | string $typeOrMessage, 22 | ?string $title = null, 23 | ?string $description = null, 24 | ?string $position = null, 25 | ?string $icon = null, 26 | ?bool $showCloseIcon = null, 27 | ?bool $showProgress = null, 28 | ?int $timeout = null, 29 | ?string $redirectTo = null 30 | ) { 31 | $validTypes = ['success', 'info', 'warning', 'error']; 32 | 33 | // Determine if the first argument is a valid type or a message 34 | $type = in_array($typeOrMessage, $validTypes) ? $typeOrMessage : 'success'; 35 | $title = $title ?? ($type === $typeOrMessage ? 'Default message' : $typeOrMessage); 36 | 37 | $iconColor = $this->iconColorByType($type); 38 | 39 | $iconName = $icon ?? match ($type) { 40 | 'success' => 'check-circle', 41 | 'warning' => 'exclamation-triangle', 42 | 'error' => 'x-circle', 43 | 'info' => 'information-circle', 44 | default => 'check-circle', 45 | }; 46 | 47 | // Prepare the toast array 48 | $toast = [ 49 | 'type' => $type, 50 | 'title' => $title, 51 | 'description' => $description, 52 | 'position' => $position ?? config('tallcraftui.toast.position', 'bottom-right'), 53 | 'icon' => Blade::render(""), 54 | 'showCloseIcon' => $showCloseIcon ?? config('tallcraftui.toast.showCloseIcon', false), 55 | 'showProgress' => $showProgress ?? config('tallcraftui.toast.showProgress', false), 56 | 'timeout' => $timeout ?? ($redirectTo ? 6000 : config('tallcraftui.toast.timeout', 3000)), 57 | ]; 58 | 59 | // Trigger the JavaScript function to show the toast 60 | $this->js('toast('.json_encode(['toast' => $toast]).')'); 61 | 62 | if ($redirectTo) { 63 | return $this->redirect($redirectTo, navigate: true); 64 | } 65 | } 66 | 67 | public function success( 68 | string $title, 69 | ?string $description = null, 70 | ?string $position = null, 71 | string $icon = 'check-circle', 72 | ?bool $showCloseIcon = null, 73 | ?bool $showProgress = null, 74 | ?int $timeout = null, 75 | ?string $redirectTo = null 76 | ) { 77 | return $this->toast('success', $title, $description, $position, $icon, $showCloseIcon, $showProgress, $timeout, $redirectTo); 78 | } 79 | 80 | public function warning( 81 | string $title, 82 | ?string $description = null, 83 | ?string $position = null, 84 | string $icon = 'exclamation-triangle', 85 | ?bool $showCloseIcon = null, 86 | ?bool $showProgress = null, 87 | ?int $timeout = null, 88 | ?string $redirectTo = null 89 | ) { 90 | return $this->toast('warning', $title, $description, $position, $icon, $showCloseIcon, $showProgress, $timeout, $redirectTo); 91 | } 92 | 93 | public function error( 94 | string $title, 95 | ?string $description = null, 96 | ?string $position = null, 97 | string $icon = 'x-circle', 98 | ?bool $showCloseIcon = null, 99 | ?bool $showProgress = null, 100 | ?int $timeout = null, 101 | ?string $redirectTo = null 102 | ) { 103 | return $this->toast('error', $title, $description, $position, $icon, $showCloseIcon, $showProgress, $timeout, $redirectTo); 104 | } 105 | 106 | public function info( 107 | string $title, 108 | ?string $description = null, 109 | ?string $position = null, 110 | string $icon = 'information-circle', 111 | ?bool $showCloseIcon = null, 112 | ?bool $showProgress = null, 113 | ?int $timeout = null, 114 | ?string $redirectTo = null 115 | ) { 116 | return $this->toast('info', $title, $description, $position, $icon, $showCloseIcon, $showProgress, $timeout, $redirectTo); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/View/Components/Accordion/Accordion.php: -------------------------------------------------------------------------------- 1 | wire('model'); 20 | @endphp 21 | 22 |
whereDoesntStartWith('wire:model') 31 | ->twMerge([ 32 | 'relative w-full mx-auto overflow-hidden font-normal bg-transparent rounded-md', 33 | !$borderless ? 'border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700' : '', 34 | ]) 35 | }} 36 | > 37 | {{ $slot }} 38 |
39 | HTML; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/View/Components/Accordion/AccordionItem.php: -------------------------------------------------------------------------------- 1 | withoutTwMergeClasses()->twMerge([ 28 | 'cursor-pointer group', 29 | $activeBorder ? 'duration-200 ease-out bg-transparent border rounded-md' : '', 30 | ]) 31 | }} 32 | 33 | @if($activeBorder) 34 | :class="{ 35 | '{{ $activeClass }}' : activeItem === id, 36 | 'border-gray-200/60 dark:border-gray-700' : activeItem === id, 37 | 'border-transparent text-gray-600 dark:text-gray-300' : activeItem !== id, 38 | }" 39 | @endif 40 | 41 | :class="{ 42 | '{{ $activeClass }}' : activeItem === id, 43 | 'dark:text-gray-100 text-gray-800' : activeItem === id, 44 | 'text-gray-600 dark:text-gray-300' : activeItem !== id, 45 | }" 46 | > 47 | 82 | 83 |
84 |
twMergeFor('content', 'p-4 pt-0') }} 86 | :class="{ '{{ $activeContentClass }}' : activeItem === id }" 87 | > 88 | {{ $slot }} 89 |
90 |
91 | 92 | HTML; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/View/Components/Alert.php: -------------------------------------------------------------------------------- 1 | icon ?: match (true) { 29 | $this->attributes->get('yellow') || $this->attributes->get('orange') || $this->attributes->get('amber') => 'exclamation-triangle', 30 | $this->attributes->get('blue') || $this->attributes->get('secondary') => 'information-circle', 31 | $this->attributes->get('red') => 'x-circle', 32 | default => 'check-circle', 33 | }; 34 | } 35 | 36 | public function roundedClass(): string 37 | { 38 | return BorderRadiusHelper::getRoundedClass('alert', $this->attributes); 39 | } 40 | 41 | public function render(): View|Closure|string 42 | { 43 | return <<<'HTML' 44 | @php 45 | $alertTitle = $title ?? ($errors ? 'Something went wrong!' : 'Alert title goes here'); 46 | @endphp 47 | 48 |
withoutTwMergeClasses() 55 | ->except($colorAttributes) 56 | ->twMerge([ 57 | "p-3 text-sm transition duration-300 border", 58 | $getAlertClasses(), 59 | $roundedClass() 60 | ]) 61 | }} 62 | > 63 |
64 |
65 | 66 |
67 | 68 |
$description])> 69 |

70 | {{ $alertTitle }} 71 |

72 | 73 | @if($description) 74 |
75 | {{ $description }} 76 |
77 | @endif 78 | 79 | @if($errors) 80 |
    81 | @foreach($errors as $error) 82 |
  • {{ $error }}
  • 83 | @endforeach 84 |
85 | @endif 86 |
87 | 88 |
89 |
90 | @if($dismissible && !$actions) 91 | 101 | @else 102 | {{ $actions }} 103 | @endif 104 |
105 |
106 |
107 |
108 | HTML; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/View/Components/Avatar.php: -------------------------------------------------------------------------------- 1 | text); 29 | if (count($words) >= 2) { 30 | return strtoupper(substr($words[0], 0, 1) . substr($words[1], 0, 1)); 31 | } else { 32 | return strtoupper(substr($this->text, 0, 2)); 33 | } 34 | } 35 | 36 | public function placeholderClasses() 37 | { 38 | return $this->getAvatarBaseClasses() . ' flex items-center justify-center bg-gray-200 dark:bg-gray-700 text-gray-600 dark:text-gray-200 font-semibold'; 39 | } 40 | 41 | public function render(): View|Closure|string 42 | { 43 | return <<<'HTML' 44 |
45 | @if($image) 46 | {{ $alt }}withoutTwMergeClasses() 48 | ->twMerge([ 49 | 'inline-block object-cover', 50 | $getAvatarBaseClasses(), 51 | $roundedClass(), 52 | $ring ? "ring-2 ring-offset-2 {$getRingColor()}" : '' 53 | ]) 54 | }} 55 | /> 56 | @elseif($text) 57 |
withoutTwMergeClasses() 58 | ->twMerge([ 59 | $placeholderClasses(), 60 | $roundedClass(), 61 | $ring ? "ring-2 ring-offset-2 {$getRingColor()}" : '' 62 | ]) 63 | }} 64 | > 65 | {{ $placeholderText() }} 66 |
67 | @else 68 | withoutTwMergeClasses() 70 | ->twMerge([ 71 | 'inline-block bg-gray-100 overflow-hidden', 72 | $getAvatarBaseClasses(), 73 | $roundedClass(), 74 | $ring ? "ring-2 {$getRingColor()}" : '' 75 | ]) 76 | }} 77 | > 78 | 79 | 80 | 81 | 82 | 83 | 84 | @endif 85 | 86 | @if($badge || $badgeColor) 87 | twMergeFor('badge', $getBadgeClasses(), $getBadgePosition(), 'ring-white dark:ring-gray-100' ) }}> 88 | @endif 89 |
90 | HTML; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/View/Components/Avatars.php: -------------------------------------------------------------------------------- 1 | 26 | {{ $slot }} 27 | @if($plus) 28 | 39 | @endif 40 | 41 | HTML; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/View/Components/Badge.php: -------------------------------------------------------------------------------- 1 | attributes); 30 | } 31 | 32 | public function render(): View|Closure|string 33 | { 34 | return <<<'HTML' 35 | withoutTwMergeClasses() 37 | ->except($colorAttributes) 38 | ->twMerge([ 39 | "inline-flex gap-x-1 w-fit items-center justify-center font-semibold", 40 | $getSizeClasses(), 41 | $getColorClasses(), 42 | $getOutlineClasses(), 43 | $roundedClass(), 44 | ]) 45 | }} 46 | > 47 | @if($icon) 48 | twMergeFor('icon', $getIconSize()) }} /> 49 | @elseif ($iconLeft) 50 | twMergeFor('icon', $getIconSize()) }} /> 51 | @endif 52 | 53 | {{ $label ? __($label) : $slot }} 54 | 55 | @if($iconRight) 56 | twMergeFor('icon', $getIconSize()) }} /> 57 | @endif 58 | 59 | HTML; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/View/Components/Breadcrumb.php: -------------------------------------------------------------------------------- 1 | 17 |
    twMerge(["inline-flex items-center space-x-1 text-sm font-medium md:space-x-2"]) }}> 18 | {{ $slot }} 19 |
20 | 21 | HTML; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/View/Components/BreadcrumbItem.php: -------------------------------------------------------------------------------- 1 | 24 |
25 | @if($icon) 26 | twMergeFor('icon', 'text-gray-400 size-6') }} /> 27 | @endif 28 | 29 | @if(!$icon && !$iconNone) 30 | twMergeFor('icon', 'text-gray-400 size-6') }} /> 31 | @endif 32 | 33 | @isset($iconLeft) 34 | twMergeFor('icon', 'text-gray-400 size-6') }} /> 35 | @endisset 36 | 37 | @isset($href) 38 | withoutTwMergeClasses() 40 | ->twMerge(["text-gray-400 capitalize hover:text-gray-500 dark:text-gray-100 dark:hover:text-gray-400"]) 41 | }} 42 | > 43 | {{ __($label) }} 44 | 45 | @else 46 | withoutTwMergeClasses()->twMerge(["text-gray-500 capitalize dark:text-gray-400"]) }}> 47 | {{ __($label) }} 48 | 49 | @endisset 50 | 51 | @isset($iconRight) 52 | twMergeFor('icon', 'text-gray-400 size-6') }} /> 53 | @endisset 54 |
55 | 56 | HTML; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/View/Components/Button.php: -------------------------------------------------------------------------------- 1 | spinner == 1 ? $this->attributes->whereStartsWith('wire:click')->first() : $this->spinner; 41 | } 42 | 43 | public function buttonBaseClasses(): string 44 | { 45 | return 'inline-flex gap-x-1.5 items-center border border-transparent w-fit justify-center font-semibold uppercase tracking-widest disabled:opacity-50 disabled:pointer-events-none focus:outline-hidden focus:ring-2 focus:ring-offset-2 transition ease-in-out duration-200 dark:focus:ring-offset-0'; 46 | } 47 | 48 | public function roundedClass(): string 49 | { 50 | return BorderRadiusHelper::getRoundedClass('button', $this->attributes); 51 | } 52 | 53 | public function render(): View|Closure|string 54 | { 55 | return <<<'HTML' 56 | @if($link) 57 | except($colorAttributes)->whereDoesntStartWith('class')->merge(['type' => 'submit']) }} 73 | @endif 74 | 75 | {{ $attributes 76 | ->withoutTwMergeClasses() 77 | ->except($colorAttributes) 78 | ->twMerge([ 79 | $buttonBaseClasses(), 80 | $roundedClass(), 81 | $getColorClasses(), 82 | $getOutlineClasses(), 83 | $getFlatClasses(), 84 | $getSizeClasses(), 85 | $getCircleClasses(), 86 | ]) 87 | }} 88 | > 89 | 90 | @if($icon) 91 | twMergeFor('icon', $getIconSize()) }} /> 92 | @elseif ($iconLeft) 93 | twMergeFor('icon', $getIconSize()) }} /> 94 | @endif 95 | 96 | {{ $label ? __($label) : '' }} 97 | 98 | {{ $slot }} 99 | 100 | @if($iconRight && !$spinner) 101 | twMergeFor('icon', $getIconSize()) }} /> 102 | @endif 103 | 104 | @if($spinner) 105 | @if($spinnerBars) 106 | 107 | @elseif($spinnerDots) 108 | 109 | @elseif($spinnerPulse) 110 | 111 | @else 112 | 113 | @endif 114 | @endif 115 | 116 | @if($link) 117 | 118 | @else 119 | 120 | @endif 121 | HTML; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/View/Components/Card/Card.php: -------------------------------------------------------------------------------- 1 | twMerge([ 20 | 'border border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-800', 21 | $getRoundedClass(), 22 | $shadowClass(), 23 | ]) 24 | }}> 25 | {{ $slot }} 26 | 27 | HTML; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/View/Components/Card/CardContent.php: -------------------------------------------------------------------------------- 1 | twMerge(['px-5 py-5 space-y-3 sm:space-y-4']) }}> 15 | {{ $slot }} 16 | 17 | HTML; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/View/Components/Card/CardFigure.php: -------------------------------------------------------------------------------- 1 | withoutTwMergeClasses() 27 | ->twMerge([ 28 | 'relative overflow-hidden group', 29 | str_replace('rounded-sm', 'rounded-t', $getRoundedClass()), 30 | ]) 31 | }} 32 | > 33 | @if($img) 34 | {{ $alt ?? 'Image' }} $hoverable, 39 | str_replace('rounded-sm', 'rounded-t', $getRoundedClass()), 40 | ]) 41 | > 42 | @endif 43 | 44 | {{ $slot }} 45 | 46 | @if($caption) 47 |
twMergeFor( 49 | 'caption', 50 | 'absolute bottom-0 z-50 w-full px-5 py-2 text-sm text-gray-100 bg-transparent' 51 | )}} 52 | > 53 | {{ $caption }} 54 |
55 | @endif 56 | 57 |
twMergeFor( 58 | 'overlay', 59 | 'absolute inset-0 bg-black/20', 60 | str_replace('rounded-sm', 'rounded-t', $getRoundedClass()), 61 | $overlay ? 'block' : 'hidden' 62 | )}} 63 | >
64 | 65 | HTML; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/View/Components/Card/CardFooter.php: -------------------------------------------------------------------------------- 1 | twMerge(['px-5 pb-5']) }} > 15 | {{ $slot }} 16 | 17 | HTML; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/View/Components/Card/CardHeader.php: -------------------------------------------------------------------------------- 1 | twMerge(['px-5 pt-5']) }}> 20 |

{{ $title }}

21 | 22 | @if($subtitle) 23 |
{{ $subtitle }}
24 | @endif 25 | 26 | {{ $slot }} 27 | 28 | HTML; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/View/Components/Checkbox.php: -------------------------------------------------------------------------------- 1 | uuid = md5(serialize($this)); 24 | } 25 | 26 | public function roundedClass(): string 27 | { 28 | return BorderRadiusHelper::getRoundedClass('checkbox', $this->attributes); 29 | } 30 | 31 | public function disabledAndReadonlyClass(): string 32 | { 33 | return $this->attributes->get('disabled') || $this->attributes->get('readonly') ? 'text-gray-300 pointer-events-none' : ''; 34 | } 35 | 36 | public function render(): View|Closure|string 37 | { 38 | return <<<'HTML' 39 | @php 40 | $name = $attributes->wire('model')->value(); 41 | $error = $errors->has($name) ? $errors->first($name) : null; 42 | $uuid = $uuid . $name; 43 | $required = $attributes->get('required') ? true : false; 44 | $errorClass = $error ? 'border-red-300' : ''; 45 | @endphp 46 | 47 |
48 | @if($textLeft) 49 |
50 | @if($label) 51 | twMergeFor('label', $error ? 'text-red-500' : '') }} 53 | /> 54 | @endif 55 | 56 | @if($hint) 57 | 58 | @endif 59 | 60 | @if($error) 61 |

{{ $error }}

62 | @endif 63 |
64 | @endif 65 | 66 |
67 | except($colorAttributes) 70 | ->withoutTwMergeClasses() 71 | ->twMerge([ 72 | "border-gray-300", 73 | $getSizeClasses(), 74 | $getColorClasses(), 75 | $errorClass, 76 | $disabledAndReadonlyClass(), 77 | $roundedClass(), 78 | ]) 79 | }} 80 | /> 81 |
82 | 83 | 84 | @if(!$textLeft) 85 |
86 | @if($label) 87 | twMergeFor('label', $error ? 'text-red-500' : '') }} 89 | /> 90 | @endif 91 | 92 | @if($hint) 93 | 94 | @endif 95 |
96 | @endif 97 |
98 | HTML; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/View/Components/Clipboard.php: -------------------------------------------------------------------------------- 1 | { 29 | this.copied = true; 30 | this.$dispatch('copy', { text: this.content }); 31 | setTimeout(() => this.copied = false, {{ $timeout }}); 32 | }).catch(err => { 33 | this.$dispatch('copy-error', { error: err }); 34 | console.log('Failed to copy content to clipboard.'); 35 | }); 36 | } else { 37 | this.$dispatch('copy-error', { error: 'Clipboard API not supported' }); 38 | console.log('Clipboard API not supported.'); 39 | } 40 | } 41 | }" 42 | > 43 | 50 | 51 | HTML; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/View/Components/DropdownItem.php: -------------------------------------------------------------------------------- 1 | 28 | withoutTwMergeClasses()->twMerge([ 29 | 'inline-flex items-center w-full px-4 py-2 text-sm font-medium text-gray-600 dark:text-gray-300 gap-x-3 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-gray-700 dark:hover:text-white group transition ease-in-out cursor-pointer', 30 | ]) 31 | }} 32 | 33 | @if($link) 34 | href="{{ $link }}" 35 | @endif 36 | 37 | @if($link && $external) 38 | target="_blank" 39 | @endif 40 | 41 | @if($link && !$external && !$noWireNavigate) 42 | wire:navigate 43 | @endif 44 | > 45 | @if($icon) 46 | twMergeFor('icon', 'text-gray-400 transition ease-in-out group-hover:text-gray-500 dark:group-hover:text-gray-300') }} 50 | /> 51 | @endif 52 | 53 | {{ $label ? __($label) : '' }} 54 | 55 | {{ $slot }} 56 | 57 | @if($badge) 58 |
$badgeEnd])> 59 | twMergeFor('badge', 'rounded-full') }} /> 60 |
61 | @endif 62 |
63 | 64 | HTML; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/View/Components/Hint.php: -------------------------------------------------------------------------------- 1 | twMerge(["mt-1 text-sm text-gray-500 dark:text-gray-400"]) 20 | }} 21 | >{{ $hint }}

22 | HTML; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/View/Components/Icon.php: -------------------------------------------------------------------------------- 1 | solid ? 's' : $defaultStyle; 22 | 23 | return "heroicon-$iconFormat-$this->name"; 24 | } 25 | 26 | public function iconColor(): string 27 | { 28 | $configStyle = config('tallcraftui.icons.style', 'outline'); 29 | 30 | return match (true) { 31 | $this->solid || $configStyle === 'solid' => 'text-gray-400 dark:text-gray-400', 32 | default => '', 33 | }; 34 | } 35 | 36 | public function render(): View|Closure|string 37 | { 38 | return <<<'HTML' 39 | twMerge(['w-5 h-5', $iconColor()]) }} /> 40 | HTML; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/View/Components/Label.php: -------------------------------------------------------------------------------- 1 | get('checkbox') || $attributes->get('radio'); 33 | 34 | $notInline = !$inline && !$checkboxOrRadio ? "block mb-1.5": ""; 35 | @endphp 36 | 37 | 51 | HTML; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/View/Components/Markdown.php: -------------------------------------------------------------------------------- 1 | uuid = md5(serialize($this)); 24 | $this->uploadUrl = route('tallcraftui.upload', absolute: false); 25 | } 26 | 27 | public function getDefaultConfig(): array 28 | { 29 | return config('tallcraftui.markdown.config', []); 30 | } 31 | 32 | public function render(): View|Closure|string 33 | { 34 | return <<<'HTML' 35 | @php 36 | $name = $attributes->wire('model')->value(); 37 | $error = $errors->has($name) ? $errors->first($name) : null; 38 | $uuid = $uuid . $name; 39 | $required = $attributes->get('required') ? true : false; 40 | @endphp 41 | 42 |
$inline])> 43 | @if($label) 44 | twMergeFor('label') }} 46 | /> 47 | @endif 48 | 49 |
107 |
108 | 113 | 114 | 119 |
120 | 121 | @if($hint && !$error) 122 | 123 | @endif 124 | 125 | @if($error) 126 |

{{ $error }}

127 | @endif 128 |
129 |
130 | HTML; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/View/Components/Menu.php: -------------------------------------------------------------------------------- 1 | attributes); 23 | } 24 | 25 | public function roundedClass(): string 26 | { 27 | return BorderRadiusHelper::getRoundedClass('menu', $this->attributes); 28 | } 29 | 30 | public function shadowClass(): string 31 | { 32 | return ShadowHelper::getShadowClass('menu', $this->attributes); 33 | } 34 | 35 | public function render(): View|Closure|string 36 | { 37 | return <<<'HTML' 38 |
    withoutTwMergeClasses()->twMerge([ 39 | "z-10 py-1 mt-2 bg-white dark:bg-gray-800 ring-1 ring-black dark:ring-gray-700 ring-opacity-5 focus:outline-hidden", 40 | $widthClass(), 41 | $roundedClass(), 42 | $shadowClass(), 43 | ]) 44 | }} 45 | > 46 | @if($title) 47 |
  • twMergeFor("title", "flex items-center px-4 pt-1 pb-2 text-xs font-medium text-gray-400 dark:text-gray-500 uppercase gap-x-2") }}> 48 | @if($icon) 49 | twMergeFor('icon', 'size-4') }} 53 | /> 54 | @endif 55 | 56 | {{ __($title)}} 57 |
  • 58 | @endif 59 | 60 | {{ $slot }} 61 |
62 | HTML; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/View/Components/MenuItem.php: -------------------------------------------------------------------------------- 1 | 28 | withoutTwMergeClasses()->twMerge([ 29 | 'inline-flex items-center w-full px-4 py-2 text-sm font-medium text-gray-600 dark:text-gray-300 gap-x-3 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-gray-700 dark:hover:text-white group transition ease-in-out cursor-pointer', 30 | ]) 31 | }} 32 | 33 | @if($link) 34 | href="{{ $link }}" 35 | @endif 36 | 37 | @if($link && $external) 38 | target="_blank" 39 | @endif 40 | 41 | @if($link && !$external && !$noWireNavigate) 42 | wire:navigate 43 | @endif 44 | > 45 | @if($icon) 46 | twMergeFor('icon', 'text-gray-400 transition ease-in-out group-hover:text-gray-500 dark:group-hover:text-gray-300') }} 50 | /> 51 | @endif 52 | 53 | {{ $label ? __($label) : '' }} 54 | 55 | {{ $slot }} 56 | 57 | @if($badge) 58 |
$badgeEnd])> 59 | twMergeFor('badge', 'rounded-full') }} /> 60 |
61 | @endif 62 |
63 | 64 | HTML; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/View/Components/Modal.php: -------------------------------------------------------------------------------- 1 | wire('model')); 27 | @endphp 28 | 29 | 104 | HTML; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/View/Components/NativeSelect.php: -------------------------------------------------------------------------------- 1 | uuid = md5(serialize($this)); 28 | } 29 | 30 | public function roundedClass(): string 31 | { 32 | return BorderRadiusHelper::getRoundedClass('native-select', $this->attributes); 33 | } 34 | 35 | public function render(): View|Closure|string 36 | { 37 | return <<<'HTML' 38 |
39 | @php 40 | $name = $attributes->wire('model')->value(); 41 | $error = $errors->has($name) ? $errors->first($name) : null; 42 | $uuid = $uuid . $name; 43 | $required = $attributes->get('required') ? true : false; 44 | 45 | $errorClass = $error ? 'border-red-500 dark:border-red-500 focus:border-red-500 dark:focus:border-red-500 focus:ring-red-500': ''; 46 | $disabledClass = $attributes->get('disabled') ? "bg-gray-200 opacity-80 cursor-not-allowed" : ''; 47 | $readonlyClass = $attributes->get('readonly') ? "bg-gray-200 opacity-80 border-gray-400 border-dashed pointer-events-none" : ''; 48 | @endphp 49 | 50 | @if($label) 51 | twMergeFor('label') }} /> 52 | @endif 53 | 54 |
55 |
56 | 87 | 88 | @if($hint && !$error) 89 | 90 | @endif 91 | 92 | @if($error) 93 |

{{ $error }}

94 | @endif 95 |
96 |
97 |
98 | HTML; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/View/Components/Password.php: -------------------------------------------------------------------------------- 1 | uuid = md5(serialize($this)); 23 | } 24 | 25 | public function roundedClass(): string 26 | { 27 | return BorderRadiusHelper::getRoundedClass('input', $this->attributes); 28 | } 29 | 30 | public function iconLeftClass(): string 31 | { 32 | return $this->icon || $this->iconLeft ? 'pl-9' : ''; 33 | } 34 | 35 | public function disableClass(): string 36 | { 37 | return $this->attributes->get('disabled') ? 'bg-gray-200 opacity-80 cursor-not-allowed' : ''; 38 | } 39 | 40 | public function readonlyClass(): string 41 | { 42 | return $this->attributes->get('readonly') ? 'bg-gray-200 opacity-80 border-gray-400 border-dashed pointer-events-none' : ''; 43 | } 44 | 45 | public function render(): View|Closure|string 46 | { 47 | return <<<'HTML' 48 |
$inline]) 63 | > 64 | @php 65 | $name = $attributes->wire('model')->value(); 66 | $error = $errors->has($name) ? $errors->first($name) : null; 67 | $uuid = $uuid . $name; 68 | $required = $attributes->get('required') ? true : false; 69 | 70 | $errorClass = $error ? 'border-red-500 dark:border-red-500 focus:border-red-500 dark:focus:border-red-500 focus:ring-red-500': ''; 71 | @endphp 72 | 73 | @if($label) 74 | twMergeFor('label') }} /> 75 | @endif 76 | 77 |
78 | @if($iconLeft || $icon) 79 | 80 | twMergeFor('icon', 'dark:text-gray-400 size-4') }} /> 81 | 82 | @endif 83 | 84 |
85 | withoutTwMergeClasses() 94 | ->whereDoesntStartWith('wire:model') 95 | ->twMerge([ 96 | "block w-full border-gray-200 py-2.5 shadow-xs text-sm outline-hidden focus:ring-primary focus:border-primary dark:focus:border-primary dark:border-gray-700 dark:bg-gray-800 dark:text-gray-300 dark:placeholder-gray-400", 97 | $iconLeftClass(), 98 | $disableClass(), 99 | $readonlyClass(), 100 | $roundedClass(), 101 | $errorClass, 102 | ]) 103 | }} 104 | /> 105 |
106 | 107 | 108 | @if($generate) 109 | twMergeFor('icon', 'dark:text-gray-400 size-[18px] cursor-pointer') }} /> 110 | @endif 111 | 112 | twMergeFor('icon', 'dark:text-gray-400 size-[18px] cursor-pointer') }} /> 113 | twMergeFor('icon', 'dark:text-gray-400 size-[18px] cursor-pointer') }} /> 114 | 115 |
116 | 117 | @if($hint && !$error) 118 | 119 | @endif 120 | 121 | @if($error) 122 |

{{ $error }}

123 | @endif 124 |
125 | HTML; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/View/Components/Progress.php: -------------------------------------------------------------------------------- 1 | value / $this->max) * 100; 27 | } 28 | 29 | public function value(): string 30 | { 31 | return $this->dividedFormat ? ($this->value . '/' . $this->max) : ($this->value / $this->max * 100 . '%'); 32 | } 33 | 34 | public function render(): View|Closure|string 35 | { 36 | return <<<'HTML' 37 |
38 | @if($label && $labelPosition === 'top') 39 |
40 | {{ $label }} 41 | @if(!$withoutValue) 42 | {{ $value() }} 43 | @endif 44 |
45 | @endif 46 | 47 | 48 |
49 | 50 |
57 | @if(!$label && !$withoutValue ) 58 | {{ $value() }} 59 | @endif 60 |
61 |
62 | 63 | @if($label && $labelPosition === 'bottom') 64 |
65 | {{ $label }} 66 | @if(!$withoutValue) 67 | {{ $value() }} 68 | @endif 69 |
70 | @endif 71 |
72 | HTML; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/View/Components/ProgressRadial.php: -------------------------------------------------------------------------------- 1 | value / $this->max) * 100; 27 | } 28 | 29 | public function value(): string 30 | { 31 | return $this->dividedFormat ? ($this->value . '/' . $this->max) : ($this->value / $this->max * 100 . '%'); 32 | } 33 | 34 | public function render(): View|Closure|string 35 | { 36 | return <<<'HTML' 37 |
twMerge(['relative rounded-full', $getSizeClasses()['size']]) }}> 38 | 39 | 40 | 47 | 48 | 58 | 59 | 60 | @if(!$withoutValue) 61 |
62 | 63 | {{ $value() }} 64 | 65 |
66 | @endif 67 | 68 | @if($label) 69 |
70 | {{ $label }} 71 |
72 | @endif 73 |
74 | HTML; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/View/Components/Radio.php: -------------------------------------------------------------------------------- 1 | uuid = md5(serialize($this)); 23 | } 24 | 25 | public function disabledAndReadonlyClass(): string 26 | { 27 | return $this->attributes->get('disabled') || $this->attributes->get('readonly') ? 'text-gray-300 pointer-events-none' : ''; 28 | } 29 | 30 | public function render(): View|Closure|string 31 | { 32 | return <<<'HTML' 33 | @php 34 | $name = $attributes->wire('model')->value(); 35 | $error = $errors->has($name) ? $errors->first($name) : null; 36 | $uuid = $uuid . $name; 37 | $required = $attributes->get('required') ? true : false; 38 | $errorClass = $error ? 'border-red-300' : ''; 39 | @endphp 40 | 41 |
42 | @if($textLeft) 43 |
44 | @if($label) 45 | twMergeFor('label', $error ? 'text-red-500' : '') }} 47 | /> 48 | @endif 49 | 50 | @if($hint) 51 | 52 | @endif 53 | 54 | @if($error) 55 |

{{ $error }}

56 | @endif 57 |
58 | @endif 59 | 60 |
61 | except($colorAttributes) 64 | ->withoutTwMergeClasses() 65 | ->twMerge([ 66 | "border-gray-300", 67 | $getSizeClasses(), 68 | $getColorClasses(), 69 | $errorClass, 70 | $disabledAndReadonlyClass(), 71 | ]) 72 | }} 73 | /> 74 |
75 | 76 | 77 | @if(!$textLeft) 78 |
79 | @if($label) 80 | twMergeFor('label', $error ? 'text-red-500' : '') }} 82 | /> 83 | @endif 84 | 85 | @if($hint) 86 | 87 | @endif 88 |
89 | @endif 90 |
91 | HTML; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/View/Components/Range.php: -------------------------------------------------------------------------------- 1 | uuid = md5(serialize($this)); 25 | } 26 | 27 | public function render(): View|Closure|string 28 | { 29 | return <<<'HTML' 30 |
$inline])> 31 | @php 32 | $name = $attributes->wire('model')->value(); 33 | $error = $errors->has($name) ? $errors->first($name) : null; 34 | $uuid = $uuid . $name; 35 | $required = $attributes->get('required') ? true : false; 36 | @endphp 37 | 38 | @if($label) 39 | twMergeFor('label', !$inline ? 'mb-3' : '') }} 41 | /> 42 | @endif 43 | 44 |
45 | withoutTwMergeClasses() 54 | ->except($colorAttributes) 55 | ->twMerge([ 56 | "block w-full h-2 appearance-none cursor-pointer bg-transparent z-30", 57 | "[&::-webkit-slider-thumb]:w-5 [&::-webkit-slider-thumb]:h-5 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-0 [&::-moz-range-thumb]:w-5 [&::-moz-range-thumb]:h-5 [&::-moz-range-thumb]:appearance-none [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-0 [&::-ms-thumb]:w-5 [&::-ms-thumb]:h-5 [&::-ms-thumb]:appearance-none [&::-ms-thumb]:rounded-full [&::-ms-thumb]:border-0 [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:overflow-hidden [&::-moz-range-track]:rounded-full [&::-ms-track]:rounded-full [&::-moz-range-progress]:rounded-full [&::-ms-fill-lower]:rounded-full [&::-webkit-slider-runnable-track]:bg-gray-200 [&::-moz-range-track]:bg-gray-200 [&::-ms-track]:bg-gray-200 dark:[&::-webkit-slider-runnable-track]:bg-gray-800 dark:[&::-moz-range-track]:bg-gray-800 dark:[&::-ms-track]:bg-gray-800", 58 | $getColorClasses(), 59 | ]) 60 | }} 61 | /> 62 |
63 | 64 | @if($hint && !$error) 65 | !$inline]) /> 66 | @endif 67 | 68 | @if($error) 69 |

!$inline])>{{ $error }}

70 | @endif 71 |
72 | HTML; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/View/Components/Rating.php: -------------------------------------------------------------------------------- 1 | uuid = md5(serialize($this)); 24 | } 25 | 26 | public function render(): View|Closure|string 27 | { 28 | return <<<'HTML' 29 | @php 30 | $name = $attributes->wire('model')->value(); 31 | $error = $errors->has($name) ? $errors->first($name) : null; 32 | $uuid = $uuid . $name; 33 | $required = $attributes->get('required', false); 34 | @endphp 35 | 36 |
37 | @if($label) 38 | twMergeFor('label') }} 40 | /> 41 | @endif 42 | 43 |
50 | @for ($i = 1; $i <= $total; $i++) 51 | 77 | @endfor 78 |
79 | 80 | @if($hint) 81 | 82 | @endif 83 | 84 | @if($error) 85 |

{{ $error }}

86 | @endif 87 |
88 | HTML; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/View/Components/Separator.php: -------------------------------------------------------------------------------- 1 | title ? 'mb-3' : ''; 20 | } 21 | 22 | public function render(): View|Closure|string 23 | { 24 | return <<<'HTML' 25 |
withoutTwMergeClasses()->twMerge([ 26 | "border-0 h-[1px] my-1 bg-gray-100 dark:bg-gray-700", 27 | $titleClass(), 28 | ]) 29 | }} 30 | /> 31 | 32 | @if($title) 33 |
  • twMergeFor("title", "flex items-center gap-x-2 text-xs px-4 pb-1 uppercase font-medium text-gray-400 dark:text-gray-500") }}> 34 | @if($icon) 35 | twMergeFor('icon', 'size-4') }} 39 | /> 40 | @endif 41 | 42 | {{ __($title) }} 43 |
  • 44 | @endif 45 | HTML; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/View/Components/Spinner.php: -------------------------------------------------------------------------------- 1 | except($colorAttributes)->twMerge([$getColorClasses(), $getSizeClasses()]) }} xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"> 25 | @elseif($pulse) 26 | except($colorAttributes)->twMerge([$getColorClasses(), $getSizeClasses()]) }} xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"> 27 | @elseif($dots) 28 | except($colorAttributes)->twMerge(['animate-spin', str_replace('text-', 'fill-', $getColorClasses()), $getSizeClasses()]) }} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> 29 | @else 30 | except($colorAttributes)->twMerge(['animate-spin', $getColorClasses(), $getSizeClasses()]) }} xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"> 31 | @endif 32 | HTML; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/View/Components/Stat.php: -------------------------------------------------------------------------------- 1 | iconRight != null ? 'order-2' : ''; 30 | } 31 | 32 | public function roundedClass(): string 33 | { 34 | return BorderRadiusHelper::getRoundedClass('stat', $this->attributes); 35 | } 36 | 37 | public function render(): View|Closure|string 38 | { 39 | return <<<'HTML' 40 |
    except($colorAttributes) 42 | ->withoutTwMergeClasses() 43 | ->twMerge([ 44 | "flex flex-col bg-white border shadow-xs dark:bg-gray-800", 45 | $getColorClasses(), 46 | $roundedClass(), 47 | ]) 48 | }} 49 | > 50 |
    51 | @if($icon || $iconRight) 52 |
    twMergeFor( 53 | 'icon', 54 | "flex size-[46px] shrink-0 items-center text-gray-600 dark:text-gray-400 justify-center bg-gray-100 dark:bg-gray-700", 55 | $getIconBgColor(), 56 | $iconRightClass(), 57 | $roundedClass(), 58 | ) 59 | }}> 60 | 61 |
    62 | @endif 63 | 64 |
    $iconRight])> 65 |
    66 |

    {{ __($title) }}

    67 | 68 | @if($tooltip) 69 |
    70 | 71 |
    72 | @endif 73 |
    74 | 75 |
    76 |

    {{ __($number) }}

    77 | 78 | @if($increase || $decrease) 79 | $increase, 82 | 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-100' => $decrease, 83 | ])> 84 | 85 | 86 | @if(is_string($increase) || is_string($decrease)) 87 | {{ is_string($increase) ? $increase : $decrease }} 88 | @endif 89 | 90 | @endif 91 |
    92 |
    93 |
    94 |
    95 | HTML; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/View/Components/Tab/Tab.php: -------------------------------------------------------------------------------- 1 | as === 'switch' ? 'space-x-0 justify-between' : ''; 19 | } 20 | 21 | public function render(): View|Closure|string 22 | { 23 | return <<<'HTML' 24 |
    31 |
    whereDoesntStartWith('wire:model') 33 | ->withoutTwMergeClasses() 34 | ->twMerge([ 35 | $as === 'switch' ? 'bg-gray-100 dark:bg-gray-800 px-1 rounded-sm' : '', 36 | ($as != 'switch') && !$noSeparator ? 'border-b border-gray-200 dark:border-gray-700' : '', 37 | ]) 38 | }} 39 | > 40 | 46 |
    47 | 48 |
    twMergeFor('content', 'mt-4') }}> 49 | {{ $slot }} 50 |
    51 |
    52 | HTML; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/View/Components/Tab/TabContent.php: -------------------------------------------------------------------------------- 1 | twMerge([]) }} > 19 | {{ $slot }} 20 | 21 | HTML; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/View/Components/Tab/TabItem.php: -------------------------------------------------------------------------------- 1 | withoutTwMergeClasses()->twMerge([ 51 | 'text-sm px-1 inline-flex items-center justify-center font-semibold whitespace-nowrap transition ease-in-out', 52 | $as != 'switch' ? 'py-4 border-b-2 gap-x-1.5' : '', 53 | $as === 'switch' ? 'py-2 my-1 rounded-sm w-full gap-x-2' : '', 54 | ]) 55 | }} 56 | > 57 | @if($icon) 58 | twMergeFor('icon', 'size-[18px]') }} /> 59 | @endif 60 | 61 | {{ __($label) }} 62 | 63 | @if($iconRight) 64 | twMergeFor('icon', 'size-[18px]') }} /> 65 | @endif 66 | 67 | HTML; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/View/Components/Table/Index.php: -------------------------------------------------------------------------------- 1 | perPage) { 26 | if (is_bool($this->perPage)) { 27 | return [10, 20, 30, 50, 100]; 28 | } elseif (is_array($this->perPage)) { 29 | return $this->perPage; 30 | } 31 | } 32 | } 33 | 34 | public function shadowClass(): string 35 | { 36 | return ShadowHelper::getShadowClass('table', $this->attributes); 37 | } 38 | 39 | public function roundedClass(): string 40 | { 41 | return BorderRadiusHelper::getRoundedClass('table', $this->attributes); 42 | } 43 | 44 | public function render(): View|Closure|string 45 | { 46 | return <<<'HTML' 47 |
    twMerge([ 48 | 'border-gray-200 dark:border-gray-700', 49 | $shadowClass(), 50 | $roundedClass(), 51 | $attributes->get('borderless') ? '' : 'border divide-y divide-gray-200 dark:divide-gray-700' 52 | ]) 53 | }} 54 | > 55 | @if(isset($bulkActions) || $searchable || isset($filters)) 56 |
    57 |
    58 | @isset($bulkActions) 59 | {{ $bulkActions }} 60 | @endisset 61 |
    62 | 63 |
    64 | @if($searchable) 65 |
    66 | 67 |
    68 | 69 |
    70 |
    71 | @endif 72 | 73 | @isset($filters) 74 | {{ $filters }} 75 | @endisset 76 |
    77 |
    78 | @endif 79 | 80 |
    !$attributes->get('borderless')])> 81 |
    82 |
    83 |
    84 | $attributes->get('striped'), 93 | 'hoverable' => $attributes->get('hoverable'), 94 | 'divide-y divide-gray-200 dark:divide-gray-700' => !$attributes->get('borderless'), 95 | ])> 96 | @isset($heading) 97 | 98 | 99 | {{ $heading }} 100 | 101 | 102 | @endisset 103 | 104 | !$attributes->get('borderless'), 107 | ])> 108 | {{ $slot }} 109 | 110 |
    111 |
    112 |
    113 | 114 | @if(!$noLoading && !$noSpinner) 115 |
    117 | 118 |
    119 | @endif 120 |
    121 | 122 | @if($paginate) 123 |
    124 |
    125 | @if($perPage) 126 | Per page: 127 | 128 | 129 | @foreach($perPageValues() as $value) 130 | 131 | @endforeach 132 | 133 | @endif 134 |
    135 | 136 |
    137 | {{ $paginate->links(data: ['scrollTo' => false]) }} 138 |
    139 |
    140 | @endif 141 |
    142 |
    143 | HTML; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/View/Components/Table/NotFound.php: -------------------------------------------------------------------------------- 1 | 20 | 21 |
    22 |
    23 | twMergeFor('icon', 'p-3 mx-auto mb-1 text-gray-500 bg-gray-100 rounded-full dark:text-gray-400 dark:bg-gray-700 w-11 h-11') }} /> 24 | 25 |
    withoutTwMergeClasses()->twMerge(["text-xl font-bold text-gray-500 lg:text-2xl dark:text-gray-400"]) }}> 26 | {{ $label ? __($label) : __('No records found') }} 27 |
    28 |
    29 |
    30 | 31 | 32 | HTML; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/View/Components/Table/Td.php: -------------------------------------------------------------------------------- 1 | twMerge(['p-4 text-sm text-gray-500 whitespace-nowrap dark:text-gray-400']) }}> 19 | {{ $label ? __($label) : $slot }} 20 | 21 | HTML; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/View/Components/Table/Th.php: -------------------------------------------------------------------------------- 1 | sortBy ??= Str::snake(strtolower($this->label)); 20 | } 21 | 22 | public function render(): View|Closure|string 23 | { 24 | return <<<'HTML' 25 | twMerge(['p-4 text-xs font-medium text-left text-gray-500 uppercase dark:text-gray-400']) }}> 26 | @if($sortable) 27 | 39 | @else 40 | {{ $label ? __($label) : $slot }} 41 | @endif 42 | 43 | HTML; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/View/Components/Table/Tr.php: -------------------------------------------------------------------------------- 1 | except(['href']) 16 | ->twMerge([ 17 | $attributes->get('href') ? "cursor-pointer" : "", 18 | ]) 19 | }} 20 | 21 | @if($attributes->get('href')) 22 | onclick="window.location='{{ $attributes->get('href') }}'" 23 | @endif 24 | > 25 | {{ $slot }} 26 | 27 | HTML; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/View/Components/Textarea.php: -------------------------------------------------------------------------------- 1 | uuid = md5(serialize($this)); 24 | } 25 | 26 | public function roundedClass(): string 27 | { 28 | return BorderRadiusHelper::getRoundedClass('textarea', $this->attributes); 29 | } 30 | 31 | public function render(): View|Closure|string 32 | { 33 | return <<<'HTML' 34 |
    $inline])> 35 | @php 36 | $name = $attributes->wire('model')->value(); 37 | $error = $errors->has($name) ? $errors->first($name) : null; 38 | $uuid = $uuid . $name; 39 | $required = $attributes->get('required') ? true : false; 40 | @endphp 41 | 42 | @if($label) 43 | twMergeFor('label') }} /> 44 | @endif 45 | 46 |
    47 | @if($icon || $iconLeft) 48 | 49 | 50 | 51 | @endif 52 | 53 |
    54 | 85 | 86 | @if($hint && !$error) 87 | 88 | @endif 89 | 90 | @if($error) 91 |

    {{ $error }}

    92 | @endif 93 |
    94 | 95 | @if($iconRight) 96 | 97 | 98 | 99 | @endif 100 |
    101 |
    102 | HTML; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/View/Components/Toggle.php: -------------------------------------------------------------------------------- 1 | wire('model')->value(); 25 | $error = $errors->has($name) ? $errors->first($name) : null; 26 | 27 | // Remove extra space & make label lowercase 28 | $label = trim($label); 29 | 30 | // Check if the label contains '*' 31 | $hasStar = strpos($label, '*') !== false; 32 | 33 | // Remove '*' from the label for translation 34 | $labelWithoutStar = rtrim($label, ' *'); 35 | 36 | $isRequired = $hasStar || $required; 37 | @endphp 38 | 39 | 79 | HTML; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/View/Components/Tooltip.php: -------------------------------------------------------------------------------- 1 | gradient = $gradient ?? config('tallcraftui.tooltip.gradient', false); 19 | $this->noArrow = $noArrow ?? config('tallcraftui.tooltip.noArrow', false); 20 | $this->noTransition = $noTransition ?? config('tallcraftui.tooltip.noTransition', false); 21 | } 22 | 23 | public function position(): string 24 | { 25 | return match (true) { 26 | $this->attributes->get('top') => 'top', 27 | $this->attributes->get('bottom') => 'bottom', 28 | $this->attributes->get('left') => 'left', 29 | $this->attributes->get('right') => 'right', 30 | default => config('tallcraftui.tooltip.position', 'top'), 31 | }; 32 | } 33 | 34 | public function render(): View|Closure|string 35 | { 36 | return <<<'HTML' 37 |
    49 |
    $position() === 'top', 56 | '-bottom-0.5 left-1/2 -translate-x-1/2 -mb-0.5 translate-y-full' => $position() === 'bottom', 57 | 'top-1/2 -translate-y-1/2 -ml-0.5 -left-0.5 -translate-x-full' => $position() === 'left', 58 | 'top-1/2 -translate-y-1/2 -mr-0.5 -right-0.5 translate-x-full' => $position() === 'right' 59 | ]) 60 | > 61 |
    $gradient 74 | ]) 75 | > 76 |

    withoutTwMergeClasses() 79 | ->except(['top', 'bottom', 'left', 'right']) 80 | ->twMerge(['shrink-0 block text-xs whitespace-nowrap']) 81 | }} 82 | >

    83 |
    $position() === 'top', 89 | 'top-0 -translate-x-1/2 left-1/2 w-2.5 -translate-y-full' => $position() === 'bottom', 90 | 'right-0 -translate-y-1/2 top-1/2 h-2.5 -mt-px translate-x-full' => $position() === 'left', 91 | 'left-0 -translate-y-1/2 top-1/2 h-2.5 -mt-px -translate-x-full' => $position() === 'right' 92 | ]) 93 | > 94 |
    $gradient, 98 | 'origin-top-left -rotate-45' => $position() === 'top', 99 | 'origin-bottom-left rotate-45' => $position() === 'bottom', 100 | 'origin-top-left rotate-45' => $position() === 'left', 101 | 'origin-top-right -rotate-45' => $position() === 'right' 102 | ]) 103 | >
    104 |
    105 |
    106 |
    107 | 108 |
    twMergeFor('content') }}> 109 | @if ($slot->isEmpty()) 110 | 111 | @else 112 | {{ $slot }} 113 | @endif 114 |
    115 |
    116 | HTML; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/resources/css/tallcraftui.css: -------------------------------------------------------------------------------- 1 | @utility tc-table { 2 | & .table-striped tbody tr:nth-of-type(odd) { 3 | @apply bg-white dark:bg-transparent; 4 | } 5 | 6 | & .table-striped tbody tr:nth-of-type(even) { 7 | @apply bg-gray-50 dark:bg-gray-700; 8 | } 9 | 10 | & .hoverable tbody tr { 11 | @apply hover:bg-gray-50 dark:hover:bg-gray-700; 12 | } 13 | } 14 | 15 | @utility table-striped { 16 | .tc-table & tbody tr:nth-of-type(odd) { 17 | @apply bg-white dark:bg-transparent; 18 | } 19 | 20 | .tc-table & tbody tr:nth-of-type(even) { 21 | @apply bg-gray-50 dark:bg-gray-700; 22 | } 23 | } 24 | 25 | @utility hoverable { 26 | .tc-table & tbody tr { 27 | @apply hover:bg-gray-50 dark:hover:bg-gray-700; 28 | } 29 | } 30 | 31 | @utility tc-pagination { 32 | & nav div:nth-child(1) { 33 | @apply flex justify-between flex-1 gap-3 sm:hidden; 34 | } 35 | 36 | & nav div:nth-child(2) { 37 | @apply hidden sm:flex-1 sm:flex sm:items-center sm:justify-between; 38 | } 39 | 40 | & nav div:nth-child(2) div { 41 | @apply block; 42 | } 43 | 44 | & nav div:nth-child(2) div p { 45 | @apply flex gap-1; 46 | } 47 | 48 | & nav { 49 | @apply gap-5; 50 | } 51 | 52 | & nav div:nth-child(2) { 53 | @apply gap-5; 54 | } 55 | 56 | & nav button { 57 | @apply border focus:border-primary/50 focus:ring-3 ring-primary/50 active:bg-gray-100 active:text-gray-700 dark:bg-gray-800 dark:border-primary/50 dark:text-gray-400 dark:hover:text-gray-300 dark:focus:border-primary; 58 | } 59 | } 60 | --------------------------------------------------------------------------------