├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── dist ├── css │ └── filter.css ├── js │ └── filter.js └── mix-manifest.json ├── nova.mix.js ├── package.json ├── resources ├── css │ └── filter.css └── js │ ├── components │ └── RangeInputFilter.vue │ └── filter.js ├── screenshots ├── dark.png └── light.png ├── src ├── RangeInputFilter.php └── RangeInputFilterServiceProvider.php ├── tailwind.config.js ├── webpack.mix.js └── yarn.lock /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: milewski 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /vendor 3 | /node_modules 4 | package-lock.json 5 | composer.phar 6 | composer.lock 7 | phpunit.xml 8 | .phpunit.result.cache 9 | .DS_Store 10 | Thumbs.db 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Digital Creative 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nova Range Input Filter 2 | 3 | [](https://packagist.org/packages/digital-creative/nova-range-input-filter) 4 | [](https://packagist.org/packages/digital-creative/nova-range-input-filter) 5 | [](https://github.com/dcasia/nova-range-input-filter/blob/main/LICENSE) 6 | 7 | A Laravel Nova range input filter. 8 | 9 | 10 | 11 | 12 | 13 | 14 | # Installation 15 | 16 | You can install the package via composer: 17 | 18 | ``` 19 | composer require digital-creative/nova-range-input-filter 20 | ``` 21 | 22 | ## Basic Usage 23 | 24 | Create a filter as usual and extend the `DigitalCreative\RangeInputFilter\RangeInputFilter` class 25 | 26 | ```php 27 | use DigitalCreative\RangeInputFilter\RangeInputFilter; 28 | 29 | class MyFilter extends RangeInputFilter { 30 | 31 | public function apply(NovaRequest $request, $query, $value) 32 | { 33 | $from = data_get($value, 'from'); 34 | $to = data_get($value, 'to'); 35 | } 36 | 37 | } 38 | ``` 39 | 40 | and use it as usual on the filters methods within your resource class: 41 | 42 | ```php 43 | class ExampleNovaResource extends Resource { 44 | 45 | public function filters(NovaRequest $request): array 46 | { 47 | return [ 48 | MyFilter::make() 49 | ]; 50 | } 51 | 52 | } 53 | ``` 54 | 55 | ### Options 56 | 57 | The available options are straight forward: 58 | 59 | ```php 60 | class ExampleNovaResource extends Resource { 61 | 62 | public function filters(NovaRequest $request): array 63 | { 64 | return [ 65 | MyFilter::make() 66 | ->dividerLabel('<>') // control the divider label in between the inputs 67 | ->inputType('week') // supports any html input type 68 | ->placeholder('From', 'To') // control the placeholder of the inputs 69 | ->fromAttributes([ 'min' => 0 ]) // some inputs type like number accepts more attributes like min/max/step etc.. 70 | ->toAttributes([ 'max' => 100 ]) 71 | ]; 72 | } 73 | 74 | } 75 | ``` 76 | 77 | Due to the size limitation of the native nova filter box some input types may not look as expected, for this reason you can 78 | use [Nova Mega Filter](https://github.com/dcasia/nova-mega-filter) package instead which is a drop-in replacement for the native filter box. 79 | 80 | ## ⭐️ Show Your Support 81 | 82 | Please give a ⭐️ if this project helped you! 83 | 84 | ### Other Packages You Might Like 85 | 86 | - [Nova Dashboard](https://github.com/dcasia/nova-dashboard) - The missing dashboard for Laravel Nova! 87 | - [Nova Welcome Card](https://github.com/dcasia/nova-welcome-card) - A configurable version of the `Help card` that comes with Nova. 88 | - [Icon Action Toolbar](https://github.com/dcasia/icon-action-toolbar) - Replaces the default boring action menu with an inline row of icon-based actions. 89 | - [Expandable Table Row](https://github.com/dcasia/expandable-table-row) - Provides an easy way to append extra data to each row of your resource tables. 90 | - [Collapsible Resource Manager](https://github.com/dcasia/collapsible-resource-manager) - Provides an easy way to order and group your resources on the sidebar. 91 | - [Resource Navigation Tab](https://github.com/dcasia/resource-navigation-tab) - Organize your resource fields into tabs. 92 | - [Resource Navigation Link](https://github.com/dcasia/resource-navigation-link) - Create links to internal or external resources. 93 | - [Nova Mega Filter](https://github.com/dcasia/nova-mega-filter) - Display all your filters in a card instead of a tiny dropdown! 94 | - [Nova Pill Filter](https://github.com/dcasia/nova-pill-filter) - A Laravel Nova filter that renders into clickable pills. 95 | - [Nova Slider Filter](https://github.com/dcasia/nova-slider-filter) - A Laravel Nova filter for picking range between a min/max value. 96 | - [Nova Range Input Filter](https://github.com/dcasia/nova-range-input-filter) - A Laravel Nova range input filter. 97 | - [Nova FilePond](https://github.com/dcasia/nova-filepond) - A Nova field for uploading File, Image and Video using Filepond. 98 | - [Custom Relationship Field](https://github.com/dcasia/custom-relationship-field) - Emulate HasMany relationship without having a real relationship set between resources. 99 | - [Column Toggler](https://github.com/dcasia/column-toggler) - A Laravel Nova package that allows you to hide/show columns in the index view. 100 | - [Batch Edit Toolbar](https://github.com/dcasia/batch-edit-toolbar) - Allows you to update a single column of a resource all at once directly from the index page. 101 | 102 | ## License 103 | 104 | The MIT License (MIT). Please see [License File](https://raw.githubusercontent.com/dcasia/nova-range-input-filter/master/LICENSE) for more information. 105 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "digital-creative/nova-range-input-filter", 3 | "description": "A Laravel Nova range input filter.", 4 | "keywords": [ 5 | "laravel", 6 | "nova", 7 | "range", 8 | "input", 9 | "filter" 10 | ], 11 | "authors": [ 12 | { 13 | "name": "Rafael Milewski" 14 | } 15 | ], 16 | "license": "MIT", 17 | "require": { 18 | "php": ">=8.1", 19 | "laravel/nova": "^4.0" 20 | }, 21 | "autoload": { 22 | "psr-4": { 23 | "DigitalCreative\\RangeInputFilter\\": "src/" 24 | } 25 | }, 26 | "extra": { 27 | "laravel": { 28 | "providers": [ 29 | "DigitalCreative\\RangeInputFilter\\RangeInputFilterServiceProvider" 30 | ] 31 | } 32 | }, 33 | "config": { 34 | "sort-packages": true 35 | }, 36 | "minimum-stability": "dev", 37 | "prefer-stable": true 38 | } 39 | -------------------------------------------------------------------------------- /dist/css/filter.css: -------------------------------------------------------------------------------- 1 | .range-input-filter :is(.mx-2){margin-left:.5rem;margin-right:.5rem}.range-input-filter :is(.block){display:block}.range-input-filter :is(.flex){display:flex}.range-input-filter :is(.w-full){width:100%}.range-input-filter :is(.items-center){align-items:center}.range-input-filter :is(.px-3){padding-left:.75rem;padding-right:.75rem}.range-input-filter :is(.text-center){text-align:center}.range-input-filter :is(.text-sm){font-size:.875rem;line-height:1.25rem}.range-input-filter :is(.filter){filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)} 2 | -------------------------------------------------------------------------------- /dist/js/filter.js: -------------------------------------------------------------------------------- 1 | (()=>{"use strict";var e,t={217:(e,t,r)=>{const n=Vue;var o={class:"flex flex-no-wrap items-center"},i=["type","placeholder"],l={class:"text-sm mx-2 text-center"},a=["type","placeholder"];function c(e){return c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},c(e)}function u(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function f(e){for(var t=1;t{},744:(e,t)=>{t.Z=(e,t)=>{const r=e.__vccOpts||e;for(const[e,n]of t)r[e]=n;return r}}},r={};function n(e){var o=r[e];if(void 0!==o)return o.exports;var i=r[e]={exports:{}};return t[e](i,i.exports,n),i.exports}n.m=t,e=[],n.O=(t,r,o,i)=>{if(!r){var l=1/0;for(f=0;f=i)&&Object.keys(n.O).every((e=>n.O[e](r[c])))?r.splice(c--,1):(a=!1,i0&&e[f-1][2]>i;f--)e[f]=e[f-1];e[f]=[r,o,i]},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={599:0,319:0};n.O.j=t=>0===e[t];var t=(t,r)=>{var o,i,[l,a,c]=r,u=0;if(l.some((t=>0!==e[t]))){for(o in a)n.o(a,o)&&(n.m[o]=a[o]);if(c)var f=c(n)}for(t&&t(r);un(217)));var o=n.O(void 0,[319],(()=>n(655)));o=n.O(o)})(); -------------------------------------------------------------------------------- /dist/mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/js/filter.js": "/js/filter.js", 3 | "/css/filter.css": "/css/filter.css" 4 | } 5 | -------------------------------------------------------------------------------- /nova.mix.js: -------------------------------------------------------------------------------- 1 | const mix = require('laravel-mix') 2 | const webpack = require('webpack') 3 | const path = require('path') 4 | 5 | class NovaExtension { 6 | name() { 7 | return 'nova-extension' 8 | } 9 | 10 | register(name) { 11 | this.name = name 12 | } 13 | 14 | webpackConfig(webpackConfig) { 15 | webpackConfig.externals = { 16 | vue: 'Vue', 17 | } 18 | 19 | webpackConfig.resolve.alias = { 20 | ...(webpackConfig.resolve.alias || {}), 21 | } 22 | 23 | webpackConfig.output = { 24 | uniqueName: this.name, 25 | } 26 | } 27 | } 28 | 29 | mix.extend('nova', new NovaExtension()) 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "watch": "mix watch", 5 | "production": "mix --production", 6 | "nova:install": "npm --prefix='../../vendor/laravel/nova' ci" 7 | }, 8 | "devDependencies": { 9 | "@vue/compiler-sfc": "^3.3.4", 10 | "laravel-mix": "^6.0.49", 11 | "mix-tailwindcss": "^1.3.0", 12 | "postcss": "^8.4.31", 13 | "sass": "^1.68.0", 14 | "sass-loader": "^13.3.2", 15 | "tailwindcss": "^3.3.3", 16 | "vue-loader": "^17.2.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /resources/css/filter.css: -------------------------------------------------------------------------------- 1 | @tailwind components; 2 | @tailwind utilities; 3 | -------------------------------------------------------------------------------- /resources/js/components/RangeInputFilter.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ filter.name }} 6 | 7 | 8 | 9 | 10 | 11 | 18 | 19 | 20 | {{ filter.dividerLabel || __('to') }} 21 | 22 | 23 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 82 | -------------------------------------------------------------------------------- /resources/js/filter.js: -------------------------------------------------------------------------------- 1 | import RangeInputFilter from './components/RangeInputFilter' 2 | 3 | Nova.booting((app, store) => { 4 | app.component('range-input-filter', RangeInputFilter) 5 | }) 6 | -------------------------------------------------------------------------------- /screenshots/dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dcasia/nova-range-input-filter/d30220866396afa63de44f17aafd7a09e8af81d4/screenshots/dark.png -------------------------------------------------------------------------------- /screenshots/light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dcasia/nova-range-input-filter/d30220866396afa63de44f17aafd7a09e8af81d4/screenshots/light.png -------------------------------------------------------------------------------- /src/RangeInputFilter.php: -------------------------------------------------------------------------------- 1 | withMeta([ 'fromPlaceholder' => $fromPlaceholder, 'toPlaceholder' => $toPlaceholder ]); 16 | } 17 | 18 | public function dividerLabel(string $dividerLabel): self 19 | { 20 | return $this->withMeta([ 'dividerLabel' => $dividerLabel ]); 21 | } 22 | 23 | public function inputType(string $inputType): self 24 | { 25 | return $this->withMeta([ 'inputType' => $inputType ]); 26 | } 27 | 28 | public function fromAttributes(array $attributes): self 29 | { 30 | return $this->withMeta([ 'fromAttributes' => $attributes ]); 31 | } 32 | 33 | public function toAttributes(array $attributes): self 34 | { 35 | return $this->withMeta([ 'toAttributes' => $attributes ]); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/RangeInputFilterServiceProvider.php: -------------------------------------------------------------------------------- 1 |