├── .babelrc ├── .gitignore ├── .vscode └── settings.json ├── README.md ├── composer.json ├── config └── swatches.php ├── dist ├── css │ └── field.css ├── js │ └── field.js └── mix-manifest.json ├── docs ├── clipboard.png ├── form-input.png ├── form-open.png ├── form-text-advanced.png ├── form.png └── index.png ├── package.json ├── resources ├── js │ ├── components │ │ ├── CustomDefaultField.vue │ │ ├── DetailField.vue │ │ ├── FormField.vue │ │ ├── IndexField.vue │ │ └── Swatch.vue │ └── field.js └── sass │ └── field.scss ├── src ├── FieldServiceProvider.php └── Swatches.php └── webpack.mix.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [] 3 | } 4 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.colorCustomizations": { 3 | "terminal.ansiBlack": "#F7F7F7", 4 | "terminal.ansiGreen": "#518a3c", 5 | "terminal.ansiBrightGreen": "#4fa367", 6 | "activityBar.background": "#2DCD78", 7 | "titleBar.activeBackground": "#3FD585", 8 | "titleBar.activeForeground": "#061D11" 9 | } 10 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nova Swatches 2 | 3 | A beautiful color picking field for Laravel Nova. Uses [vue-swatches](https://github.com/saintplay/vue-swatches). 4 | 5 | ## Screenshots 6 | 7 | 8 | 9 | 10 | ## Installation 11 | 12 | You can install the package into a Laravel application that uses Nova via composer: 13 | 14 | ``` 15 | composer require ynacorp/nova-swatches 16 | ``` 17 | 18 | ## Usage 19 | 20 | Just use the `Swatches` field in your Nova resource: 21 | 22 | ```php 23 | namespace App\Nova; 24 | 25 | use Yna\NovaSwatches\Swatches; 26 | 27 | class Article extends Resource 28 | { 29 | // ... 30 | 31 | public function fields(Request $request) 32 | { 33 | return [ 34 | // ... 35 | 36 | Swatches::make('Color'), 37 | 38 | // ... 39 | ]; 40 | } 41 | } 42 | ``` 43 | 44 | ## Customization 45 | 46 | ### Presets 47 | 48 | [vue-swatches](https://saintplay.github.io/vue-swatches/) provides a few color presets out of the box. 49 | 50 | ```php 51 | public function fields(Request $request) 52 | { 53 | return [ 54 | // ... 55 | 56 | // material-basic is a basic collection of material colors. 57 | Swatches::make('Color')->colors('material-basic'), 58 | 59 | // ... 60 | ]; 61 | } 62 | ``` 63 | 64 | Try switching between `material-basic`, `text-basic`, `text-advanced`, `material-light` and `material-dark`. 65 | 66 | If you're not satisfied with the presets, keep customizing as shown below. 67 | 68 | ### Palettes 69 | 70 | You can also provide an array of colors for the user to pick from. 71 | 72 | ```php 73 | public function fields(Request $request) 74 | { 75 | return [ 76 | // ... 77 | 78 | // material-basic is a basic collection of material colors. 79 | Swatches::make('Color')->colors(['#ffffff', '#000']), 80 | 81 | // ... 82 | ]; 83 | } 84 | ``` 85 | 86 | ### Anything else... 87 | 88 | [vue-swatches](https://saintplay.github.io/vue-swatches/) is extremely customizable, you can pass an array of `props` directly to it: 89 | 90 | ```php 91 | public function fields(Request $request) 92 | { 93 | return [ 94 | // ... 95 | 96 | Swatches::make('Color') 97 | ->withProps([ 98 | 'colors' => ["#4ae2c4", "#4fccff", "#41c84d"], 99 | 'show-fallback' => true, 100 | 'fallback-type' => 'input', 101 | 'popover-to' => 'left', 102 | 103 | // More options at https://saintplay.github.io/vue-swatches/api/props.html 104 | ]), 105 | 106 | // ... 107 | ]; 108 | } 109 | ``` 110 | 111 | Check out vue-swatches' [props section](https://saintplay.github.io/vue-swatches/api/props.html) for more options. 112 | 113 | ## Configuration 114 | 115 | While the `Swatches` component can be configured fluently, you can also set the defaults by publishing the package's config: 116 | 117 | ``` 118 | php artisan vendor:publish --tag=config --provider=Yna\\NovaSwatches\\FieldServiceProvider 119 | ``` 120 | 121 | Now edit file at the `config/nova/swatches.php` to customize the preferred defaults for your project: 122 | 123 | ```php 124 | [ 133 | 'colors' => 'basic', // Preset 134 | // 'colors' => 'material-basic', // Preset 135 | // 'colors' => ['#ffffff', '#000'], // Array 136 | 137 | // 'show-fallback' => true, 138 | // 'fallback-input-type' => 'input', // Or "color" 139 | ] 140 | ]; 141 | ``` 142 | 143 | ## Contribution 144 | 145 | We'd be glad to accept any contributions to Nova Swatches. 146 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ynacorp/nova-swatches", 3 | "description": "A beautiful color picking field for Laravel Nova.", 4 | "keywords": [ 5 | "laravel", 6 | "nova" 7 | ], 8 | "license": "MIT", 9 | "require": { 10 | "php": ">=7.1.0" 11 | }, 12 | "autoload": { 13 | "psr-4": { 14 | "Yna\\NovaSwatches\\": "src/" 15 | } 16 | }, 17 | "extra": { 18 | "laravel": { 19 | "providers": [ 20 | "Yna\\NovaSwatches\\FieldServiceProvider" 21 | ] 22 | } 23 | }, 24 | "config": { 25 | "sort-packages": true 26 | }, 27 | "minimum-stability": "dev", 28 | "prefer-stable": true 29 | } -------------------------------------------------------------------------------- /config/swatches.php: -------------------------------------------------------------------------------- 1 | [ 10 | 'colors' => 'basic', // Preset 11 | // 'colors' => 'material-basic', // Preset 12 | // 'colors' => ['#ffffff', '#000'], // Array 13 | 14 | // 'show-fallback' => true, 15 | // 'fallback-type' => 'input', // Or "color" 16 | ] 17 | ]; 18 | -------------------------------------------------------------------------------- /dist/css/field.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triolla-io/nova-swatches/464c3889eea98a1b789c09fddb8d66230f3f51c2/dist/css/field.css -------------------------------------------------------------------------------- /dist/mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/js/field.js": "/js/field.js", 3 | "/css/field.css": "/css/field.css" 4 | } -------------------------------------------------------------------------------- /docs/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triolla-io/nova-swatches/464c3889eea98a1b789c09fddb8d66230f3f51c2/docs/clipboard.png -------------------------------------------------------------------------------- /docs/form-input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triolla-io/nova-swatches/464c3889eea98a1b789c09fddb8d66230f3f51c2/docs/form-input.png -------------------------------------------------------------------------------- /docs/form-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triolla-io/nova-swatches/464c3889eea98a1b789c09fddb8d66230f3f51c2/docs/form-open.png -------------------------------------------------------------------------------- /docs/form-text-advanced.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triolla-io/nova-swatches/464c3889eea98a1b789c09fddb8d66230f3f51c2/docs/form-text-advanced.png -------------------------------------------------------------------------------- /docs/form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triolla-io/nova-swatches/464c3889eea98a1b789c09fddb8d66230f3f51c2/docs/form.png -------------------------------------------------------------------------------- /docs/index.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triolla-io/nova-swatches/464c3889eea98a1b789c09fddb8d66230f3f51c2/docs/index.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "npm run development", 5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 6 | "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 7 | "watch-poll": "npm run watch -- --watch-poll", 8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", 9 | "prod": "npm run production", 10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" 11 | }, 12 | "devDependencies": { 13 | "cross-env": "^5.0.0", 14 | "laravel-mix": "^1.0", 15 | "laravel-nova": "^1.0" 16 | }, 17 | "dependencies": { 18 | "v-clipboard": "^2.2.2", 19 | "vue": "^2.5.0", 20 | "vue-swatches": "^1.0.4" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /resources/js/components/CustomDefaultField.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 13 | {{ fieldLabel }} 14 | 15 | {{ 16 | __("*") 17 | }} 18 | 19 | 20 | 21 | 22 | 23 | 24 | 28 | {{ firstError }} 29 | 30 | 31 | 32 | {{ field.helpText }} 33 | 34 | 35 | 36 | 37 | 38 | 67 | -------------------------------------------------------------------------------- /resources/js/components/DetailField.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 43 | 44 | -------------------------------------------------------------------------------- /resources/js/components/FormField.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | 48 | -------------------------------------------------------------------------------- /resources/js/components/IndexField.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 16 | 17 | 24 | -------------------------------------------------------------------------------- /resources/js/components/Swatch.vue: -------------------------------------------------------------------------------- 1 | 2 | 9 | 13 | 14 | 15 | 16 | 17 | 18 | 62 | 63 | -------------------------------------------------------------------------------- /resources/js/field.js: -------------------------------------------------------------------------------- 1 | import Clipboard from 'v-clipboard' 2 | import "vue-swatches/dist/vue-swatches.min.css"; 3 | import Swatches from "vue-swatches"; 4 | 5 | Nova.booting((Vue, router, store) => { 6 | Vue.use(Clipboard) 7 | 8 | Vue.component('index-nova-swatches', require('./components/IndexField')) 9 | Vue.component('detail-nova-swatches', require('./components/DetailField')) 10 | Vue.component('form-nova-swatches', require('./components/FormField')) 11 | Vue.component('swatches', Swatches) 12 | }) 13 | -------------------------------------------------------------------------------- /resources/sass/field.scss: -------------------------------------------------------------------------------- 1 | // Nova Tool CSS 2 | -------------------------------------------------------------------------------- /src/FieldServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([ 24 | __DIR__ . '/../config/swatches.php' => config_path('nova/swatches.php'), 25 | ], 'config'); 26 | } 27 | 28 | /** 29 | * Register any application services. 30 | * 31 | * @return void 32 | */ 33 | public function register() 34 | { 35 | // 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Swatches.php: -------------------------------------------------------------------------------- 1 | withProps($props); 38 | } 39 | } 40 | 41 | /** 42 | * @return $this 43 | */ 44 | public function hideLabelFromForms() 45 | { 46 | return $this->withMeta(['hideLabelFromForms' => true]); 47 | } 48 | 49 | /** 50 | * @param string|array $colors 51 | * @return $this 52 | */ 53 | public function colors($colors) 54 | { 55 | return $this->withProps(['colors' => $colors]); 56 | } 57 | 58 | /** 59 | * @param string $direction 60 | * @return $this 61 | */ 62 | public function popoverTo($direction) 63 | { 64 | return $this->withProps(['popoverTo' => $direction]); 65 | } 66 | 67 | /** 68 | * @param string $length 69 | * @return $this 70 | */ 71 | public function rowLength($length) 72 | { 73 | return $this->withProps(['rowLength' => $length]); 74 | } 75 | 76 | /** 77 | * @param string|boolean $inputType - "text" | "color" | false 78 | * @return $this 79 | */ 80 | public function showFallback($inputType = 'text') 81 | { 82 | if (!$inputType) { 83 | return $this->withProp('showFallback', false); 84 | } 85 | 86 | return $this->withProps([ 87 | 'showFallback' => true, 88 | 'fallbackInputType' => $inputType, 89 | ]); 90 | } 91 | 92 | /** 93 | * Pass a prop directly to vue-swatches. 94 | * 95 | * See https://saintplay.github.io/vue-swatches/#sub-props 96 | * 97 | * @param string $name 98 | * @param mixed $value 99 | * @return $this 100 | */ 101 | public function withProp($name, $value) 102 | { 103 | return $this->withProps([$name => $value]); 104 | } 105 | 106 | /** 107 | * Pass an array of props directly to vue-swatches. 108 | * 109 | * See https://saintplay.github.io/vue-swatches/#sub-props 110 | * 111 | * @param array $array 112 | * @return $this 113 | */ 114 | public function withProps($array) 115 | { 116 | $this->props = array_merge($this->props, $array); 117 | 118 | return $this->withMeta(['props' => $this->props]); 119 | } 120 | 121 | public function withDefault($color) 122 | { 123 | return $this->withMeta(['value' => $color]); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /webpack.mix.js: -------------------------------------------------------------------------------- 1 | let mix = require('laravel-mix') 2 | 3 | mix 4 | .setPublicPath('dist') 5 | .js('resources/js/field.js', 'js') 6 | .sass('resources/sass/field.scss', 'css') 7 | --------------------------------------------------------------------------------