The beauty of Mantine UI lies in its ability to streamline the development process. Within minutes of installation, I found myself immersed in a world where creating captivating interfaces and functional components became effortless. The intuitive design of the library, coupled with its comprehensive documentation, allows developers to integrate it seamlessly into their projects.
One of the key advantages of Mantine UI is its versatility. Whether it’s crafting simple layouts or building complex interactive elements, the library excels in catering to a wide range of project requirements. Additionally, the flexibility it offers in terms of customization empowers developers to tailor components to suit their specific needs.
As I delved deeper into my projects, I began to explore the realm of custom components. Leveraging the extensibility of Mantine UI, I crafted bespoke elements that not only enhanced the visual appeal of my applications but also added a unique touch of personalization.
In retrospect, my experience with Mantine UI has been marked by efficiency and creativity. The library’s seamless integration with NextJS and TypeScript has elevated the development process, allowing me to focus on innovation and design without being encumbered by technical complexities.
In conclusion, Mantine UI has emerged as a reliable companion in my development journey, consistently delivering on its promise of simplicity and functionality. It stands as a testament to the power of well-designed tools in enhancing the development experience and shaping the future of web development.
In the course of time, I have crafted a collection of personal components including Mantine Flip, Mantine Reflection, Mantine Rings Progress, and Mantine Split Pane. These components represent my journey in coding and design, each serving a unique purpose in enhancing user interfaces.
Recently, I made the decision to consolidate them into a single cohesive entity—a website housed on Vercel. Have a look at the Matine extensions website!
]]>From a framework perspective, we decided to remove the Illuminate Eloquent ORM from the composer. In short, it won’t be installed by default anymore.
Anyway, you will be able to continue to use that out of the box. This means that WP Bones will continue to support the bootstrap of the Illuminate as the previous version.
We have also changed the boilerplate a bit in order to keep the code clean as much as possible.
Below, you’ll find all changes along with how to upgrade from a previous version.
You will find a couple of new In the master/boilerplate. We have improved the following files:
The new index.php file is cleaner than the previous one
<?php
/**
* Plugin Name: WP Kirk
* Plugin URI: http://undolog.com
* Description: WordPress plugin demo bases on WP Bones framework
* Version: 1.0.0
* Author: Giovambattista Fazioli
* Author URI: http://undolog.com
* Text Domain: wp-kirk
* Domain Path: localization
*
*/
if (!defined('ABSPATH')) {
exit;
}
/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader for
| our application. We just need to utilize it! We'll simply require it
| into the script here so that we don't have to worry about manual
| loading any of our classes later on. It feels nice to relax.
|
*/
require_once __DIR__ . '/bootstrap/autoload.php';
As you can see, now the only required line is the require_once __DIR__ . '/bootstrap/autoload.php';
In addition to that, now you will be able to get the Plugin instance by using a new static class. The most important changes are in the bootstrap/autoload.php
file
<?php
if (! defined('ABSPATH')) {
exit;
}
/*
|--------------------------------------------------------------------------
| Register The Composer Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader
| for our application. We just need to utilize it! We'll require it
| into the script here so that we do not have to worry about the
| loading of any our classes "manually". Feels great to relax.
|
*/
require_once __DIR__ . '/../vendor/autoload.php';
/*
|--------------------------------------------------------------------------
| Plugin Static class
|--------------------------------------------------------------------------
|
| We will use this static class to keep global the plugin information
|
*/
final class WPKirk
{
public const TEXTDOMAIN = 'wp-kirk';
public static $plugin;
public static $start;
}
WPKirk::$plugin = require_once __DIR__ . '/plugin.php';
WPKirk::$start = microtime(true);
// Commodity function to get the plugin instance
if (! function_exists('WPKirk')) {
/**
* Return the instance of plugin.
*
* @return Plugin
*/
function WPKirk()
{
return WPKirk::$plugin;
}
}
As you can see above, you’ll be able to use WPKirk
static class to get the Plugin instance as well as the Plugin text-domain. Anyway, we left the ability to use the global function WPKirk()
as a commodity as well as backward compatibility. In short
$instance = WPKirk::$plugin; // get the plugin instance
$instance = WPKirk(); // get the plugin instance
Remember that
WPkirk
will be your Plugin Namespace, for exampleWPMyPlugin
We have fixed, improved and added new features in the bones
console command
First of all, we added the currently Namespace information along with a couple of new amazing commands: version, API and eloquent model.
By using the version
command, you may handle the Plugin version before releasing it.
php bones version --help
readme.txt > 1.0.0 (Stable tag: 1.0.0)
index.php > 1.0.0 ( * Version: 1.0.0)
Usage:
version [plugin version]
Arguments:
[plugin version] The version of plugin. Examples: '1', '2.0', 'v1', 'v1.2', 'v1-beta.4', 'v1.3+007'
[--major] Increment the major.y.z of plugin.
[--minor] Increment the x.minor.z of plugin.
[--patch] Increment the x.y.patch of plugin.
You may use the Semantic Version SemVer standard to create patches, minor revisions, release candidate versions, and so on.
We started to implement a new way to use the WordPress API. You will find all info here.
The goal was to be able to create a Rest API in minutes. You may use the folder filesystem to organise your vendor, version and route. That’s an amazing way to manage the WordPress API.
For example, to create a simple API you have to create just a file
/api/vendor/v1/route.php
use WPKirk\WPBones\Routing\API\Route;
Route::get('/example', function () {
return 'Hello World!';
});
That’s all. Of course, you may use the php bones api:make
command to create a Rest API Controller.
We have also improved the Custom Page management. Now, you may use the new filesystem method by creating a simple file into the pages folder. For example, you may create a custom_page.php
file in the pages
folder
<?php
use WPKirk\WPBones\Routing\Pages\Support\Page;
class CustomPage extends Page
{
public function title()
{
return "Hello, Custom Page!";
}
public function render()
{
return $this->plugin->view('dashboard.custom_page');
}
}
And use the same method $plugin->getPageUrl()
to get page link.
Another important feature of this version is the ability to use a light version of DB
and Model
classes available in Laravel. If you can’t use the Illuminate ORM package, you may use the Bones Query Builder. That’s very similar to the Laravel ORM with some limitations. Anyway, you will be able to get any record from the database with a simple line of code:
use WPKirk\WPBones\Database\DB;
$users = DB::table('users')->get();
foreach ($users as $user) {
echo $user->name;
}
Of course, you may use the Model pattern
<?php
namespace WPKirk\Http\Controllers;
use WPKirk\WPBones\Database\Model;
class Users extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'users';
}
That’s all.
Below, some useful links
]]>// styled.ts
export const IconDisabled = styled(Icon).attrs({
src: "/images/ssl/unsecure.png",
})``;
]]>Sadly, WordPress architecture doesn’t currently support a complete composer/vendor philosophy yet. This is why some amazing features of composer/vendor architecture can’t apply yet.
Anyway, the aim of this library is to use both new and standard development tools in a WordPress environment. If you like Composer, npm, Laravel and Gulp, here is the framework for you.
If you know Laravel Framework, you will love WP Bones Framework too. I inspired to Laravel while developing WP Bones. Even if, as you can image, the WordPress environment doesn’t support Composer as we wished. So, you will find a lot of things similar to Laravel and some others very different.
First of all, I advise reading the documentation and then going to install WP Kirk Demo plugin where you can see all WP Bones features.
WP Bones makes it easy to write a WordPress plugin. Below, some of the impressive features of WP Bones.
php bones
command like artisan
in LaravelAs with Laravel, you can also extend WP Bones framework with official packages. Of course, you may wish to write your own.
You may already use WP Bones framework under the hood of some plugins.
The WP Bones source code is managed on Github. There you’ll find all repositories and the official packages. You may propose new features or improvements by using the Github issues. Also, you can use the WP Bones Slack team to chat with me or with the community.
That’s all for me. Enjoy and let me know your feedback.
]]>php artisan
command has the --ansi
option to force the ANSI colour output. Anyway, if you have developed your artisan command, you may wish to display its output in ANSI colour mode, you can force it by using:
$this->getOutput()->setDecorated(true);
Of course, you may put the above code in your construct method.
]]>Let’s see a typical config file:
<?php
return [
'myKey" => 'myvalue",
'myOtherKey" => env('MYVALUE_FROM_ENV', 'default')
];
Usually, we can use both static and dynamic values for our keys. Regarding dynamic values, you know that we can use only the environment values because any database access is denied in this context.
So, I use the following workaround very easy to implement. First of all, I add a new key in my configuration file, for example, “config_controller”.
<?php
return [
'config_controller' => '',
'myKey" => 'myvalue",
'myKey" => 'myvalue",
'myOtherKey" => env('MYVALUE_FROM_ENV', 'default');
];
This new key will be a class which we can use to get either all or any. In the “register” method of my service provider, I’ll check this new key. If it exists, then I will use that controller to change my configuration.
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
App::bind('namespace.facade',
function () {
$config = config('myconfig');
if ( ! $config ) {
throw new \RunTimeException('MyService configuration not found. Please run `php artisan vendor:publish`');
}
if (!empty($config['config_controller'])) {
$callable = $config['config_controller'];
if (str_contains( $callable, '@')) {
$callable = explode('@', $callable);
}
else {
$callable = [$callable, 'getConfig'];
}
if (is_callable($callable)) {
$config = call_user_func_array( $callable, [ $config ] );
}
else {
$implode = implode( ",", $callable );
throw new \RunTimeException( "MyService configuration {$implode} is not callable" );
}
}
return new MyClass( $config );
}
);
}
In the configuration file you can use:
<?php
return [
'config_controller' => App\Configuration\MyConfig::class,
'myKey" => 'myvalue",
'myOtherKey" => env( 'MYVALUE_FROM_ENV', 'default' );
];
or
<?php
return [
'config_controller' => 'App\Configurations\MyConfig@myCustomMethod',
'myKey" => 'myvalue",
'myOtherKey" => env( 'MYVALUE_FROM_ENV', 'default' );
];
If the method name is not specified then getConfig
will be used.
Let’s see a typical controller used to modify the configuration:
<?php
namespace App\Configurations;
use App\Models\MyModel;
class MyConfig
{
public static function getConfig( $config )
{
// for example, noew we can get the value from a Eloquent database model
$config['myKey'] = MyModel::where('key', 'myKey')->first()->value();
return $config;
}
}
In the above code, we have modified only one key. Of course, you can change the whole configuration file.
]]>https://code.jquery.com/jquery-2.2.4.min.js
, Laravel Mix will emit an error when compiling your scripts. First of all, you have to copy on the root of your project a fresh copy of default `webpack.config.js` (see here for more details). Next, comment the following lines:
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.ProvidePlugin(Mix.autoload || {
//jQuery: 'jquery',
//$: 'jquery',
//jquery: 'jquery',
//'window.jQuery': 'jquery'
}),
...
]]>To achieve that, you can add the following code in your functions.php
file:
<?php
add_shortcode( 'wp_is_category_cpt', 'wp_is_category_cpt' );
if ( ! function_exists( 'wp_is_category_cpt' ) ) {
function wp_is_category_cpt( $atts = [], $content = null )
{
global $post;
$defaults = [
'post_type' => false,
'taxonomy' => false,
'category' => false,
];
$atts = shortcode_atts( $defaults, $atts, 'wp_is_category_cpt' );
if ( empty( $atts[ 'post_type' ] ) || empty( $atts[ 'taxonomy' ] ) || empty( $atts[ 'category' ] ) ) {
return $content;
}
if ( $post->post_type === $atts[ 'post_type' ] && has_term( $atts[ 'category' ], $atts[ 'taxonomy' ] ) ) {
return $content;
}
return "";
}
}
Next, in your post content you can use:
[wp_is_category_cpt post_type="wp_cpt" taxonomy="wp_tax" category="cars"]
This content will be visible when this post is displayed
by "wp_cpt" custom post type, in the category "cars" for taxonomy "wp_tax"
[/wp_is_category_cpt]
The wp_cpt
and wp_tax
are the Custom Post Type slug id and Custom Post Taxonomy slug id. The category
argument is the category slug.
<?php
class Options implements ArrayAccess {
private $items = [
'item-1' => 'value 1',
'item-2' => [
'sub-item-2' => 'value 2'
]
];
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->items[] = $value;
} else {
$this->items[$offset] = $value;
}
}
public function offsetExists($offset)
{
return isset($this->items[$offset]);
}
public function offsetUnset($offset)
{
unset($this->items[$offset]);
}
public function offsetGet($offset)
{
return isset($this->items[$offset]) ? $this->items[$offset] : null;
}
public function __get( $name )
{
$name = str_replace('_', '-', $name );
if( isset( $this->items[$name] ) ) {
return $this->items[$name];
}
}
}
How does it work? In the example above, I’ve already loaded some items in the internal array. Let’s what we can do:
<?php
// let create the instance
$a = new Options;
// now, we can use this instance like an array
var_dump( $a['item-1'] );
var_dump( $a['item-2']['sub-item-2'] );
// also, we can get the value of internal array by property
var_dump( $a->item_1 );
// we can set the value
$a['item-1'] = "my new value";
var_dump( $a['item-1'] );
Next, we can add the __set()
magic method as well:
...
public function __set( $name, $value )
{
$name = str_replace('_', '-', $name );
$this->offsetSet( $name, $value );
}
and then:
<?php
// we can set the value
$a->item_1 = "by property";
var_dump( $a['item-1'] );
]]>dangerouslySetInnerHTML
attribute. This is very useful when you need to insert a custom own HTML in your page.
…is React’s replacement for using innerHTML in the browser DOM. In general, setting HTML from code is risky because it’s easy to inadvertently expose your users to a cross-site scripting (XSS) attack. So, you can set HTML directly from React, but you have to type out
dangerouslySetInnerHTML
and pass an object with a__html
key, to remind yourself that it’s dangerous.
Alternatively, you could use:
function innerHTML( props )
{
return (<span dangerouslySetInnerHTML={{ __html : props.html }}/> );
}
// and use
const html = 'something';
return (
<div>
<innerHTML html={html} />
</div>
);
]]>