add: bbcode input livewire component

This commit is contained in:
Roardom
2022-06-30 06:25:05 -05:00
parent 866476e4d8
commit 17d83c8a34
7 changed files with 362 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
<?php
/**
* NOTICE OF LICENSE.
*
* UNIT3D Community Edition is open-sourced software licensed under the GNU Affero General Public License v3.0
* The details is bundled with this project in the file LICENSE.txt.
*
* @project UNIT3D Community Edition
*
* @author Raordom <roardom@protonmail.com>
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
*/
namespace App\Http\Livewire;
use App\Helpers\Bbcode;
use Livewire\Component;
class BbcodeInput extends Component
{
public string $label = '';
public string $name = '';
public bool $isPreviewEnabled = false;
public string $contentBbcode = '';
public string $contentHtml = '';
final public function mount($name, $label)
{
$this->name = $name;
$this->label = $label;
}
final public function updatedIsPreviewEnabled(): void
{
if ($this->isPreviewEnabled) {
$this->contentHtml = (new Bbcode())->parse($this->contentBbcode);
}
}
final public function render(): \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Contracts\Foundation\Application
{
return \view('livewire.bbcode-input', [
'contentHtml' => $this->contentHtml,
'label' => $this->label,
]);
}
}
+1
View File
@@ -16,6 +16,7 @@
@import 'main/aboutus';
@import 'chat/chatbox';
@import 'main/tooltips';
@import 'components/bbcode-input';
@import 'components/form/button';
@import 'components/form/checkbox';
@import 'components/form/file';
@@ -0,0 +1,87 @@
.bbcode-input {
border: var(--bbcode-input-border);
border-radius: var(--bbcode-input-border-radius);
background-color: var(--bbcode-input-bg);
display: grid;
grid-template: "tabs buttons toggle" auto "content content content" auto / 1fr auto auto;
max-width: 100%;
}
.bbcode-input__tab-input {
opacity: 0;
position: absolute !important; /* !important is necessary until site-wide radio button styling is removed */
}
.bbcode-input__tab-label {
margin-top: 4px;
padding: 15px 12px 13px 12px;
line-height: 1 !important;
border-top-left-radius: var(--bbcode-input-border-radius);
border-top-right-radius: var(--bbcode-input-border-radius);
color: #555;
margin: 0 !important;
}
.bbcode-input__tab-input:checked + .bbcode-input__tab-label {
border-bottom: 2px solid grey;
color: #888
}
.bbcode-input__tab-pane {
grid-area: content;
padding: 12px;
background: var(--bbcode-input-body-bg);
border-bottom-left-radius: var(--bbcode-input-border-radius);
border-bottom-right-radius: var(--bbcode-input-border-radius);
}
.bbcode-input__tabs {
grid-area: tabs;
border-top-left-radius: var(--bbcode-input-border-radius);
display: flex;
align-items: center;
}
.bbcode-input__icon-bar {
grid-area: buttons;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: flex-end;
padding: 0;
margin: 0;
list-style-type: none;
}
.bbcode-input__icon-bar abbr {
all: revert !important; /* can be removed once site-wide <abbr> styling is removed */
}
.bbcode-input__icon-separator {
all: revert; /* can be removed once site-wide <hr> styles are removed */
margin: 11px 4px;
align-self: stretch;
}
.bbcode-input__icon-bar-toggle {
grid-area: toggle;
border-top-right-radius: var(--bbcode-input-border-radius);
}
.bbcode-input__input {
background: var(--bbcode-input-header-bg);
}
.bbcode-input__preview {
padding: 4px;
}
@media only screen and (max-width: 1200px) {
.bbcode-input {
grid-template: "tabs toggle" auto "buttons buttons" auto "content content" auto / 1fr auto;
}
.bbcode-input__icon-bar {
background-color: var(--bbcode-input-body-bg);
}
}
+4
View File
@@ -1,4 +1,8 @@
:root {
--bbcode-input-header-bg: #e2e2e2;
--bbcode-input-body-bg: white;
--bbcode-input-border: 1px solid #555;
--bbcode-input-border-radius: 5px;
--button-filled-bg: #5cb579 linear-gradient(to bottom right, #0ba360, #2bb673);
--button-filled-border: none;
+5
View File
@@ -1,4 +1,9 @@
:root {
--bbcode-input-header-bg: #222;
--bbcode-input-body-bg: #222;
--bbcode-input-border: 1px solid #555;
--bbcode-input-border-radius: 5px;
--button-filled-bg: #444;
--button-filled-border: none;
--button-filled-border-radius: 9999px;
+5
View File
@@ -20,6 +20,11 @@
--color-bright-white: hsl(0, 0%, 100%);
--color-light-orange: hsl(20, 20%, 50%);
--bbcode-input-header-bg: #272727;
--bbcode-input-body-bg: #272727;
--bbcode-input-border: 1px solid #555;
--bbcode-input-border-radius: 5px;
--button-filled-bg: var(--color-green);
--button-filled-border: none;
--button-filled-border-radius: 9999px;
@@ -0,0 +1,209 @@
<div
class="bbcode-input"
x-data="{
insert(openTag, closeTag) {
input = $refs.bbcode;
start = input.selectionStart;
end = input.selectionEnd;
input.value = input.value.substring(0, start)
+ openTag
+ input.value.substring(start, end)
+ closeTag
+ input.value.substring(end)
input.dispatchEvent(new Event('input'));
input.focus();
if (openTag.charAt(openTag.length - 2) === '=') {
input.setSelectionRange(start + openTag.length - 2, start + openTag.length - 2);
} else {
input.setSelectionRange(start, end + openTag.length + closeTag.length);
}
},
showButtons: false,
}"
>
<p class="bbcode-input__tabs">
<input class="bbcode-input__tab-input" type="radio" id="bbcode-preview-disabled" name="isPreviewEnabled" value="0" wire:model="isPreviewEnabled" />
<label class="bbcode-input__tab-label" for="bbcode-preview-disabled">Write</label>
<input class="bbcode-input__tab-input" type="radio" id="bbcode-preview-enabled" name="isPreviewEnabled" value="1" wire:model="isPreviewEnabled" />
<label class="bbcode-input__tab-label" for="bbcode-preview-enabled">{{ __('common.preview') }}</label>
</p>
<p class="bbcode-input__icon-bar-toggle">
<button type="button" class="form__button form__button--text" x-on:click="showButtons = ! showButtons">BBCode</button>
</p>
<menu class="bbcode-input__icon-bar" x-cloak x-show="showButtons">
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('[b]', '[/b]')">
<abbr title="Bold">
<i class="{{ config('other.font-awesome') }} fa-bold"></i>
</abbr>
</button>
</li>
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('[i]', '[/i]')">
<abbr title="Italics">
<i class="{{ config('other.font-awesome') }} fa-italic"></i>
</abbr>
</button>
</li>
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('[u]', '[/u]')">
<abbr title="Underline">
<i class="{{ config('other.font-awesome') }} fa-underline"></i>
</abbr>
</button>
</li>
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('[s]', '[/s]')">
<abbr title="Strikethrough">
<i class="{{ config('other.font-awesome') }} fa-strikethrough"></i>
</abbr>
</button>
</li>
<hr class="bbcode-input__icon-separator">
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('[img=350]', '[/img]')">
<abbr title="Insert Image">
<i class="{{ config('other.font-awesome') }} fa-image"></i>
</abbr>
</button>
</li>
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('[video=&quot;youtube&quot;]', '[/video]')">
<abbr title="Insert YouTube">
<i class="fab fa-youtube"></i>
</abbr>
</button>
</li>
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('[url]', '[/url]')">
<abbr title="Link">
<i class="{{ config('other.font-awesome') }} fa-link"></i>
</abbr>
</button>
</li>
<hr class="bbcode-input__icon-separator">
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('\n[list]\n[*]', '\n[/list]\n')">
<abbr title="Unordered List">
<i class="{{ config('other.font-awesome') }} fa-list"></i>
</abbr>
</button>
</li>
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('\n[list=1]\n[*]', '\n[/list]\n')">
<abbr title="Ordered List">
<i class="{{ config('other.font-awesome') }} fa-list-ol"></i>
</abbr>
</button>
</li>
<hr class="bbcode-input__icon-separator">
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('[color=]', '[/color]')">
<abbr title="Font Color">
<i class="{{ config('other.font-awesome') }} fa-palette"></i>
</abbr>
</button>
</li>
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('[size=]', '[/size]')">
<abbr title="Font Size">
<i class="{{ config('other.font-awesome') }} fa-text-size"></i>
</abbr>
</button>
</li>
<li>
<button type="button" class="form__button form__button--text" x-on:click="insert('[font=]', '[/font]')">
<abbr title="Font Family">
Font
</abbr>
</button>
</li>
<hr class="bbcode-input__icon-separator">
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('\n[left]\n', '\n[/left]\n')">
<abbr title="Align left">
<i class="{{ config('other.font-awesome') }} fa-align-left"></i>
</abbr>
</button>
</li>
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('\n[center]\n', '\n[/center]\n')">
<abbr title="Align center">
<i class="{{ config('other.font-awesome') }} fa-align-center"></i>
</abbr>
</button>
</li>
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('\n[right]\n', '\n[/right]\n')">
<abbr title="Align right">
<i class="{{ config('other.font-awesome') }} fa-align-right"></i>
</abbr>
</button>
</li>
<hr class="bbcode-input__icon-separator">
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('[quote]', '[/quote]')">
<abbr title="Quote">
<i class="{{ config('other.font-awesome') }} fa-quote-right"></i>
</abbr>
</button>
</li>
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('[code]', '[/code]')">
<abbr title="Code">
<i class="{{ config('other.font-awesome') }} fa-code"></i>
</abbr>
</button>
</li>
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('[spoiler]', '[/spoiler]')">
<abbr title="Spoiler">
<i class="{{ config('other.font-awesome') }} fa-eye-slash"></i>
</abbr>
</button>
</li>
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('[note]', '[/note]')">
<abbr title="Note">
<i class="{{ config('other.font-awesome') }} fa-sticky-note"></i>
</abbr>
</button>
</li>
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('[alert]', '[/alert]')">
<abbr title="Note">
<i class="{{ config('other.font-awesome') }} fa-file-exclamation"></i>
</abbr>
</button>
</li>
<li>
<button type="button" class="form__standard-icon-button" x-on:click="insert('[table]\n[tr]\n[td]', '[/td]\n[/tr]\n[/table]')">
<abbr title="Table">
<i class="{{ config('other.font-awesome') }} fa-table"></i>
</abbr>
</button>
</li>
</menu>
<div class="bbcode-input__tab-pane">
@if ($isPreviewEnabled)
<p class="bbcode-input__preview">
@joypixels($contentHtml)
</p>
@else
<p class="form__group">
<textarea
id="bbcode-{{ $name }}"
name="{{ $name }}"
class="form__textarea bbcode-input__input"
placeholder=""
x-ref="bbcode"
wire:model.defer="contentBbcode"
></textarea>
<label class="form__label form__label--floating" for="{{ $name }}">
{{ $label }}
</label>
</p>
@endif
</div>
</div>