Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
Signed-off-by: Marty Friedel <[email protected]>
  • Loading branch information
martyf committed May 1, 2022
0 parents commit 214e5ab
Show file tree
Hide file tree
Showing 26 changed files with 1,225 additions and 0 deletions.
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
vendor
.DS_Store
.phpunit.result.cache
node_modules
package-lock.json
.php_cs.cache
.idea
.antlers.json
mix-manifest.json
composer.lock
.php-cs-fixer.cache
135 changes: 135 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Iconamic

<!-- statamic:hide -->


![Statamic 3.0+](https://img.shields.io/badge/Statamic-3.0+-FF269E?style=for-the-badge&link=https://statamic.com)
[![Iconamic on Packagist](https://img.shields.io/packagist/v/mitydigital/iconamic?style=for-the-badge)](https://packagist.org/packages/mitydigital/iconamic/stats)

---

<!-- /statamic:hide -->

> Iconamic is an SVG icon picker fieldtype and tag for Statamic 3.
![The Iconamic fieldtype](./images/iconamic-fieldtype.jpg)

## Features

Iconamic allows you to have a folder of SVG icons in your site (or even an Asset container if you want your authors to
be able to upload them too) and provides you with a fieldtype to pick an icon from your list with a neat little preview
of your SVG too.

In your Antlers template, use the Iconamic tag to check if an icon exists (in case you have extra markup to include or
exclude), and inject the SVG contents in to your page markup.

This addon features:

- Iconamic fieldtype for icon selection
- Iconamic tag to inject an SVG icon in to your markup using Antlers (Regex or Runtime)
- Can be used in your Blueprints, including in Bard Sets and even within a Replicator
- Configure a path and path helper for all fieldtypes to use by default
- Override a specific instance to use a different path and/or path helper
- Performs some minor tweaks to your SVG to prevent duplicate IDs being output

## How to Install

Require using Composer:

``` bash
composer require mitydigital/iconamic
```

Publish the config file:

``` bash
php artisan vendor:publish --tag=iconamic-config
```

This will create the `config/statamic/iconamic.php` config file.

### Configuration

There are two config options:

You can set two defaults to customise where your SVG icons live in your project. By default, the config will look
in `resources/icons`. You can set a `path` and a `path_helper`.

1. `path` to provide a default path to your SVG icons from one of Laravel's path helpers, and
2. `path_helper` sets the default path helper to use. You can use one of:
- app_path
- base_path
- public_path
- resource_path
- storage_path

These define the defaults for all fieldtype usages - however you can override these per fieldtype instance if you need.

This means you could have your default pointing to the "resources" directory, but configure a specific fieldtype
instance to use "public" instead.

## How to Use

### Fieldtype

When creating a Blueprint or Bard Set, use the Iconamic fieldtype to create a searchable select box of icons in your
configured path.

Your default configuration will be used, but you can change your path and path helper in the fieldtype config options.

![The Iconamic fieldtype](./images/iconamic-fieldtype-configuration.jpg)

### Tag in Antlers

The Iconamic tag makes it easy to inject an SVG icon in to your markup.

#### Inject an icon

The Iconamic tag will look for a field handle of "icon".

```twig
{{ iconamic }}
```

If an icon cannot be found, Iconamic will fail silently: the last thing we want is for your site to unexpectedly have an
exception thrown.

You can also pass a `handle` parameter to specify a specific field to use:

```twig
{{ iconamic handle="my_iconamic_icon" }}
```

If typing 'handle' is too much, you can also do this:

```twig
{{ iconamic:my_iconamic_icon }}
```

These are looking for the icon name from a field with the handle 'my_iconamic_icon'.

#### Check if an icon exists

Iconamic comes with a handy `has` helper that returns a boolean response. This is really useful if you want to check if
an icon exists before outputting any markup, or want to hard-code a default icon (in the event of an optional field, or
missing icon) in your own antlers file.

```twig
<!-- Check if the icon exists -->
{{ if {iconamic:has} }}
<!-- Output a wrapper -->
<div class="w-8 h-8">
<!-- Inject the icon -->
{{ iconamic }}
</div>
{{ /if }}
```

You can also use the `handle` parameter to look for a field other than 'handle':

```twig
<!-- Check if the "my_iconamic_icon" exists -->
{{ if {iconamic:has handle="my_iconamic_icon"} }}
...
{{ /if }}
```
43 changes: 43 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "mitydigital/iconamic",
"license": "MIT",
"type": "statamic-addon",
"autoload": {
"psr-4": {
"MityDigital\\Iconamic\\": "src"
}
},
"extra": {
"statamic": {
"name": "Iconamic",
"description": "The SVG Icon Selector for Statamic 3"
},
"laravel": {
"providers": [
"MityDigital\\Iconamic\\ServiceProvider"
]
}
},
"require": {
"statamic/cms": "~3.3"
},
"autoload-dev": {
"psr-4": {
"MityDigital\\Iconamic\\Tests\\": "tests/"
}
},
"require-dev": {
"orchestra/testbench": "^6.9|^7.1",
"phpunit/phpunit": "^9.5"
},
"scripts": {
"test": [
"./vendor/bin/phpunit"
]
},
"config": {
"allow-plugins": {
"pixelfear/composer-dist-plugin": true
}
}
}
40 changes: 40 additions & 0 deletions config/iconamic.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

return [

/*
|--------------------------------------------------------------------------
| Default Path
|--------------------------------------------------------------------------
|
| This is your default path to your collection of icons.
|
| You can override this per field usage.
|
*/

'path' => 'icons',


/*
|--------------------------------------------------------------------------
| Path Helper
|--------------------------------------------------------------------------
|
| This sets up the Laravel path helper to use when resolving and icon
| location.
|
| You can use any of these path helpers:
| app_path
| base_path
| public_path
| resource_path
| storage_path
|
| You can override this per field usage.
|
*/

'path_helper' => 'resource_path'

];
1 change: 1 addition & 0 deletions dist/js/iconamic.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added images/iconamic-fieldtype-configuration.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/iconamic-fieldtype.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"private": true,
"scripts": {
"dev": "mix",
"development": "mix",
"watch": "mix watch",
"watch-poll": "mix watch -- --watch-options-poll=1000",
"hot": "mix watch --hot",
"prod": "npm run production",
"production": "mix --production"
},
"dependencies": {
"laravel-mix": "^6.0.43"
},
"devDependencies": {
"vue-loader": "^15.9.8"
}
}
34 changes: 34 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Fieldtypes">
<directory suffix="Test.php">tests/Fieldtypes/</directory>
</testsuite>
<testsuite name="Support">
<directory suffix="Test.php">tests/Support/</directory>
</testsuite>
<testsuite name="Tags">
<directory suffix="Test.php">tests/Tags/</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
</include>
</coverage>
<php>
<env name="APP_ENV" value="testing"/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
<env name="MAIL_MAILER" value="array"/>
<env name="QUEUE_CONNECTION" value="sync"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="TELESCOPE_ENABLED" value="false"/>
</php>
</phpunit>
80 changes: 80 additions & 0 deletions resources/js/fieldtypes/iconamic.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<template>

<div class="flex">
<v-select
ref="input"
class="flex-1"
:name="name"
:clearable="config.clearable"
:disabled="config.disabled || isReadOnly"
:options="options"
:placeholder="config.placeholder"
:searchable="true"
:multiple="false"
:close-on-select="true"
:value="this.value"
:create-option="(value) => ({ value, label: value })"
@input="vueSelectUpdated"
@search:focus="$emit('focus')"
@search:blur="$emit('blur')">
<template slot="option" slot-scope="option">
<span class="flex items-center">
<span class="flex-none iconamic-is-svg block w-4 h-4" v-html="option.svg"></span>
<span class="ml-2">{{ option.label }}</span>
</span>
</template>
<template slot="selected-option" slot-scope="option">
<span class="flex items-center">
<span class="flex-none iconamic-is-svg block w-4 h-4" v-html="meta.icons[option.label]"></span>
<span class="ml-2">{{ option.label }}</span>
</span>
</template>
</v-select>
</div>

</template>

<script>
export default {
mixins: [Fieldtype],
computed: {
options() {
let options = [];
for (let svg in this.meta.icons) {
options.push({
value: svg,
label: svg,
svg: this.meta.icons[svg]
});
}
return options;
}
},
methods: {
focus() {
this.$refs.input.focus();
},
vueSelectUpdated(value) {
if (value) {
this.update(value.value)
} else {
this.update(null);
}
}
}
};
</script>
<style>
.iconamic-is-svg svg {
width: 28px;
height: 28px;
object-fit: contain;
}
</style>
5 changes: 5 additions & 0 deletions resources/js/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import IconamicField from './fieldtypes/iconamic.vue';

Statamic.booting(() => {
Statamic.$components.register('iconamic-fieldtype', IconamicField);
});
18 changes: 18 additions & 0 deletions src/Exceptions/IconamicException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace MityDigital\Iconamic\Exceptions;

use Exception;

class IconamicException extends Exception
{
public static function missingPathHelper()
{
return new self("Missing Path Helper - a path helper was not provided.");
}

public static function unknownPathHelper(null|string $pathHelper)
{
return new self("Path Helper \"{$pathHelper}\" could not be translated to a Laravel path helper.");
}
}
Loading

0 comments on commit 214e5ab

Please sign in to comment.