diff --git a/.eslintrc b/.eslintrc new file mode 100755 index 0000000..b9cb388 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,20 @@ +{ + "extends": [ + "eslint:recommended", + "plugin:vue/essential", + "prettier" + ], + "parserOptions": { + "ecmaVersion": 2017 + }, + "globals": { + "Nova": true + }, + "env": { + "browser": true, + "node": true + }, + "rules": { + "vue/html-indent": ["error", 4] + } +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..71c30c2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,13 @@ +# Path-based git attributes +# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html + +# Ignore all test and documentation with "export-ignore". +/.gitattributes export-ignore +/.gitignore export-ignore +/.travis.yml export-ignore +/phpunit.xml.dist export-ignore +/.scrutinizer.yml export-ignore +/.styleci.yml export-ignore +/tests export-ignore +/.editorconfig export-ignore +/docs export-ignore \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e35177a --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +/.idea +/vendor +/node_modules +package-lock.json +composer.phar +composer.lock +phpunit.xml +.phpunit.result.cache +.DS_Store +Thumbs.db +yarn.lock diff --git a/.prettierrc b/.prettierrc new file mode 100755 index 0000000..4f07bd9 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "printWidth": 200, + "singleQuote": true, + "tabWidth": 4, + "trailingComma": "es5" +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..1cacd8c --- /dev/null +++ b/composer.json @@ -0,0 +1,39 @@ +{ + "name": "ericlagarda/nova-text-card", + "description": "A custom card for Laravel Nova to show Text in cards with some good options", + "keywords": [ + "laravel", + "nova", + "card", + "text" + ], + "license": "MIT", + "authors": [ + { + "name": "Eric Lagarda", + "email": "eric@infinety.es", + "role": "Developer" + } + ], + "require": { + "php": ">=7.1.0", + "laravel/nova": "*" + }, + "autoload": { + "psr-4": { + "Ericlagarda\\NovaTextCard\\": "src/" + } + }, + "extra": { + "laravel": { + "providers": [ + "Ericlagarda\\NovaTextCard\\CardServiceProvider" + ] + } + }, + "config": { + "sort-packages": true + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/dist/js/card.js b/dist/js/card.js new file mode 100644 index 0000000..2414f26 --- /dev/null +++ b/dist/js/card.js @@ -0,0 +1 @@ +!function(t){var e={};function n(r){if(e[r])return e[r].exports;var s=e[r]={i:r,l:!1,exports:{}};return t[r].call(s.exports,s,s.exports,n),s.l=!0,s.exports}n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=0)}([function(t,e,n){t.exports=n(1)},function(t,e,n){Nova.booting(function(t){t.component("text-card",n(2))})},function(t,e,n){var r=n(3)(n(4),n(5),!1,null,null,null);t.exports=r.exports},function(t,e){t.exports=function(t,e,n,r,s,i){var o,a=t=t||{},c=typeof t.default;"object"!==c&&"function"!==c||(o=t,a=t.default);var d,u="function"==typeof a?a.options:a;if(e&&(u.render=e.render,u.staticRenderFns=e.staticRenderFns,u._compiled=!0),n&&(u.functional=!0),s&&(u._scopeId=s),i?(d=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),r&&r.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(i)},u._ssrRegister=d):r&&(d=r),d){var l=u.functional,f=l?u.render:u.beforeCreate;l?(u._injectStyles=d,u.render=function(t,e){return d.call(e),f(t,e)}):u.beforeCreate=f?[].concat(f,d):[d]}return{esModule:o,exports:a,options:u}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default={props:["card"],methods:{fixPixels:function(t){return"auto"==t?"auto":"default"==t?"":parseInt(t,10)+"px"}},computed:{textClassList:function(){return this.card.center?"text-center":""},cardClassList:function(){return this.cardCenter+" "+this.textClassList},cardStyle:function(){return{height:this.card.height?this.fixPixels(this.card.height):"auto"}},cardCenter:function(){return this.card.center?"items-center":""}},mounted:function(){this.card.forceFullWidth&&(this.$parent.$el.classList.remove("w-5/6"),this.$parent.$el.classList.add("w-full"))}}},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("card",{staticClass:"card flex flex-col justify-center",class:t.cardClassList,style:t.cardStyle},[n("div",{staticClass:"px-3 py-3"},[t.card.headingRaw?n("div",{domProps:{innerHTML:t._s(t.card.heading)}}):[t.card.heading?n("h1",{staticClass:"text-3xl text-80 font-light",class:t.textClassList},[t._v(t._s(t.card.heading))]):t._e()],t._v(" "),t.card.textRaw?n("div",{domProps:{innerHTML:t._s(t.card.text)}}):[t.card.text?n("p",{staticClass:"text-80 font-light mt-2"},[t._v(t._s(t.card.text))]):t._e()]],2)])},staticRenderFns:[]}}]); \ No newline at end of file diff --git a/dist/mix-manifest.json b/dist/mix-manifest.json new file mode 100644 index 0000000..af50d33 --- /dev/null +++ b/dist/mix-manifest.json @@ -0,0 +1,3 @@ +{ + "/js/card.js": "/js/card.js" +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..eb5f90a --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "private": true, + "scripts": { + "dev": "npm run development", + "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", + "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", + "watch-poll": "npm run watch -- --watch-poll", + "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", + "prod": "npm run production", + "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", + "check-format": "prettier --list-different 'resources/**/*.{css,js,vue}'", + "format": "prettier --write 'resources/**/*.{css,js,vue}'", + "lint": "eslint resources/js --fix --ext js,vue" + }, + "devDependencies": { + "cross-env": "^5.0.0", + "eslint": "^4.19.1", + "eslint-config-prettier": "^2.9.0", + "eslint-plugin-vue": "^4.4.0", + "laravel-mix": "^1.0", + "prettier": "^1.14.0" + }, + "dependencies": { + "vue": "^2.5.0" + } +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..4b9063b --- /dev/null +++ b/readme.md @@ -0,0 +1,66 @@ +# Nova Text Card + +A custom card for Laravel Nova to show Text in cards with some good options. + +![preview](https://user-images.githubusercontent.com/74367/53241396-dd2f2600-36a1-11e9-8ee8-7341fbc58172.png) + +## Installation + +You can install the package in to a Laravel app that uses [Nova](https://nova.laravel.com) via composer: + + +```bash +composer require ericlagarda/nova-text-card +``` + +Then, register your new link in the `cards` method of the `NovaServiceProvider` or your `ResourceTool` class. + +```php + +public function cards() +{ + return [ + // ... + // Examples from the preview image + + (new TextCard()) + ->forceFullWidth() + ->heading('My custom awesome heading') + ->text('Congue platea augue fames nullam morbi vehicula egestas lobortis lacus adipiscing eleifend'), + + (new TextCard()) + ->width('1/2') + ->height(100) + ->center(false) + ->heading('Custom card no centered') + ->text('Congue platea augue fames nullam morbi'), + + (new TextCard()) + ->width('1/2') + ->height() + ->text('

This is a custom card with text and no heading. Height is set to auto.

') + ->textAsHtml(), + + (new TextCard()) + ->forceFullWidth() + ->height(90) + ->heading('

Just a heading text with a smile

') + ->headingAsHtml(), + ]; +} +``` + +## Card options + +* `->width('string')`: Width of the card. +* `->forceFullWidth()`: Force the card to be full width. A fix for nova cards order. +* `->height('string or number'):`Height of the Card. If is called without options height will be auto. Default to nova card height. +* `->center(boolean)`: If you want the text centered or not. Default to true +* `->heading('string or html')`: Heading text or custom html. Default to false. No heading text is shown. +* `->text('string or html')`: Text of the card or custom html. Default to false. No text is shown. +* `->headingAsHtml()`: If you want to print the heading as HTML +* `->textAsHtml()`: If you want to print the text as HTML + + + + diff --git a/resources/js/card.js b/resources/js/card.js new file mode 100644 index 0000000..f64814b --- /dev/null +++ b/resources/js/card.js @@ -0,0 +1,3 @@ +Nova.booting(Vue => { + Vue.component('text-card', require('./components/Card')); +}); diff --git a/resources/js/components/Card.vue b/resources/js/components/Card.vue new file mode 100644 index 0000000..de4ed5e --- /dev/null +++ b/resources/js/components/Card.vue @@ -0,0 +1,58 @@ + + + diff --git a/src/CardServiceProvider.php b/src/CardServiceProvider.php new file mode 100644 index 0000000..7c25893 --- /dev/null +++ b/src/CardServiceProvider.php @@ -0,0 +1,32 @@ +withMeta([ + 'center' => true, + 'height' => 'default', + 'heading' => false, + 'text' => false, + 'headingRaw' => false, + 'textRaw' => false, + 'forceFullWidth' => false, + ]); + } + + /** + * The width of the card (1/3, 1/2, or full). + * + * @var string + */ + public $width = '1/3'; + + /** + * Get the component name for the element. + * + * @return string + */ + public function component() + { + return 'text-card'; + } + + /** + * Set the text link + * + * @param array $text + * + * @return array + */ + public function center($boolean = true) + { + return $this->withMeta(['center' => $boolean]); + } + + /** + * Set the text link + * + * @param array $text + * + * @return array + */ + public function heading($text) + { + return $this->withMeta(['heading' => $text]); + } + + /** + * Set the height of card + * + * @param array $text + * + * @return array + */ + public function headingAsHtml() + { + return $this->withMeta(['headingRaw' => true]); + } + + /** + * Set the text link + * + * @param array $text + * + * @return array + */ + public function text($text) + { + return $this->withMeta(['text' => $text]); + } + + /** + * Set the height of card + * + * @param array $text + * + * @return array + */ + public function textAsHtml() + { + return $this->withMeta(['textRaw' => true]); + } + + /** + * Set the height of card + * + * @param array $text + * + * @return array + */ + public function height($height = 'auto') + { + return $this->withMeta(['height' => $height]); + } + + /** + * Set the height of card + * + * @param array $text + * + * @return array + */ + public function forceFullWidth() + { + return $this->withMeta(['forceFullWidth' => true, 'width' => '5/6']); + } + + /** + * Prepare the element for JSON serialization. + * + * @return array + */ + public function jsonSerialize() + { + return array_merge([ + 'name' => str_random(16), + 'width' => $this->width, + ], parent::jsonSerialize()); + } +} diff --git a/webpack.mix.js b/webpack.mix.js new file mode 100644 index 0000000..48ba617 --- /dev/null +++ b/webpack.mix.js @@ -0,0 +1,4 @@ +let mix = require('laravel-mix') + +mix.setPublicPath('dist') + .js('resources/js/card.js', 'js')