diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 0000000..fc4e90f
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,84 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+#
+# ******** NOTE ********
+# We have attempted to detect the languages in your repository. Please check
+# the `language` matrix defined below to confirm you have the correct set of
+# supported CodeQL languages.
+#
+name: "CodeQL"
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+ schedule:
+ - cron: '21 0 * * 3'
+
+jobs:
+ analyze:
+ name: Analyze
+ # Runner size impacts CodeQL analysis time. To learn more, please see:
+ # - https://gh.io/recommended-hardware-resources-for-running-codeql
+ # - https://gh.io/supported-runners-and-hardware-resources
+ # - https://gh.io/using-larger-runners
+ # Consider using larger runners for possible analysis time improvements.
+ runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
+ timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
+ permissions:
+ # required for all workflows
+ security-events: write
+
+ # only required for workflows in private repositories
+ actions: read
+ contents: read
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'javascript-typescript' ]
+ # CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ]
+ # Use only 'java-kotlin' to analyze code written in Java, Kotlin or both
+ # Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
+ # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v3
+ with:
+ languages: ${{ matrix.language }}
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
+
+ # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
+ # queries: security-extended,security-and-quality
+
+
+ # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
+ # If this step fails, then you should remove it and run the build manually (see below)
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v3
+
+ # ℹ️ Command-line programs to run using the OS shell.
+ # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
+
+ # If the Autobuild fails above, remove it and uncomment the following three lines.
+ # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
+
+ # - run: |
+ # echo "Run, Build Application using script"
+ # ./location_of_script_within_repo/buildscript.sh
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v3
+ with:
+ category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml
index ca2197d..2cb1d5e 100644
--- a/.github/workflows/dependabot-auto-merge.yml
+++ b/.github/workflows/dependabot-auto-merge.yml
@@ -13,7 +13,7 @@ jobs:
- name: Dependabot metadata
id: metadata
- uses: dependabot/fetch-metadata@v1.6.0
+ uses: dependabot/fetch-metadata@v2.3.0
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/.github/workflows/fix-php-code-style-issues.yml b/.github/workflows/fix-php-code-style-issues.yml
index 7520a18..87459d5 100644
--- a/.github/workflows/fix-php-code-style-issues.yml
+++ b/.github/workflows/fix-php-code-style-issues.yml
@@ -14,14 +14,15 @@ jobs:
steps:
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
- name: Fix PHP code style issues
- uses: aglipanci/laravel-pint-action@2.3.0
+ uses: aglipanci/laravel-pint-action@2.5
- name: Commit changes
- uses: stefanzweifel/git-auto-commit-action@v4
+ uses: stefanzweifel/git-auto-commit-action@v5
with:
+ token: ${{secrets.GITHUB_TOKEN}}
commit_message: Fix styling
diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml
index 9d41c0c..3855a08 100644
--- a/.github/workflows/phpstan.yml
+++ b/.github/workflows/phpstan.yml
@@ -11,7 +11,7 @@ jobs:
name: phpstan
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
@@ -20,7 +20,7 @@ jobs:
coverage: none
- name: Install composer dependencies
- uses: ramsey/composer-install@v2
+ uses: ramsey/composer-install@v3
- name: Run PHPStan
run: ./vendor/bin/phpstan --error-format=github
diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml
index d473710..f13d0e2 100644
--- a/.github/workflows/run-tests.yml
+++ b/.github/workflows/run-tests.yml
@@ -25,7 +25,7 @@ jobs:
steps:
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml
index 8c12ba9..ec40921 100644
--- a/.github/workflows/update-changelog.yml
+++ b/.github/workflows/update-changelog.yml
@@ -13,7 +13,7 @@ jobs:
steps:
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
ref: main
@@ -24,7 +24,7 @@ jobs:
release-notes: ${{ github.event.release.body }}
- name: Commit updated CHANGELOG
- uses: stefanzweifel/git-auto-commit-action@v4
+ uses: stefanzweifel/git-auto-commit-action@v5
with:
branch: main
commit_message: Update CHANGELOG
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8ff584b..0076bff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
All notable changes to `lazy-ui` will be documented in this file.
-## 1.0.0 -
-- Initial release
+## v1.1.0 - 2025-03-10
+
+**Full Changelog**: https://github.com/step2dev/lazy-ui/compare/v1.0.0...v1.0.0
+## 1.0.0 -
+
+- Initial release
diff --git a/README.md b/README.md
index 23a45bb..513302c 100644
--- a/README.md
+++ b/README.md
@@ -88,7 +88,7 @@ composer test
- [ ] Select
- [ ] Multi select
- [x] Textarea
- - [ ] Toggle
+ - [x] Toggle
- Layout
- [ ] Artboard
diff --git a/composer.json b/composer.json
index adda41d..6ada533 100644
--- a/composer.json
+++ b/composer.json
@@ -26,7 +26,7 @@
],
"require": {
"php": "^8.1",
- "illuminate/contracts": "^v10.17.1",
+ "illuminate/contracts": "^v10.17.1|^v11.0|^12.0",
"livewire/livewire": "^3.0",
"spatie/laravel-package-tools": "^1.14.0"
},
diff --git a/package.json b/package.json
index d4f3dca..39df0b0 100644
--- a/package.json
+++ b/package.json
@@ -13,12 +13,15 @@
"tailwind"
],
"dependencies": {
- "alpinejs": "^3.13.0",
+ "@tailwindcss/forms": "^0.5.6",
+ "alpinejs": "^3.13.1",
+ "axios": "^1.6.0",
+ "quill": "^1.3.7",
"theme-change": "^2.5.0"
},
"devDependencies": {
- "daisyui": "^3.6.3",
- "sanitize-html": "^2.11.0",
+ "daisyui": "^3.9.2",
+ "sanitize-html": "^2.12.1",
"tailwindcss": "^3.3.3"
}
}
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index e69de29..6107e64 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -0,0 +1,6 @@
+parameters:
+ ignoreErrors:
+ -
+ message: "#^Call to an undefined method Step2dev\\\\LazyUI\\\\LazyUiServiceProvider\\:\\:dispatch\\(\\)\\.$#"
+ count: 1
+ path: src/LazyUiServiceProvider.php
diff --git a/resources/js/components/logout.js b/resources/js/components/logout.js
new file mode 100644
index 0000000..82e02bc
--- /dev/null
+++ b/resources/js/components/logout.js
@@ -0,0 +1,7 @@
+let logout = document.querySelector('.logout')
+if (logout) {
+ logout.addEventListener('click', (event) => {
+ event.preventDefault()
+ document.getElementById('logout-form').submit()
+ })
+}
diff --git a/resources/js/components/quill.js b/resources/js/components/quill.js
new file mode 100644
index 0000000..01b7655
--- /dev/null
+++ b/resources/js/components/quill.js
@@ -0,0 +1,88 @@
+import Quill from "quill";
+
+window.Quill = Quill;
+document.addEventListener('alpine:init', () => {
+ Alpine.data('quill', ({__value, options, __config, onTextChange, onInit}) => {
+ return {
+ __ready: false,
+ __value,
+ __quill: undefined,
+
+ init() {
+ if (typeof window.Quill !== 'function') {
+ throw new Error(`quill requires Quill to be loaded. See https://quilljs.com/docs/`);
+ }
+
+ queueMicrotask(() => {
+ this.__ready = true;
+
+ this.__quill = new window.Quill(this.$refs.quill, this.__quillOptions());
+
+ this.__quill.root.innerHTML = this.__value;
+
+ this.__quill.on('text-change', () => {
+ if (typeof onTextChange === 'function') {
+ const result = onTextChange(this);
+
+ if (result === false) {
+ return;
+ }
+ }
+
+ this.__value = this.__quill.root.innerHTML;
+
+ this.$dispatch('input', this.__value);
+ });
+
+ if (options.autofocus) {
+ this.$nextTick(() => {
+ this.focus();
+ });
+ }
+
+ if (typeof onInit === 'function') {
+ onInit(this);
+ }
+ });
+ },
+
+ focus() {
+ if (!this.__ready) {
+ return;
+ }
+
+ this.__quill.focus();
+ },
+
+ __quillOptions() {
+ let config = __config(this, options);
+ let toolbarHandlers = {};
+ let modules = {};
+
+ if (config.hasOwnProperty('toolbarHandlers')) {
+ toolbarHandlers = config.toolbarHandlers;
+ delete config.toolbarHandlers;
+ }
+
+ if (config.hasOwnProperty('modules')) {
+ modules = config.modules;
+ delete config.modules;
+ }
+
+ return {
+ theme: options.theme,
+ readOnly: options.readOnly,
+ placeholder: options.placeholder,
+ modules: {
+ toolbar: {
+ container: options.toolbar,
+ handlers: toolbarHandlers,
+ },
+ ...modules,
+ },
+ ...config,
+ };
+ },
+ };
+ });
+})
diff --git a/resources/js/components/toast/index.js b/resources/js/components/toast/index.js
new file mode 100644
index 0000000..392ef86
--- /dev/null
+++ b/resources/js/components/toast/index.js
@@ -0,0 +1,121 @@
+import {Timer} from "./timer";
+import sanitizeHtml from 'sanitize-html';
+document.addEventListener('alpine:init', () => {
+ window.Alpine.store('toasts', {
+ counter: 0, list: [], createToast(message, type = 'success', options = {}) {
+ options = options || {}
+
+ let props = {
+ ...{
+ timeout: 5000, render: false, close: '', title: '', icon: ''
+ }, ...options
+ }
+
+ let title = props.title
+ message = sanitizeHtml(message, {
+ allowedTags: ["div", "figcaption", "figure", "hr", "li", "ol", "p", "img", "ul", "a", "b", "br", "small", "span", "strong", "sub", "sup", "caption",],
+ disallowedTagsMode: 'discard',
+ allowedAttributes: {
+ div: ['style', 'class'],
+ span: ['style', 'class'],
+ ul: ['style', 'class'],
+ li: ['style', 'class'],
+ a: ['href', 'name', 'target', 'style', 'class'], // We don't currently allow img itself by default, but these attributes would make sense if we did.
+ img: ['src', 'srcset', 'alt', 'title', 'width', 'height', 'loading', 'style', 'class']
+ }, // Lots of these won't come up by default because we don't allow them
+ selfClosing: ['img', 'br', 'hr', 'area', 'base', 'basefont', 'input', 'link'], // URL schemes we permit
+ allowedSchemes: ['http', 'https', 'mailto', 'tel'],
+ allowedSchemesByTag: {},
+ allowedSchemesAppliedToAttributes: ['href', 'src'],
+ allowProtocolRelative: true,
+ enforceHtmlBoundary: false
+ })
+
+ let id = this.counter++
+ let _this = this;
+
+ if (props.close) {
+ _this.destroyToast(props.close)
+ }
+
+
+ this.list.unshift({
+ id: props.id || id,
+ duration: Math.floor(props.timeout / 1000),
+ title,
+ message,
+ type,
+ visible: true,
+ render: Number(props.render),
+ timer: new Timer(function () {
+ if (props.timeout) {
+ _this.destroyToast(id)
+ }
+ }, props.timeout)
+ })
+ }, destroyToast(toastId) {
+ const index = this.list.findIndex((obj) => obj.id === toastId);
+
+ if (index > -1) {
+ if (this.list[index]) {
+ this.list[index].visible = false
+ setTimeout(() => {
+ this.list.splice(index, 1);
+ }, 1000)
+ }
+ }
+ }
+ })
+
+ class Toast {
+ constructor() {
+ this.toast = Alpine.store('toasts')
+ }
+
+ success(message, options = {}) {
+ return this.toast.createToast(message, 'success', options)
+ }
+
+ error(message, options = {}) {
+ return this.toast.createToast(message, 'error', options)
+ }
+
+ info(message, options = {}) {
+ return this.toast.createToast(message, 'info', options)
+ }
+
+ warning(message, options = {}) {
+ return this.toast.createToast(message, 'warning', options)
+ }
+
+ notification(message, type = 'success', options = {}) {
+ return this[type](message, options)
+ }
+ }
+
+ window.toast = new Toast()
+ document.addEventListener('notify', async (event) => {
+ let detail = event.detail
+ if (Array.isArray(detail)) {
+ detail = detail.shift()
+ }
+
+ const {title = null, message, type = 'success'} = detail
+
+ toast.notification(message, type, {
+ title: title
+ })
+ })
+
+ window.addEventListener("offline", (event) => {
+ window.toast.warning('You are offline', {
+ title: 'Internet connection', id: 'offline', timeout: 10000,
+ })
+ });
+
+ window.addEventListener("online", (event) => {
+ window.toast.success('You are online', {
+ title: 'Internet connection', id: 'online', timeout: 10000,
+ })
+ });
+})
diff --git a/resources/js/components/toast/timer.js b/resources/js/components/toast/timer.js
new file mode 100644
index 0000000..3914e6e
--- /dev/null
+++ b/resources/js/components/toast/timer.js
@@ -0,0 +1,16 @@
+export function Timer(callback, delay) {
+ let timerId, start, remaining = delay;
+
+ this.pause = function () {
+ window.clearTimeout(timerId);
+ remaining -= new Date() - start;
+ };
+
+ this.resume = function () {
+ start = new Date();
+ window.clearTimeout(timerId);
+ timerId = window.setTimeout(callback, remaining);
+ };
+
+ this.resume();
+}
diff --git a/resources/js/lazy.js b/resources/js/lazy.js
new file mode 100644
index 0000000..1874367
--- /dev/null
+++ b/resources/js/lazy.js
@@ -0,0 +1,4 @@
+import './components/themeswitcher'
+import './components/logout'
+import './components/toast'
+import './components/quill'
diff --git a/resources/css/components/toast.scss b/resources/scss/components/toast.scss
similarity index 100%
rename from resources/css/components/toast.scss
rename to resources/scss/components/toast.scss
diff --git a/resources/css/lazy.scss b/resources/scss/lazy.scss
similarity index 57%
rename from resources/css/lazy.scss
rename to resources/scss/lazy.scss
index 6378004..d39ab6b 100644
--- a/resources/css/lazy.scss
+++ b/resources/scss/lazy.scss
@@ -1,2 +1,3 @@
@import "tailwind";
+@import "quill/dist/quill.snow.css";
@import "./components/toast";
diff --git a/resources/css/tailwind.scss b/resources/scss/tailwind.scss
similarity index 100%
rename from resources/css/tailwind.scss
rename to resources/scss/tailwind.scss
diff --git a/resources/views/btn/delete.blade.php b/resources/views/btn/delete.blade.php
index a80cfeb..52055a5 100644
--- a/resources/views/btn/delete.blade.php
+++ b/resources/views/btn/delete.blade.php
@@ -1,5 +1,5 @@
@props([
- 'href' => '',
+ 'href' => '#',
])
@aware([
@@ -9,9 +9,8 @@
@@ -58,19 +57,9 @@ class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-
+ href="{{ $href }}"
+ outline error sm :label="__('lazy-ui::buttons.delete')" sm class="mr-2">
- {{-- --}}
- {{-- --}}
-
diff --git a/resources/views/choices.blade.php b/resources/views/choices.blade.php
new file mode 100644
index 0000000..4f4f6a1
--- /dev/null
+++ b/resources/views/choices.blade.php
@@ -0,0 +1,57 @@
+@props([
+ 'options' => null,
+ 'label' => '',
+ 'placeholder' => 'Please select a value',
+// 'value'=> null
+])
+@php
+ $model = $attributes->wire('model');
+ $lazy = $model->hasModifier('lazy');
+ $parameter = $model->value();
+
+@endphp
+{{--@dd($attributes,$model, $lazy, $parameter)--}}
+
+
diff --git a/resources/views/form-group.blade.php b/resources/views/form-group.blade.php
new file mode 100644
index 0000000..05c16dc
--- /dev/null
+++ b/resources/views/form-group.blade.php
@@ -0,0 +1,32 @@
+@props([
+ 'label' => '',
+ 'help' => '',
+ 'hr' => false
+])
+@php
+ $required = $attributes['required'] ?? null;
+ if ($label) {
+ $label .= ($required ? '*' : '');
+ }
+ $model = $attributes->wire('model');
+ $parameter = $model->value();
+ $class = [];
+@endphp
+
+
diff --git a/resources/views/form/image.blade.php b/resources/views/form/image.blade.php
new file mode 100644
index 0000000..5aca943
--- /dev/null
+++ b/resources/views/form/image.blade.php
@@ -0,0 +1,45 @@
+@props([
+ 'label' => '',
+ 'placeholder' => '',
+ 'help' => '',
+ 'hr' => '',
+ 'outerClass' => '',
+ 'icon' => '',
+ 'rightIcon' => '',
+ 'src' => '',
+ 'type' => 'file',
+])
+
+@php
+ $required = $attributes['required'] ?? false;
+ $placeholder = $placeholder ?: $label;
+ $parameter = $attributes->wire('model')->value();
+ $hasError = $errors->has($parameter);
+@endphp
+
+
diff --git a/resources/views/form/input.blade.php b/resources/views/form/input.blade.php
index 1429635..bc2d725 100644
--- a/resources/views/form/input.blade.php
+++ b/resources/views/form/input.blade.php
@@ -17,7 +17,6 @@
- {{-- merge(['class' => 'input w-full'.($hasError ? ' text-error' : ''), 'type' => 'text', 'placeholder' => $placeholder ]) }} />--}}
{{ $slot }}
@if($rightIcon)
@@ -39,4 +38,3 @@ class="stroke-info h-6 w-6 flex-shrink-0">
@enderror
@endif
-
diff --git a/resources/views/form/richtext.blade.php b/resources/views/form/richtext.blade.php
new file mode 100644
index 0000000..3f77b4e
--- /dev/null
+++ b/resources/views/form/richtext.blade.php
@@ -0,0 +1,42 @@
+@props([
+ 'label' => '',
+ 'placeholder' => '',
+ 'help' => '',
+ 'hr' => '',
+ 'outerClass' => '',
+ 'icon' => '',
+ 'rightIcon' => ''
+])
+
+@php
+ $required = $attributes['required'] ?? false;
+ $placeholder = $placeholder ?: $label;
+ $parameter = $attributes->wire('model')->value();
+ $hasError = $errors->has($parameter);
+@endphp
+
+
diff --git a/resources/views/form/select.blade.php b/resources/views/form/select.blade.php
new file mode 100644
index 0000000..2f52534
--- /dev/null
+++ b/resources/views/form/select.blade.php
@@ -0,0 +1,47 @@
+@props([
+ 'label' => '',
+ 'placeholder' => '',
+ 'help' => '',
+ 'hr' => '',
+ 'outerClass' => '',
+ 'icon' => '',
+ 'rightIcon' => ''
+])
+
+@php
+ $required = $attributes['required'] ?? false;
+ $placeholder = $placeholder ?: $label;
+ $parameter = $attributes->wire('model')->value();
+ $hasError = $errors->has($parameter);
+@endphp
+
diff --git a/resources/views/form/textarea.blade.php b/resources/views/form/textarea.blade.php
new file mode 100644
index 0000000..cf6b3b3
--- /dev/null
+++ b/resources/views/form/textarea.blade.php
@@ -0,0 +1,42 @@
+@props([
+ 'label' => '',
+ 'placeholder' => '',
+ 'help' => '',
+ 'hr' => '',
+ 'outerClass' => '',
+ 'icon' => '',
+ 'rightIcon' => ''
+])
+
+@php
+ $required = $attributes['required'] ?? false;
+ $placeholder = $placeholder ?: $label;
+ $parameter = $attributes->wire('model')->value();
+ $hasError = $errors->has($parameter);
+@endphp
+
+
diff --git a/resources/views/form/toggle.blade.php b/resources/views/form/toggle.blade.php
index 1dbb73f..ab6ed5d 100644
--- a/resources/views/form/toggle.blade.php
+++ b/resources/views/form/toggle.blade.php
@@ -1,12 +1,12 @@
-{{--@props([
+@props([
'label' => '',
'help' => '',
'hr' => ''
-])--}}
+])
-
-{{--@php
+
+@php
$required = $attributes['required'] ?? null;
if ($label) {
$label .= ($required ? '
*' : '');
@@ -20,7 +20,7 @@
--}}
+
diff --git a/resources/views/menu.blade.php b/resources/views/menu.blade.php
new file mode 100644
index 0000000..fd39179
--- /dev/null
+++ b/resources/views/menu.blade.php
@@ -0,0 +1,82 @@
+@props([
+ 'route' => '',
+ 'href' => '#',
+ 'icon' => '',
+ 'label' => '',
+ 'title' => '',
+ 'show' => true,
+ 'count' => 0,
+ 'inlineIcon' => '',
+ 'indicator' => '',
+ 'toggle' => false,
+])
+
+@php
+ if (! $show) {
+ return ;
+ }
+
+ $routePath = $route ? route($route, [], false) : $href;
+
+ $path = trim($routePath !== '/admin' ? $routePath.'*' : $routePath, '/');
+
+ $count = (int) $count > 99 ? '99+' : $count
+@endphp
+@if ($title)
+
+@endif
+
+
+ class([
+ 'active' => request()->is($path),
+ ]) }}
+ @if ($toggle)
+ @click="open = ! open"
+ @endif
+ >
+
+ @if ($inlineIcon || $icon)
+ @if ($inlineIcon)
+
+ @else
+
+ {!! $icon !!}
+
+ @endif
+ @endif
+
+ {{ $label }}
+ @if ($indicator)
+ {{ $indicator }}
+ @endif
+ @if ($count)
+ {{ $count }}
+ @endif
+ @if ($toggle)
+
+ @endif
+
+ @if ($slot->isNotEmpty())
+
+ @endif
+
diff --git a/resources/views/rich-text/quill.blade.php b/resources/views/rich-text/quill.blade.php
deleted file mode 100644
index c70e6ee..0000000
--- a/resources/views/rich-text/quill.blade.php
+++ /dev/null
@@ -1,49 +0,0 @@
-class($containerClass()) }}
-
- @if ($hasXModel())
- x-modelable="__value"
- {{ $attributes->whereStartsWith('x-model') }}
- @endif
->
- @if ($name)
-
- @endif
-
-
-
diff --git a/resources/views/richtext.blade.php b/resources/views/richtext.blade.php
new file mode 100644
index 0000000..b41718c
--- /dev/null
+++ b/resources/views/richtext.blade.php
@@ -0,0 +1,20 @@
+@props([
+ 'hasError' => false,
+ 'value' => '',
+ 'options' => [],
+ 'quillUniq' => 'quill'
+])
+merge(['class' => $hasError ? ' textarea-error' : '' ]) }}
+ x-data="quill({
+__value: @entangle($attributes->wire('model')),
+options: {{ $options }},
+__config(instance, quillOptions) {
+return { {{ $config ?? '' }} };
+},
+})"
+ x-cloak
+>
+
+
{{ $value ?: $slot }}
+
diff --git a/resources/views/select.blade.php b/resources/views/select.blade.php
new file mode 100644
index 0000000..249b0f2
--- /dev/null
+++ b/resources/views/select.blade.php
@@ -0,0 +1,11 @@
+@props([
+ 'placeholder' => '',
+ 'hasError' => false
+])
+
+
diff --git a/resources/views/tabs.blade.php b/resources/views/tabs.blade.php
index a4fb47b..95e704b 100644
--- a/resources/views/tabs.blade.php
+++ b/resources/views/tabs.blade.php
@@ -1,10 +1,7 @@
@props([
'type' => '',
- 'size' => ''
])
-class([
- 'tabs-boxed' => $type === 'boxed',
-]) }}>
+
{{ $slot }}
diff --git a/resources/views/textarea.blade.php b/resources/views/textarea.blade.php
index 0f00c31..e292332 100644
--- a/resources/views/textarea.blade.php
+++ b/resources/views/textarea.blade.php
@@ -2,4 +2,4 @@
'hasError' => false,
'value' => ''
])
-
+
diff --git a/resources/views/themeswitcher.blade.php b/resources/views/themeswitcher.blade.php
index ef56c4d..136421f 100644
--- a/resources/views/themeswitcher.blade.php
+++ b/resources/views/themeswitcher.blade.php
@@ -6,7 +6,7 @@
],
'themes' => []
])
-
+@persist('theme-switcher')
@switch($themeToggle)
@case ('multiple')
@@ -70,3 +70,4 @@ class="bg-base-100 text-base-content w-full cursor-pointer font-sans">
@break
@default
@endswitch
+@endpersist
diff --git a/resources/views/toggle.blade.php b/resources/views/toggle.blade.php
index f9b326e..37ab712 100644
--- a/resources/views/toggle.blade.php
+++ b/resources/views/toggle.blade.php
@@ -1,44 +1 @@
-@props([
- 'label' => '',
- 'help' => '',
- 'hr' => ''
-])
-@php
- $required = $attributes['required'] ?? null;
- if ($label) {
- $label .= ($required ? '
*' : '');
- }
- $model = $attributes->wire('model');
- $parameter = $model->value();
- $class = [];
-@endphp
-
-
+
diff --git a/resources/views/widget/country-time-widget.blade.php b/resources/views/widget/country-time-widget.blade.php
new file mode 100644
index 0000000..5f97671
--- /dev/null
+++ b/resources/views/widget/country-time-widget.blade.php
@@ -0,0 +1,34 @@
+
diff --git a/src/Commands/LazyComponentCommand.php b/src/Commands/LazyComponentCommand.php
deleted file mode 100644
index c4edc84..0000000
--- a/src/Commands/LazyComponentCommand.php
+++ /dev/null
@@ -1,19 +0,0 @@
-comment('All done');
-
- return self::SUCCESS;
- }
-}
diff --git a/src/Commands/LazyInstallCommand.php b/src/Commands/LazyInstallCommand.php
new file mode 100644
index 0000000..80c7160
--- /dev/null
+++ b/src/Commands/LazyInstallCommand.php
@@ -0,0 +1,107 @@
+info('Run command "npm i '.$package.'"');
+ shell_exec('npm i '.$package);
+ }
+ }
+
+ if (confirm(
+ label: 'Do you want initialize tailwindcss?',
+ default: true,
+ hint: 'This will initialize tailwindcss'
+ )) {
+ info('Run command "npm i npx tailwindcss init"');
+ shell_exec('npx tailwindcss init');
+ }
+
+ if (! file_exists(base_path('postcss.config.js'))) {
+ info('Copy postcss.config.js');
+ copy(__DIR__.'/../../stubs/postcss.config.js', base_path('postcss.config.js'));
+ }
+
+ if (! file_exists(base_path('resources/scss/lazy.scss'))) {
+ info('Copy lazy.scss');
+ $this->copy(__DIR__.'/../../stubs/scss/lazy.scss', base_path('resources/scss/lazy.scss'));
+ }
+
+ if (! file_exists(base_path('resources/js/lazy.js'))) {
+ info('Copy lazy.js');
+ $this->copy(__DIR__.'/../../stubs/js/lazy.js', base_path('resources/js/lazy.js'));
+ }
+
+ $select = select(
+ label: 'What type config do you want to use?',
+ options: [
+ 'tailwind.config.js' => 'tailwind.config.js',
+ 'tailwind.lazy.config.js' => 'tailwind.lazy.config.js If you use tailwindcss on site, you can use this config',
+ 'ignore' => 'Ignore',
+ ],
+ default: 'tailwind.lazy.config.js',
+ );
+
+ if ($select === 'ignore') {
+ return self::SUCCESS;
+ }
+
+ if ($select === 'tailwind.config.js') {
+ info('Copy tailwind.config.js');
+ copy(__DIR__.'/../../stubs/tailwind.config.js', base_path('tailwind.config.js'));
+ }
+
+ if ($select === 'tailwind.lazy.config.js') {
+ info('Copy tailwind.lazy.config.js');
+
+ copy(__DIR__.'/../../stubs/tailwind.lazy.config.js', base_path('tailwind.lazy.config.js'));
+
+ info('use @config "path to file/tailwind.admin.config.js" in your css file');
+ }
+
+ return self::SUCCESS;
+ }
+
+ public function copy(string $from, string $to): void
+ {
+ $concurrentDirectory = dirname($to);
+
+ // The directory doesn't exist, so create it.
+ if (! is_dir($concurrentDirectory) && ! mkdir($concurrentDirectory, 0755, true) && ! is_dir($concurrentDirectory)) {
+ throw new RuntimeException(sprintf('Directory "%s" was not created', $concurrentDirectory));
+ }
+
+ copy($from, $to);
+ }
+}
diff --git a/src/Components/Alert.php b/src/Components/Alert.php
index 68ecf07..960315b 100644
--- a/src/Components/Alert.php
+++ b/src/Components/Alert.php
@@ -8,7 +8,7 @@
class Alert extends LazyComponent
{
- public function getTypeByAttribute(ComponentAttributeBag $attribute, string $default = null): ?string
+ public function getTypeByAttribute(ComponentAttributeBag $attribute, ?string $default = null): ?string
{
return $this->getKeyByAttribute($attribute, $this->allowedColors(), 'type', $default);
}
diff --git a/src/Components/BtnGroup.php b/src/Components/BtnGroup.php
index 8db2bca..696e557 100644
--- a/src/Components/BtnGroup.php
+++ b/src/Components/BtnGroup.php
@@ -2,6 +2,4 @@
namespace Step2dev\LazyUI\Components;
-class BtnGroup extends Join
-{
-}
+class BtnGroup extends Join {}
diff --git a/src/Components/Chat.php b/src/Components/Chat.php
index db5be3a..5a7808f 100644
--- a/src/Components/Chat.php
+++ b/src/Components/Chat.php
@@ -14,8 +14,7 @@ public function __construct(
public string $avatar = '',
public string $time = '',
public string $position = 'start'
- ) {
- }
+ ) {}
public function render(): Closure|View
{
diff --git a/src/Components/Choices.php b/src/Components/Choices.php
new file mode 100644
index 0000000..7b96c2c
--- /dev/null
+++ b/src/Components/Choices.php
@@ -0,0 +1,39 @@
+isNotEmpty()) {
+ preg_match_all(
+ '/