├── .eslintrc.js ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── composer.json ├── composer.lock ├── dist ├── css │ └── field.css ├── js │ └── field.js └── mix-manifest.json ├── package-lock.json ├── package.json ├── public └── images │ └── demo.gif ├── resources ├── js │ ├── components │ │ ├── DetailField.vue │ │ ├── FormField.vue │ │ ├── IndexField.vue │ │ └── RowFields │ │ │ ├── AddRow.vue │ │ │ ├── Fields │ │ │ ├── RowCarouselField.vue │ │ │ ├── RowImageField.vue │ │ │ ├── RowTextField.vue │ │ │ └── RowVideoField.vue │ │ │ └── RowContainer.vue │ ├── field.js │ ├── mixins │ │ └── Miscellaneous.js │ └── utils │ │ └── icons.js └── sass │ └── field.scss ├── src ├── FieldServiceProvider.php └── PostContent.php └── webpack.mix.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parserOptions: { 4 | parser: 'babel-eslint', 5 | sourceType: 'module' 6 | }, 7 | env: { 8 | browser: true, 9 | node: true, 10 | es6: true, 11 | }, 12 | extends: ['eslint:recommended'], 13 | 14 | // add your custom rules here 15 | //it is based on older Vues JS config, which was my preference https://github.com/vuejs/eslint-config-vue 16 | rules: { 17 | "vue/max-attributes-per-line": [2, { 18 | "singleline": 10, 19 | "multiline": { 20 | "max": 1, 21 | "allowFirstLine": false 22 | } 23 | }], 24 | "vue/name-property-casing": ["error", "PascalCase"], 25 | 'accessor-pairs': 2, 26 | 'arrow-spacing': [2, { 27 | 'before': true, 28 | 'after': true 29 | }], 30 | 'block-spacing': [2, 'always'], 31 | 'brace-style': [2, '1tbs', { 32 | 'allowSingleLine': true 33 | }], 34 | 'camelcase': [0, { 35 | 'properties': 'always' 36 | }], 37 | 'comma-dangle': [2, 'never'], 38 | 'comma-spacing': [2, { 39 | 'before': false, 40 | 'after': true 41 | }], 42 | 'comma-style': [2, 'last'], 43 | 'constructor-super': 2, 44 | 'curly': [2, 'multi-line'], 45 | 'dot-location': [2, 'property'], 46 | 'eol-last': 2, 47 | 'eqeqeq': [2, 'allow-null'], 48 | 'generator-star-spacing': [2, { 49 | 'before': true, 50 | 'after': true 51 | }], 52 | 'handle-callback-err': [2, '^(err|error)$'], 53 | 'indent': [2, 2, { 54 | 'SwitchCase': 1 55 | }], 56 | 'jsx-quotes': [2, 'prefer-single'], 57 | 'key-spacing': [2, { 58 | 'beforeColon': false, 59 | 'afterColon': true 60 | }], 61 | 'keyword-spacing': [2, { 62 | 'before': true, 63 | 'after': true 64 | }], 65 | 'new-cap': [2, { 66 | 'newIsCap': true, 67 | 'capIsNew': false 68 | }], 69 | 'new-parens': 2, 70 | 'no-array-constructor': 2, 71 | 'no-caller': 2, 72 | 'no-console': 'off', 73 | 'no-class-assign': 2, 74 | 'no-cond-assign': 2, 75 | 'no-const-assign': 2, 76 | 'no-control-regex': 2, 77 | 'no-delete-var': 2, 78 | 'no-dupe-args': 2, 79 | 'no-dupe-class-members': 2, 80 | 'no-dupe-keys': 2, 81 | 'no-duplicate-case': 2, 82 | 'no-empty-character-class': 2, 83 | 'no-empty-pattern': 2, 84 | 'no-eval': 2, 85 | 'no-ex-assign': 2, 86 | 'no-extend-native': 2, 87 | 'no-extra-bind': 2, 88 | 'no-extra-boolean-cast': 2, 89 | 'no-extra-parens': [2, 'functions'], 90 | 'no-fallthrough': 2, 91 | 'no-floating-decimal': 2, 92 | 'no-func-assign': 2, 93 | 'no-implied-eval': 2, 94 | 'no-inner-declarations': [2, 'functions'], 95 | 'no-invalid-regexp': 2, 96 | 'no-irregular-whitespace': 2, 97 | 'no-iterator': 2, 98 | 'no-label-var': 2, 99 | 'no-labels': [2, { 100 | 'allowLoop': false, 101 | 'allowSwitch': false 102 | }], 103 | 'no-lone-blocks': 2, 104 | 'no-mixed-spaces-and-tabs': 2, 105 | 'no-multi-spaces': 2, 106 | 'no-multi-str': 2, 107 | 'no-multiple-empty-lines': [2, { 108 | 'max': 1 109 | }], 110 | 'no-native-reassign': 2, 111 | 'no-negated-in-lhs': 2, 112 | 'no-new-object': 2, 113 | 'no-new-require': 2, 114 | 'no-new-symbol': 2, 115 | 'no-new-wrappers': 2, 116 | 'no-obj-calls': 2, 117 | 'no-octal': 2, 118 | 'no-octal-escape': 2, 119 | 'no-path-concat': 2, 120 | 'no-proto': 2, 121 | 'no-redeclare': 2, 122 | 'no-regex-spaces': 2, 123 | 'no-return-assign': [2, 'except-parens'], 124 | 'no-self-assign': 2, 125 | 'no-self-compare': 2, 126 | 'no-sequences': 2, 127 | 'no-shadow-restricted-names': 2, 128 | 'no-spaced-func': 2, 129 | 'no-sparse-arrays': 2, 130 | 'no-this-before-super': 2, 131 | 'no-throw-literal': 2, 132 | 'no-trailing-spaces': 2, 133 | 'no-undef': 0, 134 | 'no-undef-init': 2, 135 | 'no-unexpected-multiline': 2, 136 | 'no-unmodified-loop-condition': 2, 137 | 'no-unneeded-ternary': [2, { 138 | 'defaultAssignment': false 139 | }], 140 | 'no-unreachable': 2, 141 | 'no-unsafe-finally': 2, 142 | 'no-unused-vars': [2, { 143 | 'vars': 'all', 144 | 'args': 'none' 145 | }], 146 | 'no-useless-call': 2, 147 | 'no-useless-computed-key': 2, 148 | 'no-useless-constructor': 2, 149 | 'no-useless-escape': 0, 150 | 'no-whitespace-before-property': 2, 151 | 'no-with': 2, 152 | 'one-var': [2, { 153 | 'initialized': 'never' 154 | }], 155 | 'operator-linebreak': [2, 'after', { 156 | 'overrides': { 157 | '?': 'before', 158 | ':': 'before' 159 | } 160 | }], 161 | 'padded-blocks': [2, 'never'], 162 | 'quotes': [2, 'single', { 163 | 'avoidEscape': true, 164 | 'allowTemplateLiterals': true 165 | }], 166 | 'semi': [2, 'never'], 167 | 'semi-spacing': [2, { 168 | 'before': false, 169 | 'after': true 170 | }], 171 | 'space-before-blocks': [2, 'always'], 172 | 'space-before-function-paren': [2, 'never'], 173 | 'space-in-parens': [2, 'never'], 174 | 'space-infix-ops': 2, 175 | 'space-unary-ops': [2, { 176 | 'words': true, 177 | 'nonwords': false 178 | }], 179 | 'spaced-comment': [2, 'always', { 180 | 'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','] 181 | }], 182 | 'template-curly-spacing': [2, 'never'], 183 | 'use-isnan': 2, 184 | 'valid-typeof': 2, 185 | 'wrap-iife': [2, 'any'], 186 | 'yield-star-spacing': [2, 'both'], 187 | 'yoda': [2, 'never'], 188 | 'prefer-const': 2, 189 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, 190 | 'object-curly-spacing': [2, 'always', { 191 | objectsInObjects: false 192 | }], 193 | 'array-bracket-spacing': [2, 'never'] 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | > Please make sure you: 11 | > - [ ] Write a descriptive title 12 | > - [ ] Fill out the required sections as clearly as you can 13 | > - [ ] Remove the unfilled sections 14 | > - [ ] Add a Priority label 15 | 16 | Bug Description (required) 17 | ---------------------------- 18 | ... 19 | 20 | Where ? (required) 21 | ----------------- 22 | - [ ] Detail 23 | - [ ] Form 24 | - [ ] Index 25 | - [ ] Other: ... 26 | 27 | To Reproduce 28 | -------------- 29 | 1. ... 30 | 2. ... 31 | 3. ... 32 | 33 | Logs, Error Outputs 34 | ------------------- 35 | Please keep it short. If long, please paste a [GithubGist](https://gist.github.com/) link. 36 | 37 | ... 38 | 39 | Screenshots 40 | ----------- 41 | ... 42 | 43 | Tasks 44 | ----- 45 | - [ ] ... 46 | - [ ] ... 47 | - [ ] ... 48 | 49 | 50 | Additional Comments 51 | ------------------- 52 | ... 53 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | > Please make sure you: 11 | > - [ ] Write a descriptive title 12 | > - [ ] Fill out the required sections as clearly as you can 13 | > - [ ] Remove the unfilled sections 14 | > - [ ] Add a Priority label 15 | 16 | Feature Description (required) 17 | ---------------------------- 18 | ... 19 | 20 | Where ? (required) 21 | ----------------- 22 | - [ ] Detail 23 | - [ ] Form 24 | - [ ] Index 25 | - [ ] Other: ... 26 | 27 | UX / UI screenshots 28 | -------------------- 29 | ... 30 | 31 | Tasks 32 | ----- 33 | - [ ] ... 34 | - [ ] ... 35 | - [ ] ... 36 | 37 | 38 | Additional Comments 39 | ------------------- 40 | ... 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /vendor 3 | /.idea 4 | .env 5 | .phpunit.result.cache 6 | npm-debug.log 7 | yarn-error.log 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of the repository. 3 | 4 | ### How to Contribute 5 | 1. Please open an issue before submitting a pull request. 6 | 1. Fork the guillaumeferron/post-content. 7 | 1. Make your changes on the fork. 8 | 1. Submit a PR to the guillaumeferron/post-content **master** branch. 9 | 10 | ### Coding conventions 11 | 12 | Start reading my code and you'll get the hang of it. We optimize for readability: 13 | 14 | * PSR-2 Coding Standard - The easiest way to apply the conventions is to run `make phplint`, which uses [PHP Coding Standards Fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer). 15 | * ESLINT Coding Syntax - Please have your IDE / Text editor respect the eslint as I won't accept a PR that is not compliant. 16 | * For weight's sake, eslint node package isn't included in the repository, but please have alook at [eslintrc.js](eslintrc.js) file. 17 | 18 | ### Security 19 | 20 | If you discover any security related issues, please email guillaume.ferron2@gmail.com instead of using the issue tracker. 21 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 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. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Nova / Post Content 2 | 3 | This package adds a custom field to nova resources. 4 | 5 | The field is a post content writer and supports images, videos, paragraphs and carousels. 6 | 7 |  8 | 9 | [Demo Video](https://www.loom.com/share/eb8fee941c4d4050a9b8641f593c7800) 10 | 11 | ## How it works 12 | 13 | This package adds orderable rows: 14 | 15 | Currently this package only supports : 16 | - Plain text paragraphs. 17 | - Url-provided images. 18 | - Url-provided videos (Youtube | Vimeo | Server Storage). 19 | - Images / Videos carousels. 20 | 21 | ## Installation and usage 22 | 23 | You may require this package using composer: 24 | 25 | ``` 26 | composer require guillaumeferron/post-content 27 | ``` 28 | 29 | You can directly use the PostContent in the ```fields()``` methods by relating it to a **longText** SQL attribute: 30 | 31 | ``` 32 | PostContent::make('attribute_name') 33 | ``` 34 | 35 | ### Customization 36 | You can customize the field behavior : 37 | 38 | 39 | ##### withFields 40 | ``` 41 | PostContent::make('attribute_name')->withFields([options]) 42 | ``` 43 | *Choose the fields to be added as new rows* 44 | 45 | | Function | Type | Default | Values | 46 | |-----------------------|--------|----------------------------------------|----------------------------------------| 47 | | ->withFields(options) | Array | ['text', 'image', 'video', 'carousel'] | {'text', 'image', 'video', 'carousel'} | 48 | 49 | 50 | ##### withCarouselFields 51 | ``` 52 | PostContent::make('attribute_name')->withCarouselFields([options]) 53 | ``` 54 | *Choose the fields to be added as new carousel's slides* 55 | 56 | | Function | Type | Default | Values | 57 | |-----------------------|--------|----------------------------------------|----------------------------------------| 58 | | ->withCarouselFields([options]) | Array | ['image', 'video'] | {'image', 'video'} | 59 | 60 | 61 | ##### withFileManager 62 | ``` 63 | PostContent::make('attribute_name')->withFileManager('url') 64 | ``` 65 | *Specify the file manager url if it exists. Recommendation: [Nova FileManager](https://packagist.org/packages/infinety-es/nova-filemanager)* 66 | 67 | | Function | Type | Default | 68 | |-----------------------|--------|----------------------------------------| 69 | | ->withFileManager('url') | String | '' | 70 | 71 | 72 | ##### hideHelpers 73 | ``` 74 | PostContent::make('attribute_name')->hideHelpers() 75 | ``` 76 | *Hide the blue background helpers displayed when a row needs to be filled* 77 | 78 | ## Roadmap 79 | - [ ] Make the initial row dynamic depending on what fields are specified or not. 80 | - [ ] Make the paragraphs' text editor WYSIWYG. 81 | - [ ] Add the two columns options to the paragraphs. 82 | 83 | 84 | ## License 85 | 86 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 87 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "guillaumeferron/post-content", 3 | "description": "A post content builder 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 | "Guillaumeferron\\PostContent\\": "src/" 15 | } 16 | }, 17 | "extra": { 18 | "laravel": { 19 | "providers": [ 20 | "Guillaumeferron\\PostContent\\FieldServiceProvider" 21 | ] 22 | } 23 | }, 24 | "config": { 25 | "sort-packages": true 26 | }, 27 | "minimum-stability": "dev", 28 | "prefer-stable": true 29 | } 30 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "05240f15aee24036bdef1330b36c5c59", 8 | "packages": [], 9 | "packages-dev": [], 10 | "aliases": [], 11 | "minimum-stability": "dev", 12 | "stability-flags": [], 13 | "prefer-stable": true, 14 | "prefer-lowest": false, 15 | "platform": { 16 | "php": ">=7.1.0" 17 | }, 18 | "platform-dev": [], 19 | "plugin-api-version": "1.1.0" 20 | } 21 | -------------------------------------------------------------------------------- /dist/css/field.css: -------------------------------------------------------------------------------- 1 | .VueCarousel-slide{min-height:200px}.VueCarousel-navigation-next{right:43px!important} -------------------------------------------------------------------------------- /dist/mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/js/field.js": "/js/field.js", 3 | "/css/field.css": "/css/field.css" 4 | } -------------------------------------------------------------------------------- /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 | "vue": "^2.5.0", 19 | "vue-carousel": "^0.16.1", 20 | "vue-vimeo-player": "0.0.9", 21 | "vue-youtube": "^1.3.3", 22 | "vuedraggable": "^2.17.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /public/images/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuillaumeFerron/post-content/ce5b2a36e679f5bbc5ac5531a842cfe124826cb9/public/images/demo.gif -------------------------------------------------------------------------------- /resources/js/components/DetailField.vue: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 16 | 17 | 22 | 23 | 28 | 29 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 62 | -------------------------------------------------------------------------------- /resources/js/components/FormField.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 17 | 18 | 23 | 24 | 29 | 30 | 35 | 36 | 37 | 38 | 39 | 42 | 43 | 44 | 45 | 46 | 187 | -------------------------------------------------------------------------------- /resources/js/components/IndexField.vue: -------------------------------------------------------------------------------- 1 | 2 | N/A 3 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /resources/js/components/RowFields/AddRow.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 12 | 15 | 16 | 17 | 18 | {{ option.name }} 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 92 | 93 | 160 | -------------------------------------------------------------------------------- /resources/js/components/RowFields/Fields/RowCarouselField.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 16 | 17 | 23 | 24 | 25 | 26 | 27 | 28 | 32 | 33 | 38 | 39 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 194 | 195 | 200 | -------------------------------------------------------------------------------- /resources/js/components/RowFields/Fields/RowImageField.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ __('Please provide the image URL') }} 6 | 9 | {{ __('File Manager') }} 10 | 11 | 12 | 16 | 18 | {{ __('Submit') }} 19 | 20 | 21 | 22 | {{ value }} 23 | 24 | 25 | 26 | 63 | 64 | 89 | -------------------------------------------------------------------------------- /resources/js/components/RowFields/Fields/RowTextField.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | {{ value }} 10 | 11 | 12 | 13 | 14 | 62 | -------------------------------------------------------------------------------- /resources/js/components/RowFields/Fields/RowVideoField.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ __('Please provide the video URL') }} 6 | 9 | {{ __('File Manager') }} 10 | 11 | 12 | 13 | {{ __('Submit') }} 14 | 15 | 16 | 17 | 18 | 19 | 20 | {{ value }} 21 | 22 | 23 | 24 | 98 | 99 | 120 | -------------------------------------------------------------------------------- /resources/js/components/RowFields/RowContainer.vue: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 112 | 113 | 225 | 226 | -------------------------------------------------------------------------------- /resources/js/field.js: -------------------------------------------------------------------------------- 1 | import vueVimeoPlayer from 'vue-vimeo-player' 2 | import VueCarousel from 'vue-carousel' 3 | import VueYoutube from 'vue-youtube' 4 | 5 | Nova.booting((Vue, router) => { 6 | Vue.use(vueVimeoPlayer) 7 | Vue.use(VueCarousel) 8 | Vue.use(VueYoutube) 9 | Vue.component('index-PostContent', require('./components/IndexField')) 10 | Vue.component('detail-PostContent', require('./components/DetailField')) 11 | Vue.component('form-PostContent', require('./components/FormField')) 12 | }) 13 | -------------------------------------------------------------------------------- /resources/js/mixins/Miscellaneous.js: -------------------------------------------------------------------------------- 1 | export default { 2 | methods: { 3 | /** 4 | * Generates a id slug 5 | * 6 | * @param length 7 | */ 8 | generateId(length = 10) { 9 | return '_' + Math.random().toString(36).substr(2, length - 1) 10 | } 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /resources/js/utils/icons.js: -------------------------------------------------------------------------------- 1 | export const textIcon = '' + 4 | '' + 5 | '' + 6 | '' + 7 | '' + 8 | '' 9 | 10 | export const imageIcon = '' + 13 | '' 19 | 20 | export const videoIcon = '' + 25 | '' + 26 | '' 34 | 35 | export const carouselIcon = '' + 38 | '' + 40 | '' + 41 | '' + 42 | '' + 43 | '' 44 | 45 | export const moveIcon = '' + 47 | '' + 51 | '' + 55 | '' + 59 | '' 63 | 64 | export const addIcon = '' 70 | 71 | export const trashIcon = '\n' + 72 | '\n' + 73 | '' 74 | 75 | export const checkIcon = '\n' + 76 | '\n' + 77 | '' 78 | 79 | export const cancelIcon = '\n' + 80 | '\n' + 81 | '' -------------------------------------------------------------------------------- /resources/sass/field.scss: -------------------------------------------------------------------------------- 1 | // Carousel 2 | .VueCarousel-slide { 3 | min-height: 200px; 4 | } 5 | 6 | .VueCarousel-navigation-next { 7 | right: 43px !important; 8 | } 9 | -------------------------------------------------------------------------------- /src/FieldServiceProvider.php: -------------------------------------------------------------------------------- 1 | withMeta((['fields' => $fields])); 25 | } 26 | 27 | /** 28 | * Sets the fields to be used when adding a new carousel slide 29 | * 30 | * @param array $carousel_fields 31 | * @return PostContent 32 | */ 33 | public function withCarouselFields(array $carousel_fields) 34 | { 35 | return $this->withMeta(['carousel_fields' => $carousel_fields]); 36 | } 37 | 38 | /** 39 | * Set the file manager url to be used when adding a video or an image 40 | * 41 | * @param string $file_manager_url 42 | * @return PostContent 43 | */ 44 | public function withFileManager(string $file_manager_url) 45 | { 46 | return $this->withMeta(['file_manager_url' => $file_manager_url]); 47 | } 48 | 49 | /** 50 | * Hide the helpers 51 | * 52 | * @return PostContent 53 | */ 54 | public function hideHelpers() 55 | { 56 | return $this->withMeta(['hide_helpers' => true]); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /webpack.mix.js: -------------------------------------------------------------------------------- 1 | let mix = require('laravel-mix') 2 | 3 | mix.setPublicPath('dist') 4 | .js('resources/js/field.js', 'js') 5 | .sass('resources/sass/field.scss', 'css') 6 | --------------------------------------------------------------------------------
{{ value }}