├── resources
├── views
│ ├── .gitkeep
│ ├── functional
│ │ ├── slot.blade.php
│ │ ├── html.blade.php
│ │ ├── script.blade.php
│ │ ├── content.blade.php
│ │ ├── persistent-layout.blade.php
│ │ ├── teleport.blade.php
│ │ ├── outside.blade.php
│ │ ├── preloaded-modal.blade.php
│ │ ├── flash.blade.php
│ │ ├── state.blade.php
│ │ ├── errors.blade.php
│ │ ├── toggle.blade.php
│ │ ├── rehydrate.blade.php
│ │ ├── event.blade.php
│ │ ├── lazy.blade.php
│ │ ├── link.blade.php
│ │ ├── dynamicHtml.blade.php
│ │ ├── data.blade.php
│ │ ├── dataStores.blade.php
│ │ ├── dialog.blade.php
│ │ ├── defer.blade.php
│ │ ├── form.blade.php
│ │ ├── transition.blade.php
│ │ ├── vue-bridge.blade.php
│ │ └── form-builder.blade.php
│ ├── form
│ │ ├── help.blade.php
│ │ ├── error.blade.php
│ │ ├── label.blade.php
│ │ ├── radios.blade.php
│ │ ├── checkboxes.blade.php
│ │ ├── select-child.blade.php
│ │ ├── group.blade.php
│ │ ├── radio.blade.php
│ │ ├── textarea.blade.php
│ │ ├── wysiwyg.blade.php
│ │ ├── checkbox.blade.php
│ │ └── submit.blade.php
│ ├── table
│ │ ├── wrapper.blade.php
│ │ ├── per-page-selector.blade.php
│ │ ├── add-search-row.blade.php
│ │ ├── global-search.blade.php
│ │ ├── select-rows-dropdown.blade.php
│ │ ├── table.blade.php
│ │ ├── filters.blade.php
│ │ ├── simple-pagination.blade.php
│ │ └── controls.blade.php
│ ├── transitions
│ │ └── classes.blade.php
│ └── components
│ │ ├── button-with-dropdown.blade.php
│ │ ├── dropdown.blade.php
│ │ ├── modal-wrapper.blade.php
│ │ ├── toast-wrapper.blade.php
│ │ └── button.blade.php
└── lang
│ ├── ja.json
│ ├── ar.json
│ ├── en.json
│ ├── fa.json
│ ├── zh_CN.json
│ ├── uk_UA.json
│ ├── it.json
│ ├── pt_BR.json
│ ├── pt_PT.json
│ ├── fr.json
│ ├── id.json
│ ├── ru.json
│ ├── bn.json
│ ├── ms.json
│ ├── ur.json
│ ├── es.json
│ ├── de.json
│ ├── ne.json
│ ├── fil.json
│ └── nl.json
├── lib
├── jodit.js
├── renderSpladeApp.js
├── Components
│ ├── Button.vue
│ ├── Script.vue
│ ├── Transition.vue
│ ├── jodit.scss
│ ├── Flash.vue
│ ├── PreloadedModal.vue
│ ├── Teleport.vue
│ ├── Dialog.vue
│ ├── Errors.vue
│ ├── flatpickr.styl
│ ├── Render.vue
│ ├── DynamicHtml.vue
│ ├── State.vue
│ ├── filepond.scss
│ ├── Toast.vue
│ ├── Toasts.vue
│ ├── FormHelpers.js
│ ├── Textarea.vue
│ ├── JoditEditor.vue
│ ├── DataStores.vue
│ ├── Lazy.vue
│ ├── OnClickOutside.vue
│ └── Data.vue
├── main.js
├── EventBus.js
├── PreserveScrollDirective.js
├── server.js
└── ServerError.vue
├── .vscode
├── extensions.json
└── settings.json
├── stubs
├── resources
│ ├── css
│ │ └── app.css
│ ├── views
│ │ ├── docs.blade.php
│ │ ├── components
│ │ │ ├── panel.blade.php
│ │ │ ├── layout.blade.php
│ │ │ ├── application-mark.blade.php
│ │ │ ├── nav-link.blade.php
│ │ │ └── responsive-nav-link.blade.php
│ │ ├── home.blade.php
│ │ └── root.blade.php
│ └── js
│ │ ├── ssr.js
│ │ └── app.js
├── postcss.config.js
├── vite.config.js
├── tailwind.config.js
└── routes
│ └── web.php
├── src
├── FileUploads
│ ├── HasSpladeFileUploads.php
│ ├── SpladeUploadedFile.php
│ ├── SpladeFile.php
│ └── TemporaryFileUpload.php
├── PaginationException.php
├── FormBuilder
│ ├── Text.php
│ ├── Color.php
│ ├── Email.php
│ ├── Date.php
│ ├── Hidden.php
│ ├── Time.php
│ ├── Password.php
│ ├── Datetime.php
│ ├── Concerns
│ │ ├── HasValue.php
│ │ ├── CanBeInline.php
│ │ └── HasOptions.php
│ ├── Wysiwyg.php
│ ├── Submit.php
│ ├── Radio.php
│ ├── Checkbox.php
│ ├── Textarea.php
│ ├── Radios.php
│ ├── Checkboxes.php
│ ├── Number.php
│ └── Button.php
├── InvalidTransformerException.php
├── Table
│ ├── LaravelExcelException.php
│ ├── PowerJoinsException.php
│ ├── SearchInput.php
│ ├── Export.php
│ ├── HasBulkActions.php
│ ├── HasExports.php
│ └── Filter.php
├── Bridge
│ ├── CouldNotResolveComponentInstance.php
│ └── MiddlewareException.php
├── DataStore.php
├── Components
│ ├── Cell.php
│ ├── Slot.php
│ ├── Script.php
│ ├── Outside.php
│ ├── Teleport.php
│ ├── TableWrapper.php
│ ├── PassesVueVariablesThrough.php
│ ├── ToastWrapper.php
│ ├── ButtonWithDropdown.php
│ ├── Content.php
│ ├── Flash.php
│ ├── State.php
│ ├── Errors.php
│ ├── Toast.php
│ ├── Confirm.php
│ ├── Dynamic.php
│ ├── ModalWrapper.php
│ ├── DynamicHtml.php
│ ├── Dropdown.php
│ ├── Form
│ │ ├── Group.php
│ │ ├── Radio.php
│ │ ├── Radios.php
│ │ ├── Checkbox.php
│ │ ├── Checkboxes.php
│ │ ├── Textarea.php
│ │ └── Submit.php
│ ├── SpladeComponent.php
│ ├── Dialog.php
│ ├── Lazy.php
│ ├── Event.php
│ ├── DataStores.php
│ ├── ParsesJsonDataAttribute.php
│ ├── Rehydrate.php
│ ├── Link.php
│ ├── SerializesNewModels.php
│ ├── Transition.php
│ ├── Toggle.php
│ ├── Button.php
│ └── Data.php
├── Http
│ ├── EventRedirectController.php
│ ├── TableExportController.php
│ ├── ResolvableData.php
│ ├── ConfirmPasswordController.php
│ ├── TableBulkActionController.php
│ ├── FileUploadController.php
│ └── SpladeResponseData.php
├── Facades
│ ├── Animation.php
│ ├── SEO.php
│ └── Toast.php
├── Commands
│ ├── stubs
│ │ ├── splade.request.stub
│ │ ├── splade.form.stub
│ │ └── splade.table.stub
│ ├── CleanupTemporaryFileUploads.php
│ ├── SsrTestCommand.php
│ └── PublishFormStylesheetsCommand.php
├── EloquentSerializer.php
├── SpladeToastBuilder.php
├── Ssr.php
├── EventRefresh.php
├── TransitionAnimation.php
├── FormSelectOption.php
├── TransitionRepository.php
├── Meta.php
└── AbstractForm.php
├── dev-setup.sh
├── phpstan.neon
├── pint.json
├── ExtractTransitionClasses.php
├── .eslintrc.cjs
├── LICENSE.md
├── config
└── splade-seo.php
├── TestStubs.php
└── package.json
/resources/views/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/jodit.js:
--------------------------------------------------------------------------------
1 | import "./Components/jodit.scss";
--------------------------------------------------------------------------------
/resources/views/functional/slot.blade.php:
--------------------------------------------------------------------------------
1 | {{ $slot }}
--------------------------------------------------------------------------------
/resources/views/functional/html.blade.php:
--------------------------------------------------------------------------------
1 | {{ $_spladeEvaluatedHtml }}
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["Vue.volar"]
3 | }
4 |
--------------------------------------------------------------------------------
/resources/views/functional/script.blade.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/stubs/resources/css/app.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
--------------------------------------------------------------------------------
/resources/views/form/help.blade.php:
--------------------------------------------------------------------------------
1 | @if($help)
mergeVueBinding(':passthrough', $passthroughValue()) }}
5 | />
--------------------------------------------------------------------------------
/lib/renderSpladeApp.js:
--------------------------------------------------------------------------------
1 | import { h } from "vue";
2 | import SpladeApp from "./SpladeApp.vue";
3 |
4 | /**
5 | * A little helper function to render the SpladeApp in the main app.js file.
6 | */
7 | export default function render(props) {
8 | return () => {
9 | return h(SpladeApp, props);
10 | };
11 | }
--------------------------------------------------------------------------------
/phpstan.neon:
--------------------------------------------------------------------------------
1 | includes:
2 | - ./vendor/nunomaduro/larastan/extension.neon
3 | - ./phpstan-baseline.neon
4 |
5 | parameters:
6 |
7 | paths:
8 | - src/
9 | excludePaths:
10 | - src/TableExporter.php
11 |
12 | level: 5
13 |
14 | checkGenericClassInNonGenericObjectType: false
15 |
--------------------------------------------------------------------------------
/pint.json:
--------------------------------------------------------------------------------
1 | {
2 | "preset": "laravel",
3 | "rules": {
4 | "binary_operator_spaces": {
5 | "default": "align_single_space_minimal"
6 | },
7 | "concat_space": {
8 | "spacing": "one"
9 | },
10 | "not_operator_with_successor_space": false
11 | }
12 | }
--------------------------------------------------------------------------------
/resources/views/form/label.blade.php:
--------------------------------------------------------------------------------
1 |
2 | {!! $label !!}
3 | @if($attributes->has('required') || $attributes->has('data-required'))
4 | *
5 | @endif
6 |
7 |
--------------------------------------------------------------------------------
/src/DataStore.php:
--------------------------------------------------------------------------------
1 |
2 | {{ $label }}
3 |
4 | @foreach($options as $value => $label)
5 |
6 | @endforeach
7 |
--------------------------------------------------------------------------------
/resources/views/functional/data.blade.php:
--------------------------------------------------------------------------------
1 |
3 | @unless($store)
4 |
5 | {{ $slot }}
6 |
7 | @endunless
8 |
--------------------------------------------------------------------------------
/lib/Components/Button.vue:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/resources/views/table/wrapper.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ $slot }}
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/resources/views/transitions/classes.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/stubs/resources/views/docs.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ __('Docs') }}
4 |
5 |
6 |
7 | Hi developer!
8 | You'll find the docs at splade.dev/docs
9 |
10 |
--------------------------------------------------------------------------------
/stubs/resources/views/components/panel.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
class(['p-6 sm:px-20 bg-white border-b border-gray-200' => true]) }}>
5 | {{ $slot }}
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/stubs/resources/views/home.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ __('Home') }}
4 |
5 |
6 |
7 |
8 |
9 |
10 | Welcome to your Splade application!
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Components/Cell.php:
--------------------------------------------------------------------------------
1 | value = $value;
17 |
18 | return $this;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Components/Slot.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | @spladeHead
8 | @vite('resources/js/app.js')
9 |
10 |
11 | @splade
12 |
13 |
14 |
--------------------------------------------------------------------------------
/stubs/resources/js/ssr.js:
--------------------------------------------------------------------------------
1 | import { createServer } from "http";
2 | import { createSSRApp } from "vue";
3 | import { renderToString } from "@vue/server-renderer";
4 | import { renderSpladeApp, SpladePlugin, startServer } from "@protonemedia/laravel-splade";
5 |
6 | startServer(createServer, renderToString, (props) => {
7 | return createSSRApp({
8 | render: renderSpladeApp(props)
9 | })
10 | .use(SpladePlugin);
11 | });
--------------------------------------------------------------------------------
/lib/main.js:
--------------------------------------------------------------------------------
1 | import "./Components/choices.scss";
2 | import "./Components/filepond.scss";
3 | import "./Components/flatpickr.styl";
4 |
5 | import { Splade } from "./Splade.js";
6 | import renderSpladeApp from "./renderSpladeApp.js";
7 | import SpladePlugin from "./SpladePlugin.js";
8 | import SpladeApp from "./SpladeApp.vue";
9 | import { startServer } from "./server.js";
10 |
11 | export { Splade, SpladeApp, renderSpladeApp, SpladePlugin, startServer };
--------------------------------------------------------------------------------
/src/Components/Script.php:
--------------------------------------------------------------------------------
1 | inline = $inline;
17 |
18 | return $this;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lib/Components/Script.vue:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/Components/Outside.php:
--------------------------------------------------------------------------------
1 | $rawJson)
7 | @js($store): {!! $rawJson !!}@if(!$loop->last),@endif
8 | @endforeach
9 | }"
10 | >
11 |
12 | {{ $slot }}
13 |
14 |
--------------------------------------------------------------------------------
/src/Components/TableWrapper.php:
--------------------------------------------------------------------------------
1 |
2 | import { TransitionRoot, TransitionChild } from "@headlessui/vue";
3 |
4 | export default {
5 | render() {
6 | /*
7 | * This is just a wrapper around the Headless UI components
8 | * so it's easy to use them in Blade templates.
9 | */
10 | return this.$slots.default({
11 | TransitionRoot,
12 | TransitionChild,
13 | });
14 | },
15 | };
16 |
17 |
--------------------------------------------------------------------------------
/src/Components/PassesVueVariablesThrough.php:
--------------------------------------------------------------------------------
1 | passthrough,
12 | '##SPLADE-PASSTHROUGH-',
13 | $this->passthrough ? 'APPEND' : 'NEW',
14 | '##',
15 | '}',
16 | ]);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Components/ToastWrapper.php:
--------------------------------------------------------------------------------
1 |
2 | {{ $label }}
3 |
4 | @foreach($options as $value => $label)
5 |
11 | @endforeach
12 |
--------------------------------------------------------------------------------
/resources/views/table/per-page-selector.blade.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/FormBuilder/Concerns/HasOptions.php:
--------------------------------------------------------------------------------
1 | 'Label 1', 'value2' => 'Label 2']
13 | * @return $this
14 | */
15 | public function options(array $options = []): self
16 | {
17 | $this->options = $options;
18 |
19 | return $this;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Http/EventRedirectController.php:
--------------------------------------------------------------------------------
1 | with($data['with'] ?? []);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib/Components/jodit.scss:
--------------------------------------------------------------------------------
1 | @import "jodit/build/jodit.css";
2 |
3 | .jodit-container:not(.jodit_inline) {
4 | @apply shadow-sm rounded-md border-gray-300;
5 | }
6 |
7 | .jodit-toolbar__box:not(:empty) {
8 | @apply rounded-t-md;
9 | }
10 |
11 | .jodit-status-bar,
12 | .jodit-container:not(.jodit_inline) .jodit-workplace {
13 | @apply rounded-b-md;
14 | }
15 |
16 | .jodit-toolbar__box:not(:empty):not(:empty) {
17 | @apply bg-gray-50;
18 | }
19 |
20 | .jodit-container:not(.jodit_inline) .jodit-wysiwyg {
21 | @apply px-3 py-2;
22 | }
--------------------------------------------------------------------------------
/resources/views/form/select-child.blade.php:
--------------------------------------------------------------------------------
1 | @php $attributes = $selectChild->attributes() @endphp
2 |
3 | @if($selectChild->isGroup())
4 |
9 | @else
10 |
13 | @endif
--------------------------------------------------------------------------------
/resources/views/functional/dialog.blade.php:
--------------------------------------------------------------------------------
1 |
2 | mergeVueBinding(':is', $panel ? 'DialogPanel' : 'Dialog')
5 | ->mergeVueBinding(':open', $open ? ('(' . e($open) . ') && isActivated' . $spladeId) : '', escape: false)
6 | ->mergeVueBinding(':unmount', $unmount)
7 | ->mergeVueBinding('@close', $close)
8 | }}
9 | >
10 | {{ $slot }}
11 |
12 |
--------------------------------------------------------------------------------
/stubs/resources/js/app.js:
--------------------------------------------------------------------------------
1 | import "./bootstrap";
2 | import "../css/app.css";
3 | import "@protonemedia/laravel-splade/dist/style.css";
4 |
5 | import { createApp } from "vue/dist/vue.esm-bundler.js";
6 | import { renderSpladeApp, SpladePlugin } from "@protonemedia/laravel-splade";
7 |
8 | const el = document.getElementById("app");
9 |
10 | createApp({
11 | render: renderSpladeApp({ el })
12 | })
13 | .use(SpladePlugin, {
14 | "max_keep_alive": 10,
15 | "transform_anchors": false,
16 | "progress_bar": true
17 | })
18 | .mount(el);
19 |
--------------------------------------------------------------------------------
/lib/Components/Flash.vue:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/Components/ButtonWithDropdown.php:
--------------------------------------------------------------------------------
1 | SpladeComponent::normalize('dropdown'),
18 | ]);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/FormBuilder/Wysiwyg.php:
--------------------------------------------------------------------------------
1 | name,
18 | label: $this->label,
19 | help: $this->help
20 | );
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/resources/views/components/button-with-dropdown.blade.php:
--------------------------------------------------------------------------------
1 | class('w-full bg-white border border-gray-300 rounded-md shadow-sm px-2.5 sm:px-4 py-2 inline-flex justify-center text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500') }}>
2 |
3 | {{ $button }}
4 |
5 |
6 |
7 | {{ $slot }}
8 |
9 |
10 |
--------------------------------------------------------------------------------
/stubs/resources/views/components/layout.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | @if(isset($header))
6 |
13 | @endif
14 |
15 |
16 |
17 | {{ $slot }}
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/Bridge/MiddlewareException.php:
--------------------------------------------------------------------------------
1 | response;
20 | }
21 |
22 | public static function fromResponse($response)
23 | {
24 | return tap(new static, fn (self $e) => $e->response = $response);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/stubs/resources/views/components/application-mark.blade.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/stubs/resources/views/components/nav-link.blade.php:
--------------------------------------------------------------------------------
1 | @props(['active'])
2 |
3 | @php
4 | $classes = ($active ?? false)
5 | ? 'inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 text-sm font-medium leading-5 text-gray-900 focus:outline-none focus:border-indigo-700 transition'
6 | : 'inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition';
7 | @endphp
8 |
9 | merge(['class' => $classes]) }}>
10 | {{ $slot }}
11 |
12 |
--------------------------------------------------------------------------------
/ExtractTransitionClasses.php:
--------------------------------------------------------------------------------
1 | classes());
13 |
14 | file_put_contents(
15 | __DIR__ . '/resources/views/transitions/classes.blade.php',
16 | "\n\n
",
17 | );
18 |
--------------------------------------------------------------------------------
/src/Components/Content.php:
--------------------------------------------------------------------------------
1 |
24 | */
25 | public function rules()
26 | {
27 | return {{ form }}::rules();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/FormBuilder/Submit.php:
--------------------------------------------------------------------------------
1 | spinner = $enabled;
19 |
20 | return $this;
21 | }
22 |
23 | /**
24 | * Create a new form field
25 | */
26 | public static function make(string $name = ''): static
27 | {
28 | return new static($name);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/stubs/resources/views/components/responsive-nav-link.blade.php:
--------------------------------------------------------------------------------
1 | @props(['active'])
2 |
3 | @php
4 | $classes = ($active ?? false)
5 | ? 'block pl-3 pr-4 py-2 border-l-4 border-indigo-400 text-base font-medium text-indigo-700 bg-indigo-50 focus:outline-none focus:text-indigo-800 focus:bg-indigo-100 focus:border-indigo-700 transition'
6 | : 'block pl-3 pr-4 py-2 border-l-4 border-transparent text-base font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:text-gray-800 focus:bg-gray-50 focus:border-gray-300 transition';
7 | @endphp
8 |
9 | merge(['class' => $classes]) }}>
10 | {{ $slot }}
11 |
12 |
--------------------------------------------------------------------------------
/resources/views/functional/defer.blade.php:
--------------------------------------------------------------------------------
1 | mergeVueBinding(':manual', $manual)
3 | ->mergeVueBinding(':poll', $poll)
4 | ->mergeVueBinding(':watch-debounce', $watchDebounce)
5 | ->mergeVueBinding(':watch-value', $watchValue)
6 | ->mergeVueBinding(':url', $url)
7 | }}
8 | @if($data) :default="@js($data)" @else :default="{!! $json !!}" @endif
9 | @if($headers) :headers="@js($headers)" @else :headers="{!! $jsonHeaders !!}" @endif
10 | @if($requestData) :request="@js($requestData)" @else :request="{!! $requestJson !!}" @endif>
11 |
12 | {{ $slot }}
13 |
14 |
--------------------------------------------------------------------------------
/src/FormBuilder/Radio.php:
--------------------------------------------------------------------------------
1 | name,
21 | value: $this->value ?? 1,
22 | label: $this->label,
23 | help: $this->help
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/stubs/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import laravel from "laravel-vite-plugin";
3 | import vue from "@vitejs/plugin-vue";
4 |
5 | export default defineConfig({
6 | plugins: [
7 | laravel({
8 | input: "resources/js/app.js",
9 | ssr: "resources/js/ssr.js",
10 | refresh: true,
11 | }),
12 | vue({
13 | template: {
14 | transformAssetUrls: {
15 | base: null,
16 | includeAbsolute: false,
17 | },
18 | },
19 | }),
20 | ],
21 | ssr: {
22 | noExternal: ["vue", "@protonemedia/laravel-splade"]
23 | },
24 | });
--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: [
3 | "eslint:recommended",
4 | "plugin:vue/vue3-recommended",
5 | "plugin:vue/vue3-essential",
6 | "plugin:vue/vue3-strongly-recommended",
7 | ],
8 | rules: {
9 | "no-undef": 0,
10 | "vue/multi-word-component-names": 0,
11 | "vue/no-v-html": 0,
12 | "vue/require-default-prop": 0,
13 | "vue/no-setup-props-destructure": 0,
14 | indent: ["error", 4],
15 | quotes: ["error", "double"],
16 | "object-curly-spacing": ["error", "always"],
17 | semi: ["error", "always"],
18 | "comma-spacing": ["error", { before: false, after: true }],
19 | },
20 | };
21 |
--------------------------------------------------------------------------------
/lib/Components/PreloadedModal.vue:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/Components/Toast.php:
--------------------------------------------------------------------------------
1 | toast->toArray());
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lib/Components/Teleport.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
33 |
--------------------------------------------------------------------------------
/src/FormBuilder/Checkbox.php:
--------------------------------------------------------------------------------
1 | name,
21 | value: $this->value ?? true,
22 | label: $this->label,
23 | help: $this->help,
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/resources/lang/ja.json:
--------------------------------------------------------------------------------
1 | {
2 | "Are you sure you want to continue?": "続行しますか?",
3 | "Browse": "ファイルを選択",
4 | "Cancel": "キャンセル",
5 | "Clear selection": "選択箇所を解除",
6 | "Confirm": "確認",
7 | "Drag and drop your files or Browse": "ファイルをドラッグ&ドロップするか選択",
8 | "Excel Export": "Excelにエクスポート",
9 | "Export results": "エクスポート結果",
10 | "Go to page :page": ":pageページに移動",
11 | "Item selected": "選択されたアイテム",
12 | "Items selected": "選択されたアイテム",
13 | "Pagination Navigation": "ナビゲーションのページ送り",
14 | "Search": "検索",
15 | "Select all on this page": "このページの全てを選択",
16 | "Select all results": "全ての結果を選択",
17 | "of": "件目、全:",
18 | "per page": "毎ページ",
19 | "results": "件",
20 | "to": "から"
21 | }
22 |
--------------------------------------------------------------------------------
/src/Commands/CleanupTemporaryFileUploads.php:
--------------------------------------------------------------------------------
1 | info('Cleaning up temporary file uploads...');
20 |
21 | $filesystem->deleteTemporaryFiles();
22 |
23 | $this->info('Done!');
24 |
25 | return static::SUCCESS;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lib/Components/Dialog.vue:
--------------------------------------------------------------------------------
1 |
32 |
--------------------------------------------------------------------------------
/src/FormBuilder/Textarea.php:
--------------------------------------------------------------------------------
1 | attributes['autosize'] = $autosize;
12 |
13 | return $this;
14 | }
15 |
16 | /**
17 | * Renders the SpladeTextarea
18 | *
19 | * @return \Closure|\Illuminate\Contracts\View\View|string
20 | */
21 | public function toSpladecomponent()
22 | {
23 | return new SpladeTextarea(
24 | name: $this->name,
25 | label: $this->label,
26 | help: $this->help
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Http/TableExportController.php:
--------------------------------------------------------------------------------
1 | authorize($request)) {
20 | throw new UnauthorizedException;
21 | }
22 |
23 | return $tableInstance->makeExporter($export);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/Components/Errors.vue:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/Components/Confirm.php:
--------------------------------------------------------------------------------
1 | Route::has('splade.confirmedPasswordStatus') ? route('splade.confirmedPasswordStatus') : '',
19 |
20 | 'confirmPasswordRoute' => Route::has('splade.confirmPassword') ? route('splade.confirmPassword') : '',
21 | ]);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/stubs/tailwind.config.js:
--------------------------------------------------------------------------------
1 | import forms from "@tailwindcss/forms";
2 | import typography from "@tailwindcss/typography";
3 |
4 | /* @type {import('tailwindcss').Config} */
5 | export default {
6 | content: [
7 | "./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php",
8 | "./vendor/protonemedia/laravel-splade/lib/**/*.vue",
9 | "./vendor/protonemedia/laravel-splade/resources/views/**/*.blade.php",
10 | "./storage/framework/views/*.php",
11 | "./resources/views/**/*.blade.php",
12 | "./resources/js/**/*.vue",
13 | // "./app/Forms/*.php",
14 | // "./app/Tables/*.php",
15 | ],
16 |
17 | theme: {
18 | extend: {},
19 | },
20 |
21 | plugins: [forms, typography],
22 | };
23 |
--------------------------------------------------------------------------------
/lib/EventBus.js:
--------------------------------------------------------------------------------
1 | class EventBus {
2 | constructor(id) {
3 | this.id = id;
4 | this.events = {};
5 | }
6 |
7 | on(event, callback) {
8 | if (!this.events[event]) {
9 | this.events[event] = [];
10 | }
11 |
12 | this.events[event].push(callback);
13 | }
14 |
15 | off(event, callback) {
16 | if (!this.events[event]) {
17 | return;
18 | }
19 |
20 | this.events[event] = this.events[event].filter(cb => cb !== callback);
21 | }
22 |
23 | emit(event, data) {
24 | if (!this.events[event]) {
25 | return;
26 | }
27 |
28 | this.events[event].forEach((callback) => {
29 | callback(data);
30 | });
31 | }
32 | }
33 |
34 | export default EventBus;
--------------------------------------------------------------------------------
/src/EloquentSerializer.php:
--------------------------------------------------------------------------------
1 | getSerializedPropertyValue($value);
20 | }
21 |
22 | /**
23 | * Get the restored value after deserialization.
24 | *
25 | * @param mixed $value
26 | * @return mixed
27 | */
28 | public function restore($value)
29 | {
30 | return $this->getRestoredPropertyValue($value);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/SpladeToastBuilder.php:
--------------------------------------------------------------------------------
1 | forwardCallTo(
28 | $this->splade->toast(),
29 | $method,
30 | $parameters
31 | );
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Components/Dynamic.php:
--------------------------------------------------------------------------------
1 | name . '-->',
27 | '{{ $slot }}',
28 | '',
29 | ]);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/resources/lang/ar.json:
--------------------------------------------------------------------------------
1 | {
2 | "Are you sure you want to continue?": "هل أنت متأكد من المواصلة؟",
3 | "Browse": "تصفح",
4 | "Cancel": "إلغاء",
5 | "Clear selection": "حذف العناصر المحددة",
6 | "Confirm": "تأكيد",
7 | "Drag and drop your files or Browse": "اسحب الملفات وأسقطها أو تصفح",
8 | "Excel Export": "تصدير إكسيل",
9 | "Export results": "تصدير النتائج",
10 | "Go to page :page": "اذهب إلى الصفحة :page",
11 | "Item selected": "العنصر المحدد",
12 | "Items selected": "العناصر المحددة",
13 | "Pagination Navigation": "التنقل بين الصفحات",
14 | "Search": "بحث",
15 | "Select all on this page": "تحديد الكل في هاته الصفحة",
16 | "Select all results": "تحديد كل النتائج",
17 | "of": "من",
18 | "per page": "لكل صفحة",
19 | "results": "النتائج",
20 | "to": "إلى"
21 | }
22 |
--------------------------------------------------------------------------------
/src/Components/ModalWrapper.php:
--------------------------------------------------------------------------------
1 | name,
23 | options: $this->options,
24 | label: $this->label,
25 | inline: $this->inline,
26 | help: $this->help
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/resources/lang/fa.json:
--------------------------------------------------------------------------------
1 | {
2 | "Are you sure you want to continue?": "آیا مطمئن هستید که میخواهید ادامه دهید؟",
3 | "Browse": "مرور کردن",
4 | "Cancel": "لغو",
5 | "Clear selection": "پاک کردن انتخاب",
6 | "Confirm": "تأیید",
7 | "Drag and drop your files or Browse": "فایل های خود را بکشید و رها کنید یا مرور کنید",
8 | "Excel Export": "خروجی به اکسل",
9 | "Export results": "خروجی نتایج",
10 | "Go to page :page": "رفتن به صفحه :page",
11 | "Item selected": "مورد انتخاب شده",
12 | "Items selected": "موارد انتخاب شده",
13 | "Pagination Navigation": "پیمایش صفحه",
14 | "Search": "جستجو کردن",
15 | "Select all on this page": "انتخاب همه در این صفحه",
16 | "Select all results": "انتخاب همه نتایج",
17 | "of": "از",
18 | "per page": "هر صفحه",
19 | "results": "نتایج",
20 | "to": "به"
21 | }
22 |
--------------------------------------------------------------------------------
/resources/lang/zh_CN.json:
--------------------------------------------------------------------------------
1 | {
2 | "Are you sure you want to continue?": "确定要继续吗?",
3 | "Browse": "浏览",
4 | "Cancel": "取消",
5 | "Clear selection": "清除选择项",
6 | "Confirm": "确认",
7 | "Drag and drop your files or Browse": "拖拽或浏览选择文件",
8 | "Excel Export": "导出 Excel",
9 | "Export results": "导出结果",
10 | "Go to page :page": "前往第 :page 页",
11 | "Item selected": "当前所选项目",
12 | "Items selected": "已选择项目",
13 | "No user is logged in": "没有用户登录",
14 | "Pagination Navigation": "分页导航",
15 | "Please confirm your password before continuing": "请在继续操作之前确认您的密码",
16 | "Remove search": "取消搜索",
17 | "Reset": "重置",
18 | "Search": "搜索",
19 | "Select all on this page": "选择当前页",
20 | "Select all results": "选择全部",
21 | "of": "的",
22 | "per page": "每页",
23 | "results": "个结果",
24 | "to": "到"
25 | }
26 |
--------------------------------------------------------------------------------
/src/Components/DynamicHtml.php:
--------------------------------------------------------------------------------
1 | passthrough = implode(',', Form::splitByComma($passthrough));
21 | }
22 |
23 | /**
24 | * Get the view / contents that represent the component.
25 | *
26 | * @return \Illuminate\Contracts\View\View|\Closure|string
27 | */
28 | public function render()
29 | {
30 | return view('splade::functional.dynamicHtml');
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/FormBuilder/Checkboxes.php:
--------------------------------------------------------------------------------
1 | name,
23 | options: $this->options,
24 | label: $this->label,
25 | inline: $this->inline,
26 | help: $this->help
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Commands/stubs/splade.form.stub:
--------------------------------------------------------------------------------
1 | action(route('...'))
16 | ->method('POST')
17 | ->class('space-y-4')
18 | ->fill([
19 | //
20 | ]);
21 | }
22 |
23 | public function fields(): array
24 | {
25 | return [
26 | Text::make('...')
27 | ->label(__('...')),
28 |
29 | //
30 |
31 | Submit::make()
32 | ->label(__('Save')),
33 | ];
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Components/Dropdown.php:
--------------------------------------------------------------------------------
1 | spladeId = Str::random();
23 | }
24 |
25 | /**
26 | * Get the view / contents that represent the component.
27 | *
28 | * @return \Illuminate\Contracts\View\View|\Closure|string
29 | */
30 | public function render()
31 | {
32 | return view('splade::components.dropdown');
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/resources/lang/uk_UA.json:
--------------------------------------------------------------------------------
1 | {
2 | "Are you sure you want to continue?": "Ви впевнені, що бажаєте продовжити?",
3 | "Browse": "Огляд",
4 | "Cancel": "Скасувати",
5 | "Clear selection": "Очистити вибір",
6 | "Confirm": "Підтвердити",
7 | "Drag and drop your files or Browse": "Перетягніть файли або перегляньте їх",
8 | "Excel Export": "Експорт Excel",
9 | "Export results": "Експорт результатів",
10 | "Go to page :page": "Перейти на сторінку :page",
11 | "Item selected": "Елемент обрано",
12 | "Items selected": "Вибрані елементи",
13 | "Pagination Navigation": "Навігація по сторінках",
14 | "Search": "Пошук",
15 | "Select all on this page": "Вибрати все на цій сторінці",
16 | "Select all results": "Вибрати всі результати",
17 | "of": "з",
18 | "per page": "на сторінку",
19 | "results": "результати",
20 | "to": "до"
21 | }
22 |
--------------------------------------------------------------------------------
/lib/Components/flatpickr.styl:
--------------------------------------------------------------------------------
1 | $calendarBorderColor ?= #d1d5db // gray-300
2 | $dayHoverBackground ?= #f3f4f6 // gray-100
3 | $monthForeground ?= #111827 // gray-900
4 | $weekdaysForeground ?= #d1d5db // gray-300
5 | $dayForeground ?= #374151 // gray-700
6 | $arrow_hover_color ?= #6366f1 // indigo-500
7 | $selectedDayBackground ?= #6366f1 // indigo-500
8 |
9 | @import "flatpickr/src/style/flatpickr.styl"
10 |
11 | .flatpickr-calendar
12 | border-radius 0.375rem // .rounded-md
13 | margin-top 1px // .mt-px
14 |
15 | &:before, &:after
16 | display none // .hidden
17 |
18 | .flatpickr-wrapper
19 | width 100% // .w-full
20 |
21 | .flatpickr-current-month
22 | .flatpickr-monthDropdown-months
23 | input.cur-year
24 | font-size 1rem // .font-base
25 |
26 | .flatpickr-time
27 | input
28 | &:focus
29 | box-shadow none // .shadow-none
--------------------------------------------------------------------------------
/resources/lang/it.json:
--------------------------------------------------------------------------------
1 | {
2 | "Are you sure you want to continue?": "Sei sicuro di voler continuare?",
3 | "Browse": "Sfoglia",
4 | "Cancel": "Annulla",
5 | "Clear selection": "Elimina selezione",
6 | "Confirm": "Conferma",
7 | "Drag and drop your files or Browse": "Trascina qua i tuoi file oppure Sfoglia",
8 | "Excel Export": "Esporta Excel",
9 | "Export results": "Esporta risultati",
10 | "Go to page :page": "Vai alla pagina :page",
11 | "Item selected": "Elemento selezionato",
12 | "Items selected": "Elementi selezionati",
13 | "Pagination Navigation": "Naviga per pagine",
14 | "Search": "Cerca",
15 | "Select all on this page": "Seleziona tutto su questa pagina",
16 | "Select all results": "Seleziona tutti i risultati",
17 | "of": "di",
18 | "per page": "per pagina",
19 | "results": "risultati",
20 | "to": "a"
21 | }
22 |
--------------------------------------------------------------------------------
/src/FileUploads/SpladeUploadedFile.php:
--------------------------------------------------------------------------------
1 | exists($this->temporaryFileUpload);
20 | }
21 |
22 | /**
23 | * Sets the temporary file upload.
24 | */
25 | public function setTemporaryFileUpload(TemporaryFileUpload $temporaryFileUpload): self
26 | {
27 | $this->temporaryFileUpload = $temporaryFileUpload;
28 |
29 | return $this;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/resources/lang/pt_BR.json:
--------------------------------------------------------------------------------
1 | {
2 | "Are you sure you want to continue?": "Você tem certeza que quer continuar?",
3 | "Browse": "Procurar",
4 | "Cancel": "Cancelar",
5 | "Clear selection": "Limpar seleção",
6 | "Confirm": "Confirmar",
7 | "Drag and drop your files or Browse": "Arraste e solte seus arquivos ou Procure",
8 | "Excel Export": "Exportar para Excel",
9 | "Export results": "Exportar resultados",
10 | "Go to page :page": "Ir para página :page:",
11 | "Item selected": "Item selecionado",
12 | "Items selected": "Itens selecionados",
13 | "Pagination Navigation": "Navegação de Páginas",
14 | "Search": "Pesquisar",
15 | "Select all on this page": "Selecionar todos nessa página",
16 | "Select all results": "Selecionar todos os resultados",
17 | "of": "de",
18 | "per page": "por página",
19 | "results": "resultados",
20 | "to": "até"
21 | }
22 |
--------------------------------------------------------------------------------
/lib/Components/Render.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/resources/lang/pt_PT.json:
--------------------------------------------------------------------------------
1 | {
2 | "Are you sure you want to continue?": "Tem a certeza que quer continuar?",
3 | "Browse": "Procurar",
4 | "Cancel": "Cancelar",
5 | "Clear selection": "Cancelar escolhas",
6 | "Confirm": "Confirmar",
7 | "Drag and drop your files or Browse": "Arraste e solte seus ficheiros ou Procurar",
8 | "Excel Export": "Exportar para Excel",
9 | "Export results": "Exportar resultados",
10 | "Go to page :page": "Ir para a página :page:",
11 | "Item selected": "Item selecionado",
12 | "Items selected": "Itens selecionados",
13 | "Pagination Navigation": "Navegação de Páginas",
14 | "Search": "Pesquisar",
15 | "Select all on this page": "Selecionar todos nesta página",
16 | "Select all results": "Selecionar todos os resultados",
17 | "of": "de",
18 | "per page": "por página",
19 | "results": "resultados",
20 | "to": "até"
21 | }
22 |
--------------------------------------------------------------------------------
/resources/lang/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "Are you sure you want to continue?": "Êtes-vous sûr de vouloir continuer ?",
3 | "Browse": "Explorer",
4 | "Cancel": "Annuler",
5 | "Clear selection": "Effacer la sélection",
6 | "Confirm": "Confirmer",
7 | "Drag and drop your files or Browse": "Glissez et déposez vos fichiers ou parcourez-les",
8 | "Excel Export": "Exporter en Excel",
9 | "Export results": "Exporter les résultats",
10 | "Go to page :page": "Aller à la page :page",
11 | "Item selected": "Elément sélectionné",
12 | "Items selected": "Eléments sélectionnés",
13 | "Pagination Navigation": "Navigation par pagination",
14 | "Search": "Recherche",
15 | "Select all on this page": "Tout sélectionner sur cette page",
16 | "Select all results": "Sélectionner tous les résultats",
17 | "of": "de",
18 | "per page": "par page",
19 | "results": "résultats",
20 | "to": "à"
21 | }
22 |
--------------------------------------------------------------------------------
/src/Ssr.php:
--------------------------------------------------------------------------------
1 | null];
16 |
17 | $data = [
18 | 'components' => $components,
19 | 'html' => $html,
20 | 'dynamics' => $dynamics,
21 | 'splade' => $splade->toArray(),
22 | ];
23 |
24 | return rescue(
25 | callback: fn () => Http::post(config('splade.ssr.server'), $data)->throw()->json(),
26 | rescue: $default,
27 | report: false
28 | ) ?: $default;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/resources/lang/id.json:
--------------------------------------------------------------------------------
1 | {
2 | "Are you sure you want to continue?": "Apakah anda yakin ingin melanjutkan?",
3 | "Browse": "Temukan",
4 | "Cancel": "Batalkan",
5 | "Clear selection": "Hapus pilihan",
6 | "Confirm": "Konfimasi",
7 | "Drag and drop your files or Browse": "Tarik dan lepas file anda atau telusuri",
8 | "Excel Export": "Export Excel",
9 | "Export results": "Export hasil",
10 | "Go to page :page": "Pergi ke halaman :page",
11 | "Item selected": "Item yang dipilih",
12 | "Items selected": "Item yang dipilih",
13 | "Pagination Navigation": "Navigasi paginasi",
14 | "Remove search": "Hapus pencarian",
15 | "Reset": "Atur ulang",
16 | "Search": "Cari",
17 | "Select all on this page": "Pilih semua di halaman ini",
18 | "Select all results": "Pilih semua hasil",
19 | "of": "dari",
20 | "per page": "Per halaman",
21 | "results": "hasil",
22 | "to": "ke"
23 | }
24 |
--------------------------------------------------------------------------------
/src/Table/SearchInput.php:
--------------------------------------------------------------------------------
1 | key,
34 | $this->columns,
35 | $this->label,
36 | $this->value,
37 | );
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/resources/lang/ru.json:
--------------------------------------------------------------------------------
1 | {
2 | "Are you sure you want to continue?": "Вы уверены, что хотите продолжить?",
3 | "Browse": "Открыть",
4 | "Cancel": "Отмена",
5 | "Clear selection": "Сбросить выбор",
6 | "Confirm": "Подтвердить",
7 | "Drag and drop your files or Browse": "Перетащите или откройте Ваши файлы",
8 | "Excel Export": "Экспорт в Excel",
9 | "Export results": "Результаты экспорта",
10 | "Go to page :page": "Перейти к :page-й странице",
11 | "Item selected": "Выбранный элемент",
12 | "Items selected": "Выбранные элементы",
13 | "Pagination Navigation": "Навигация",
14 | "Remove search": "Сбросить поиск",
15 | "Reset": "Сброс",
16 | "Search": "Поиск",
17 | "Select all on this page": "Выбрать все на этой странице",
18 | "Select all results": "Выбрать все результаты",
19 | "of": "из",
20 | "per page": "на странице",
21 | "results": "результатов",
22 | "to": "по"
23 | }
24 |
--------------------------------------------------------------------------------
/resources/views/form/group.blade.php:
--------------------------------------------------------------------------------
1 | @php
2 | [$gridClasses, $otherClasses] = collect(explode(' ', $attributes->get('class')))
3 | ->partition(fn ($class) => Str::startsWith($class, ['gap', 'grid']) || Str::contains($class, [':gap', ':grid']));
4 | @endphp
5 |
6 | only(['v-if', 'v-show'])->class($otherClasses->all())->merge([
7 | 'data-validation-key' => $validationKey(),
8 | ]) }}>
9 | @includeWhen($label, 'splade::form.label', ['label' => $label])
10 |
11 |
except(['v-if', 'v-show', 'class'])->class([
12 | 'flex flex-wrap space-x-6' => $inline && $gridClasses->isEmpty(),
13 | 'space-y-1' => !$inline && $gridClasses->isEmpty(),
14 | ])->class($gridClasses->all()) }}
15 | >
16 | {{ $slot }}
17 |
18 |
19 | @includeWhen($help, 'splade::form.help', ['help' => $help])
20 | @includeWhen($showErrors, 'splade::form.error', ['name' => $validationKey()])
21 |
--------------------------------------------------------------------------------
/src/Components/Form/Group.php:
--------------------------------------------------------------------------------
1 | only(['v-if', 'v-show', 'class']) }}>
2 |
20 |
21 | @includeWhen($help, 'splade::form.help', ['help' => $help])
22 | @includeWhen($showErrors, 'splade::form.error', ['name' => $validationKey()])
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/resources/views/form/textarea.blade.php:
--------------------------------------------------------------------------------
1 | only(['v-if', 'v-show', 'class']) }}
3 | :autosize="@js($attributes->has('autosize') ? (bool) $attributes->get('autosize') : $defaultAutosizeValue)"
4 | v-model="{{ $vueModel() }}"
5 | >
6 |
17 |
18 | @includeWhen($help, 'splade::form.help', ['help' => $help])
19 | @includeWhen($showErrors, 'splade::form.error', ['name' => $validationKey()])
20 |
21 |
--------------------------------------------------------------------------------
/resources/views/form/wysiwyg.blade.php:
--------------------------------------------------------------------------------
1 | only(['v-if', 'v-show', 'class']) }}
3 | :options="@js($joditOptions())"
4 | :js-options="{!! $jsJoditOptions() !!}"
5 | v-model="{{ $vueModel() }}"
6 | :dusk="@js($attributes->get('dusk'))"
7 | >
8 |
19 |
20 | @includeWhen($help, 'splade::form.help', ['help' => $help])
21 | @includeWhen($showErrors, 'splade::form.error', ['name' => $validationKey()])
22 |
23 |
--------------------------------------------------------------------------------
/resources/views/table/add-search-row.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | @foreach($table->searchInputs() as $searchInput)
9 | @if($searchInput->key === 'global')
10 | @continue
11 | @endif
12 |
13 |
19 | @endforeach
20 |
--------------------------------------------------------------------------------
/resources/views/table/global-search.blade.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/Http/ResolvableData.php:
--------------------------------------------------------------------------------
1 | callable = $callable;
17 | }
18 |
19 | /**
20 | * Helper method the wrap non-callable values into a callable.
21 | *
22 | * @param mixed $value
23 | */
24 | public static function from($value): static
25 | {
26 | return new static(
27 | is_callable($value) ? $value : fn () => $value
28 | );
29 | }
30 |
31 | /**
32 | * Resolves the callable based on the given boolean.
33 | *
34 | * @return mixed
35 | */
36 | public function resolveIf(bool $shouldResolve)
37 | {
38 | return $shouldResolve
39 | ? App::call($this->callable)
40 | : null;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/resources/views/functional/form.blade.php:
--------------------------------------------------------------------------------
1 | @php $data = $formData() @endphp
2 |
3 | rejectWhenBlank('id')->except('class') }}
4 | @if($data['data']) :default="@js($data['data'])" @else :default="{!! $data['json'] !!}" @endif
5 | :scroll-on-error="@js($scrollOnError)"
6 | :splade-id="@js($spladeId)"
7 | :submit-on-change="@js($submitOnChange)"
8 | :escape-validation-messages="@js($escapeValidationMessages)"
9 | :preserve-scroll="@js($preserveScroll)"
10 | :background="@js($background)"
11 | :debounce="@js($debounce)"
12 | :accept-header="@js($acceptHeader)"
13 | >
14 |
15 |
20 |
21 |
--------------------------------------------------------------------------------
/resources/views/form/checkbox.blade.php:
--------------------------------------------------------------------------------
1 | only(['v-if', 'v-show', 'class']) }}>
2 |
19 |
20 | @includeWhen($help, 'splade::form.help', ['help' => $help])
21 | @includeWhen($showErrors, 'splade::form.error', ['name' => $validationKey()])
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/Components/SpladeComponent.php:
--------------------------------------------------------------------------------
1 | component = static::normalize($is);
18 | }
19 |
20 | /**
21 | * Prepends the 'x-' Blade Component prefix to the given name.
22 | */
23 | public static function tag(string $name): string
24 | {
25 | return 'x-' . static::normalize($name);
26 | }
27 |
28 | /**
29 | * Prepends the configured prefix to the given component name.
30 | */
31 | public static function normalize(string $name): string
32 | {
33 | $prefix = config('splade.blade.component_prefix');
34 |
35 | if ($prefix) {
36 | $prefix .= '-';
37 | }
38 |
39 | return $prefix . $name;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/lib/Components/DynamicHtml.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
12 |
13 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/lib/Components/State.vue:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/views/functional/transition.blade.php:
--------------------------------------------------------------------------------
1 |
2 | mergeVueBinding('enter', "{$animate} ? '{$animation->enter}' : ''")
5 | ->mergeVueBinding('enter-from', "{$animate} ? '{$animation->enterFrom}' : ''")
6 | ->mergeVueBinding('enter-to', "{$animate} ? '{$animation->enterTo}' : ''")
7 | ->mergeVueBinding('leave', "{$animate} ? '{$animation->leave}' : ''")
8 | ->mergeVueBinding('leave-from', "{$animate} ? '{$animation->leaveFrom}' : ''")
9 | ->mergeVueBinding('leave-to', "{$animate} ? '{$animation->leaveTo}' : ''")
10 | ->mergeVueBinding(':is', $child ? 'TransitionChild' : 'TransitionRoot')
11 | ->mergeVueBinding(':show', $show)
12 | ->mergeVueBinding(':appear', $appear)
13 | ->mergeVueBinding(':unmount', $unmount)
14 | ->mergeVueBinding('@after-leave', $afterLeave)
15 | }}
16 | >
17 | {{ $slot }}
18 |
19 |
--------------------------------------------------------------------------------
/src/Components/Dialog.php:
--------------------------------------------------------------------------------
1 | spladeId = Str::random();
24 | }
25 |
26 | /**
27 | * Get the view / contents that represent the component.
28 | *
29 | * @return \Illuminate\Contracts\View\View|\Closure|string
30 | */
31 | public function render()
32 | {
33 | return view('splade::functional.dialog', [
34 | 'panel' => $this->panel,
35 | 'open' => $this->open,
36 | 'unmount' => $this->unmount,
37 | 'close' => $this->close,
38 | ]);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Components/Form/Radio.php:
--------------------------------------------------------------------------------
1 | true,
21 | 'splade.preserveScroll' => $this->preserveScroll,
22 | ];
23 | }
24 |
25 | /**
26 | * Preserve the scroll value on refresh.
27 | *
28 | * @return $this
29 | */
30 | public function preserveScroll(bool $value = true): self
31 | {
32 | $this->preserveScroll = $value;
33 |
34 | return $this;
35 | }
36 |
37 | /**
38 | * Returns the same array, but this method is called when broadcasting.
39 | *
40 | * @return array
41 | */
42 | public function jsonSerialize(): mixed
43 | {
44 | return $this->toArray();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/lib/Components/filepond.scss:
--------------------------------------------------------------------------------
1 | @import "filepond/dist/filepond.css";
2 | @import "filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css";
3 |
4 | .filepond--root {
5 | @apply mb-0;
6 |
7 | .filepond--drop-label {
8 | @apply min-h-[2.625rem];
9 | }
10 | }
11 |
12 | .filepond--panel-root {
13 | @apply bg-white rounded-md border border-gray-300 shadow-sm;
14 | }
15 |
16 | .filepond--drop-label {
17 | @apply text-black justify-start text-gray-500 px-2;
18 | }
19 |
20 | .filepond--item-panel {
21 | @apply bg-indigo-500;
22 | }
23 |
24 | .filepond--file-action-button {
25 | @apply bg-indigo-700;
26 | }
27 |
28 | .filepond--file,
29 | .filepond--item-panel,
30 | .filepond--image-preview-wrapper {
31 | @apply rounded-md;
32 | }
33 |
34 | .filepond--image-preview-overlay-success {
35 | @apply text-gray-900;
36 | }
37 |
38 | .filepond--file-info {
39 | .filepond--file-info-sub {
40 | @apply opacity-75;
41 | }
42 | }
43 |
44 | [data-filepond-item-state*="invalid"] .filepond--item-panel, [data-filepond-item-state*="error"] .filepond--item-panel {
45 | @apply bg-red-500;
46 | }
--------------------------------------------------------------------------------
/resources/views/functional/vue-bridge.blade.php:
--------------------------------------------------------------------------------
1 | @php $vueData = $_vueData() @endphp
2 |
3 | only($vueEvents = ['v-on:success', 'v-on:error', '@@success', '@@error']) }}
5 | :backend-route="@js(route('splade.withVueBridge'))"
6 | :default="@js($vueData['data'])"
7 | :initial-instance="@js($vueData['instance'])"
8 | :initial-signature="@js($vueData['signature'])"
9 | :methods="@js($vueData['methods'])"
10 | :original-url="@js($vueData['url'])"
11 | :verb="@js($vueData['verb'])"
12 | >
13 |
14 | @php($hasAttributes = (string) $attributes ? true : false)
15 |
16 | @if ($hasAttributes)
17 | except($vueEvents) }}>
18 | @endif
19 |
20 | @isset($originalName)
21 | @include($originalName, array_merge($originalData, ['slot' => $slot]))
22 | @else
23 | {{ isset($component) ? $component : $slot }}
24 | @endisset
25 |
26 | @if ($hasAttributes)
27 |
28 | @endif
29 |
30 |
--------------------------------------------------------------------------------
/lib/PreserveScrollDirective.js:
--------------------------------------------------------------------------------
1 | import { nextTick } from "vue";
2 | import { Splade } from "./Splade.js";
3 | import debounce from "lodash-es/debounce";
4 |
5 | export default {
6 | created: (el, binding) => {
7 | if(Splade.isSsr) {
8 | return;
9 | }
10 |
11 | const key = `preserveScroll-${binding.arg}`;
12 |
13 | const scrollPosition = Splade.restore(key);
14 |
15 | if (scrollPosition) {
16 | nextTick(() => {
17 | if (typeof el.scrollTo === "function") {
18 | el.scrollTo(scrollPosition.left, scrollPosition.top);
19 | } else {
20 | el.scrollTop = scrollPosition.top;
21 | el.scrollLeft = scrollPosition.left;
22 | }
23 | });
24 | }
25 |
26 | const rememberScroll = function () {
27 | Splade.remember(key, {
28 | top: el.scrollTop,
29 | left: el.scrollLeft,
30 | });
31 | };
32 |
33 | el.addEventListener("scroll", debounce(rememberScroll, 100));
34 |
35 | rememberScroll();
36 | }
37 | };
--------------------------------------------------------------------------------
/stubs/routes/web.php:
--------------------------------------------------------------------------------
1 | group(function () {
17 | Route::get('/', fn () => view('home'))->name('home');
18 | Route::get('/docs', fn () => view('docs'))->name('docs');
19 |
20 | // Registers routes to support the interactive components...
21 | Route::spladeWithVueBridge();
22 |
23 | // Registers routes to support password confirmation in Form and Link components...
24 | Route::spladePasswordConfirmation();
25 |
26 | // Registers routes to support Table Bulk Actions and Exports...
27 | Route::spladeTable();
28 |
29 | // Registers routes to support async File Uploads with Filepond...
30 | Route::spladeUploads();
31 | });
32 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) protonemedia
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/FormBuilder/Number.php:
--------------------------------------------------------------------------------
1 | attributes['min'] = $value;
17 |
18 | return $this;
19 | }
20 |
21 | /**
22 | * Set the max-value
23 | *
24 | * @return $this
25 | */
26 | public function maxValue(int $value): self
27 | {
28 | $this->attributes['max'] = $value;
29 |
30 | return $this;
31 | }
32 |
33 | /**
34 | * Set the min-value to 0
35 | *
36 | * @return $this
37 | */
38 | public function unsigned(): self
39 | {
40 | $this->minValue(0);
41 |
42 | return $this;
43 | }
44 |
45 | /**
46 | * Set the step-size
47 | *
48 | * @param float|int $value
49 | * @return $this
50 | */
51 | public function step($step = 1): self
52 | {
53 | $this->attributes['step'] = $step;
54 |
55 | return $this;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/FileUploads/SpladeFile.php:
--------------------------------------------------------------------------------
1 | file = $file;
16 |
17 | if ($file instanceof UploadedFile) {
18 | $this->upload = $file;
19 | }
20 |
21 | if ($file instanceof ExistingFile) {
22 | $this->existing = $file;
23 | }
24 | }
25 |
26 | /**
27 | * Returns a boolean whether the file exists.
28 | */
29 | public function exists(): bool
30 | {
31 | return $this->file instanceof ExistingFile;
32 | }
33 |
34 | /**
35 | * Returns a boolean whether the file is uploaded.
36 | */
37 | public function doesntExist(): bool
38 | {
39 | return !$this->exists();
40 | }
41 |
42 | /**
43 | * Returns true if the file is uploaded.
44 | */
45 | public function new(): bool
46 | {
47 | return $this->file instanceof UploadedFile;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/TransitionAnimation.php:
--------------------------------------------------------------------------------
1 | name;
28 | }
29 |
30 | /**
31 | * Returns an array with all data.
32 | *
33 | * @return array
34 | */
35 | public function toArray()
36 | {
37 | return [
38 | 'enter' => $this->enter,
39 | 'enter-from' => $this->enterFrom,
40 | 'enter-to' => $this->enterTo,
41 | 'leave' => $this->leave,
42 | 'leave-from' => $this->leaveFrom,
43 | 'leave-to' => $this->leaveTo,
44 | ];
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Components/Form/Radios.php:
--------------------------------------------------------------------------------
1 | SpladeComponent::normalize('group'),
38 | 'radioComponent' => SpladeComponent::normalize('radio'),
39 | ]);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Http/ConfirmPasswordController.php:
--------------------------------------------------------------------------------
1 | recentlyConfirmed($request)) {
18 | return response()->noContent(200)->skipSpladeMiddleware();
19 | }
20 |
21 | throw ValidationException::withMessages([
22 | 'password' => __('The password confirmation has expired.'),
23 | ]);
24 | }
25 |
26 | /**
27 | * Confirm the given user's password.
28 | */
29 | public function store(Request $request, PasswordValidator $passwordValidator): Response
30 | {
31 | $passwordValidator->validateRequest($request, 'password');
32 |
33 | $request->session()->put('auth.password_confirmed_at', time());
34 |
35 | return response()->noContent(200)->skipSpladeMiddleware();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/resources/views/components/dropdown.blade.php:
--------------------------------------------------------------------------------
1 | except('class')
2 | ->mergeVueBinding(':inline', $inline)
3 | ->mergeVueBinding(':teleport', $teleport)
4 | ->mergeVueBinding(':close-on-click', $closeOnClick)
5 | }} :splade-id="@js($spladeId)">
6 |
7 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | {{ $slot }}
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/Components/Lazy.php:
--------------------------------------------------------------------------------
1 | passthrough = implode(',', Form::splitByComma($passthrough));
23 | }
24 |
25 | /**
26 | * Get the view / contents that represent the component.
27 | *
28 | * @return \Illuminate\Contracts\View\View|\Closure|string
29 | */
30 | public function render()
31 | {
32 | $key = $this->splade->newLazyComponentKey();
33 |
34 | return $this->splade->isLazyRequest()
35 | ? implode([
36 | '',
37 | '{{ $slot }}',
38 | '',
39 | ]) : view('splade::functional.lazy', [
40 | 'name' => $key,
41 | ]);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Components/Form/Checkbox.php:
--------------------------------------------------------------------------------
1 |
2 | mergeVueBinding(':close-button', $closeButton) }} :name="@js($name)">
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
18 |
19 | {{ $slot }}
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/Facades/SEO.php:
--------------------------------------------------------------------------------
1 | listeners = $this->parseListeners($listen);
22 | }
23 |
24 | /**
25 | * Parses the given 'listen' attribute.
26 | *
27 | * @return void
28 | */
29 | private function parseListeners(mixed $listen)
30 | {
31 | if (!is_string($listen)) {
32 | return $this->parseJsonData($listen);
33 | }
34 |
35 | return collect(explode(',', $listen))
36 | ->map(fn ($key) => trim($key))
37 | ->all();
38 | }
39 |
40 | /**
41 | * Get the view / contents that represent the component.
42 | *
43 | * @return \Illuminate\Contracts\View\View|\Closure|string
44 | */
45 | public function render()
46 | {
47 | return view('splade::functional.event');
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Commands/SsrTestCommand.php:
--------------------------------------------------------------------------------
1 | info('Testing SSR server: ' . config('splade.ssr.server'));
24 |
25 | $dataTag = SpladeComponent::tag('data');
26 |
27 | $result = (new Ssr)->render(
28 | components: '',
29 | html: Blade::render("<{$dataTag}>Test
{$dataTag}>"),
30 | dynamics: [],
31 | splade: SpladeResponseData::make()
32 | );
33 |
34 | if (Str::contains($result['body'] ?? '', 'Test
')) {
35 | $this->info('OK');
36 |
37 | return static::SUCCESS;
38 | }
39 |
40 | $this->error('Wrong response.');
41 |
42 | return static::FAILURE;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/lib/Components/Toast.vue:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/Components/DataStores.php:
--------------------------------------------------------------------------------
1 | keyBy->name;
31 |
32 | $this->scopes = $stores->map->name->implode(',');
33 | $this->remember = $stores->filter->remember->keys()->all();
34 | $this->localStorage = $stores->filter->localStorage->keys()->all();
35 |
36 | $this->parsed = (object) $stores->reject->json->map->data->all();
37 | $this->raw = (object) $stores->map->json->filter()->all();
38 | }
39 |
40 | /**
41 | * Get the view / contents that represent the component.
42 | *
43 | * @return \Illuminate\Contracts\View\View|\Closure|string
44 | */
45 | public function render()
46 | {
47 | return view('splade::functional.dataStores');
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/resources/views/functional/form-builder.blade.php:
--------------------------------------------------------------------------------
1 | getClass())
7 |
8 | :confirm="$form->getOption('confirm')"
9 | :confirm-danger="$form->getOption('confirm_danger')"
10 | :confirm-text="$form->getOption('text')"
11 | :confirm-button="$form->getOption('confirm_button')"
12 | :cancel-button="$form->getOption('cancel_button')"
13 | :require-password="$form->getOption('require_password')"
14 | :require-password-once="$form->getOption('require_password_once')"
15 |
16 | :submit-on-change="$form->getOption('submit_on_change')"
17 | :background="$form->getOption('background')"
18 | :debounce="$form->getOption('debounce')"
19 |
20 | :stay="$form->getOption('stay')"
21 | :reset-on-success="$form->getOption('reset_on_success')"
22 | :restore-on-success="$form->getOption('restore_on_success')"
23 |
24 | :preserve-scroll="$form->getOption('preserve_scroll')"
25 | :blob="$form->getOption('blob')"
26 |
27 | {{ $attributes->rejectWhenBlank('id')->except('class') }}
28 | >
29 | @foreach($form->getFields() as $field)
30 | {!! $field->render() !!}
31 | @endforeach
32 |
33 | {{ $slot ?? '' }}
34 |
35 |
--------------------------------------------------------------------------------
/src/Commands/PublishFormStylesheetsCommand.php:
--------------------------------------------------------------------------------
1 | ensureDirectoryExists(resource_path('css'));
21 |
22 | copy(__DIR__ . '/../../lib/Components/choices.scss', resource_path('css/choices.scss'));
23 | copy(__DIR__ . '/../../lib/Components/filepond.scss', resource_path('css/filepond.scss'));
24 | copy(__DIR__ . '/../../lib/Components/flatpickr.styl', resource_path('css/flatpickr.styl'));
25 | copy(__DIR__ . '/../../lib/Components/jodit.scss', resource_path('css/jodit.scss'));
26 |
27 | $this->comment('All done');
28 |
29 | $this->comment('Please install the required pre-processors with "npm add -D sass stylus", and import the published stylesheet in "app.js".');
30 |
31 | return self::SUCCESS;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Components/Form/Checkboxes.php:
--------------------------------------------------------------------------------
1 | SpladeComponent::normalize('group'),
43 | 'checkboxComponent' => SpladeComponent::normalize('checkbox'),
44 | ]);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Components/ParsesJsonDataAttribute.php:
--------------------------------------------------------------------------------
1 | toJson(), true);
30 | }
31 |
32 | if ($data instanceof JsonSerializable) {
33 | return json_decode(json_encode($data), true);
34 | }
35 |
36 | if ($data instanceof Arrayable) {
37 | return $data->toArray();
38 | }
39 |
40 | if (is_array($data)) {
41 | return $data;
42 | }
43 |
44 | $decoded = rescue(fn () => json_decode($data, true), null, false);
45 |
46 | if ($decoded) {
47 | return $decoded;
48 | }
49 |
50 | return null;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/FormSelectOption.php:
--------------------------------------------------------------------------------
1 | attributes);
23 | }
24 |
25 | /**
26 | * Returns the options array from the attributes.
27 | */
28 | public function getOptions(): array
29 | {
30 | return $this->attributes['options'] ?? [];
31 | }
32 |
33 | /**
34 | * Returns a new ComponentAttributeBag instance with the
35 | * attributes, except the options as we don't want to
36 | * render those as an attribute.
37 | */
38 | public function attributes(): ComponentAttributeBag
39 | {
40 | return (new ComponentAttributeBag($this->attributes))->except('options');
41 | }
42 |
43 | /**
44 | * Returns the attributes as an array.
45 | *
46 | * @return array
47 | */
48 | public function toArray()
49 | {
50 | return $this->attributes()->getAttributes();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Facades/Toast.php:
--------------------------------------------------------------------------------
1 | validate([
18 | 'ids' => ['required', 'array', 'min:1'],
19 | ]);
20 |
21 | $action = base64_decode($action);
22 |
23 | /** @var AbstractTable $tableInstance */
24 | $tableInstance = app(base64_decode($table));
25 |
26 | if (!$tableInstance->authorize($request)) {
27 | throw new UnauthorizedException;
28 | }
29 |
30 | /** @var BulkAction */
31 | $bulkActionInstance = $tableInstance->make()->getBulkActions()[$action];
32 |
33 | if ($bulkActionInstance->requirePassword) {
34 | $passwordValidator->validateRequest($request, $bulkActionInstance->requirePassword);
35 | }
36 |
37 | $tableInstance->performBulkAction($action, $request->input('ids', []));
38 |
39 | return redirect()->back();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Table/Export.php:
--------------------------------------------------------------------------------
1 | label);
30 | }
31 |
32 | /**
33 | * Generates a Signed URL to the export URL.
34 | */
35 | public function getUrl(): string
36 | {
37 | /** @var Route $route */
38 | $route = app('router')->getRoutes()->getByAction(TableExportController::class);
39 |
40 | return URL::signedRoute($route->getName(), array_merge(
41 | Arr::except(request()->query(), 'signature'),
42 | [
43 | 'table' => base64_encode($this->tableClass),
44 | 'export' => base64_encode($this->key),
45 | 'slug' => $this->getSlug(),
46 | ]
47 | ));
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Components/Rehydrate.php:
--------------------------------------------------------------------------------
1 | on = Form::splitByComma($on);
24 | }
25 |
26 | $this->passthrough = implode(',', Form::splitByComma($passthrough));
27 | }
28 |
29 | /**
30 | * Get the view / contents that represent the component.
31 | *
32 | * @return \Illuminate\Contracts\View\View|\Closure|string
33 | */
34 | public function render()
35 | {
36 | $key = $this->splade->newRehydrateComponentKey();
37 |
38 | return $this->splade->isRehydrateRequest()
39 | ? implode([
40 | '',
41 | '{{ $slot }}',
42 | '',
43 | ]) : view('splade::functional.rehydrate', [
44 | 'name' => $key,
45 | 'on' => $this->on,
46 | ]);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Http/FileUploadController.php:
--------------------------------------------------------------------------------
1 | validate([
19 | 'file' => ['required', 'file'],
20 | ]);
21 |
22 | $temporaryFileUpload = $filesystem->storeUploadedFileTemporarely($request->file('file'));
23 |
24 | return response($temporaryFileUpload->encryptAttributes())->skipSpladeMiddleware();
25 | }
26 |
27 | /**
28 | * Decrypt the requested path and delete the file.
29 | */
30 | public function delete(Request $request, Filesystem $filesystem): Response
31 | {
32 | $request->validate([
33 | 'file' => ['required', 'string'],
34 | ]);
35 |
36 | $temporaryFileUpload = TemporaryFileUpload::fromEncryptedString($request->input('file'));
37 |
38 | if ($temporaryFileUpload) {
39 | $filesystem->delete($temporaryFileUpload);
40 | }
41 |
42 | return response()->noContent()->skipSpladeMiddleware();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Commands/stubs/splade.table.stub:
--------------------------------------------------------------------------------
1 | withGlobalSearch(columns: ['id'])
52 | ->column('id', sortable: true);
53 |
54 | // ->searchInput()
55 | // ->selectFilter()
56 | // ->withGlobalSearch()
57 |
58 | // ->bulkAction()
59 | // ->export()
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/Components/Link.php:
--------------------------------------------------------------------------------
1 | parseJsonData($data);
27 |
28 | if ($parsed) {
29 | $this->data = $parsed;
30 | } else {
31 | $this->jsonData = $data ?: '{}';
32 | }
33 |
34 | //
35 |
36 | $parsed = $this->parseJsonData($headers);
37 |
38 | if ($parsed) {
39 | $this->headers = $parsed;
40 | } else {
41 | $this->jsonHeaders = $headers ?: '{}';
42 | }
43 | }
44 |
45 | /**
46 | * Get the view / contents that represent the component.
47 | *
48 | * @return \Illuminate\Contracts\View\View|\Closure|string
49 | */
50 | public function render()
51 | {
52 | return view('splade::functional.link', [
53 | 'data' => $this->data,
54 | 'jsonData' => $this->jsonData,
55 | 'headers' => $this->headers,
56 | 'jsonHeaders' => $this->jsonHeaders,
57 | ]);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/config/splade-seo.php:
--------------------------------------------------------------------------------
1 | [
16 | 'title' => env('APP_NAME', 'Laravel Splade'),
17 | 'description' => 'Splade provides a super easy way to build Single Page Applications (SPA) using standard Laravel Blade templates, enhanced with renderless Vue 3 components.',
18 | 'keywords' => ['Laravel', 'Splade'],
19 | ],
20 |
21 | 'title_prefix' => '',
22 | 'title_separator' => '',
23 | 'title_suffix' => '',
24 |
25 | 'auto_canonical_link' => true,
26 |
27 | 'open_graph' => [
28 | 'auto_fill' => false,
29 | 'image' => null,
30 | 'site_name' => null,
31 | 'title' => null,
32 | 'type' => null, // 'WebPage'
33 | 'url' => null,
34 | ],
35 |
36 | 'twitter' => [
37 | 'auto_fill' => false,
38 | 'card' => null, // 'summary_large_image',
39 | 'description' => null,
40 | 'image' => null,
41 | 'site' => null, // '@username',
42 | 'title' => null,
43 | ],
44 |
45 | ];
46 |
--------------------------------------------------------------------------------
/src/Components/Form/Textarea.php:
--------------------------------------------------------------------------------
1 | static::$defaultAutosize,
51 | ]);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/Components/SerializesNewModels.php:
--------------------------------------------------------------------------------
1 | exists) {
21 | return $value;
22 | }
23 |
24 | if ($value instanceof Collection
25 | && $value instanceof QueueableCollection
26 | && $value->first(fn ($model) => !$model->exists)
27 | ) {
28 | return QueueableCollectionWithNewModels::from($value);
29 | }
30 |
31 | return $this->getSerializedPropertyValueTrait($value);
32 | }
33 |
34 | protected function getRestoredPropertyValue($value)
35 | {
36 | if ($value instanceof Model && !$value->exists) {
37 | return $value;
38 | }
39 |
40 | if ($value instanceof QueueableCollectionWithNewModels) {
41 | return $value->restore();
42 | }
43 |
44 | return $this->getRestoredPropertyValueTrait($value);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Components/Form/Submit.php:
--------------------------------------------------------------------------------
1 | primary = !$this->danger && !$this->secondary;
33 | }
34 |
35 | /**
36 | * Get the view / contents that represent the component.
37 | *
38 | * @return \Illuminate\Contracts\View\View|\Closure|string
39 | */
40 | public function render()
41 | {
42 | return view('splade::form.submit');
43 | }
44 |
45 | /**
46 | * Returns a boolean whether there are background or text classes.
47 | */
48 | public function hasCustomStyling(ComponentAttributeBag $attributes): bool
49 | {
50 | return Button::hasCustomStyling($attributes);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Components/Transition.php:
--------------------------------------------------------------------------------
1 | animate = $animate ? 'true' : 'false';
26 | }
27 | }
28 |
29 | /**
30 | * Get the view / contents that represent the component.
31 | *
32 | * @return \Illuminate\Contracts\View\View|\Closure|string
33 | */
34 | public function render()
35 | {
36 | $transitionRepository = app(TransitionRepository::class);
37 |
38 | return view('splade::functional.transition', [
39 | 'animation' => $transitionRepository->get($this->animation),
40 | 'child' => $this->child,
41 | 'show' => $this->show,
42 | 'appear' => $this->appear,
43 | 'unmount' => $this->unmount,
44 | 'afterLeave' => $this->afterLeave,
45 | 'animate' => $this->animate,
46 | ]);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Components/Toggle.php:
--------------------------------------------------------------------------------
1 | toggles = collect(explode(',', $data))
22 | ->map(fn ($key) => trim($key))
23 | ->filter()
24 | ->mapWithKeys(fn ($key) => [$key => false])
25 | ->all();
26 | } elseif (is_bool($data)) {
27 | $this->toggles = ['default' => $data];
28 | } else {
29 | $this->toggles = $this->parseJsonData($data) ?: ['default' => false];
30 | }
31 | }
32 |
33 | /**
34 | * Get the view / contents that represent the component.
35 | *
36 | * @return \Illuminate\Contracts\View\View|\Closure|string
37 | */
38 | public function render()
39 | {
40 | $toggles = collect($this->toggles)->keys();
41 |
42 | return view('splade::functional.toggle', [
43 | 'props' => $toggles->all() === ['default']
44 | ? implode(', ', ['toggle', 'setToggle', 'toggled'])
45 | : collect($this->toggles)->keys()->merge([
46 | 'toggle', 'setToggle', 'toggled',
47 | ])->implode(', '),
48 | ]);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/lib/Components/Toasts.vue:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/Components/FormHelpers.js:
--------------------------------------------------------------------------------
1 | // The methods in this file are completely stolen from Inertia.js:
2 | // https://github.com/inertiajs/inertia/tree/master/packages/inertia/src
3 |
4 | export function objectToFormData(source, form, parentKey) {
5 | source = source || {};
6 | form = form || new FormData();
7 | parentKey = parentKey || null;
8 |
9 | for (const key in source) {
10 | if (Object.prototype.hasOwnProperty.call(source, key)) {
11 | append(form, composeKey(parentKey, key), source[key]);
12 | }
13 | }
14 |
15 | return form;
16 | }
17 |
18 | function composeKey(parent, key) {
19 | return parent ? parent + "[" + key + "]" : key;
20 | }
21 |
22 | function append(form, key, value) {
23 | if (Array.isArray(value)) {
24 | return Array.from(value.keys()).forEach(index => append(form, composeKey(key, index.toString()), value[index]));
25 | } else if (value instanceof Date) {
26 | return form.append(key, value.toISOString());
27 | } else if (value instanceof File) {
28 | return form.append(key, value, value.name);
29 | } else if (value instanceof Blob) {
30 | return form.append(key, value);
31 | } else if (typeof value === "boolean") {
32 | return form.append(key, value ? "1" : "0");
33 | } else if (typeof value === "string") {
34 | return form.append(key, value);
35 | } else if (typeof value === "number") {
36 | return form.append(key, `${value}`);
37 | } else if (value === null || value === undefined) {
38 | return form.append(key, "");
39 | }
40 |
41 | objectToFormData(value, form, key);
42 | }
--------------------------------------------------------------------------------
/src/Components/Button.php:
--------------------------------------------------------------------------------
1 | primary = !$this->danger && !$this->secondary;
31 | }
32 |
33 | /**
34 | * Get the view / contents that represent the component.
35 | *
36 | * @return \Illuminate\Contracts\View\View|\Closure|string
37 | */
38 | public function render()
39 | {
40 | return view('splade::components.button');
41 | }
42 |
43 | /**
44 | * Returns a boolean whether there are background or text classes.
45 | */
46 | public static function hasCustomStyling(ComponentAttributeBag $attributes): bool
47 | {
48 | $backgroundOrTextClasses = array_filter(explode(' ', $attributes->get(key: 'class', default: '')), function ($class) {
49 | return Str::contains($class, ['bg-', 'text-']);
50 | });
51 |
52 | return !empty($backgroundOrTextClasses);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/TestStubs.php:
--------------------------------------------------------------------------------
1 | get(), 1000);
53 |
54 | $needles = [
55 | '
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/lib/server.js:
--------------------------------------------------------------------------------
1 | function startServer(createServer, renderToString, createApp) {
2 | const args = {};
3 |
4 | // Parse the CLI arguments
5 | process.argv.slice(2).forEach((argument) => {
6 | const splitted = argument.replace(/^-+/, "").split("=");
7 |
8 | args[splitted[0]] = (splitted.length === 2) ? splitted[1] : true;
9 | });
10 |
11 | // Listen to port 9000 by default
12 | const port = args.port || 9000;
13 |
14 | createServer(async (request, response) => {
15 | if (request.method == "POST") {
16 | let data = "";
17 | request.on("data", (chunk) => (data += chunk));
18 | request.on("end", async () => {
19 | // This is the same JSON data that is on the initial
20 | // request in the Vue app data-* attributes.
21 | const json = JSON.parse(data);
22 |
23 | const app = createApp({
24 | components: json.components,
25 | initialDynamics: json.dynamics,
26 | initialHtml: json.html,
27 | initialSpladeData: json.splade
28 | });
29 |
30 | // Let Vue render the app and return the
31 | // rendered content as a JSON object.
32 | const body = await renderToString(app);
33 |
34 | response.writeHead(200, { "Content-Type": "application/json", "Server": "Splade SSR" });
35 | response.write(JSON.stringify({ body }));
36 | response.end();
37 | });
38 | }
39 | }).listen(port, () => console.log(`Splade SSR server started on port ${port}.`));
40 | }
41 |
42 | export { startServer };
--------------------------------------------------------------------------------
/src/Table/HasExports.php:
--------------------------------------------------------------------------------
1 | exports;
18 | }
19 |
20 | /**
21 | * Returns a boolean whether this table has exports.
22 | */
23 | public function hasExports(): bool
24 | {
25 | return !empty($this->exports);
26 | }
27 |
28 | /**
29 | * Adds an export.
30 | *
31 | * @return $this
32 | */
33 | public function export(
34 | ?string $label = null,
35 | ?string $filename = null,
36 | ?string $type = null,
37 | array $events = [],
38 | ): self {
39 | if (!class_exists(Excel::class)) {
40 | throw new LaravelExcelException(
41 | "To generate exports from a Splade Table, please install the 'maatwebsite/excel' package."
42 | );
43 | }
44 |
45 | if ($filename === null) {
46 | $filename = $this->configurator
47 | ? Str::slug(class_basename($this->configurator)) . '.xlsx'
48 | : 'export.xlsx';
49 | }
50 |
51 | $key = count($this->exports);
52 |
53 | $this->exports[$key] = new Export(
54 | key: $key,
55 | label: $label ?: __('Excel Export'),
56 | filename: $filename,
57 | type: $type ?: Excel::XLSX,
58 | tableClass: get_class($this->configurator),
59 | events: $events,
60 | );
61 |
62 | return $this;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/lib/Components/JoditEditor.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
67 |
--------------------------------------------------------------------------------
/src/Components/Data.php:
--------------------------------------------------------------------------------
1 | parseJsonData($default);
30 |
31 | if ($parsed) {
32 | $this->data = $parsed;
33 | } else {
34 | $this->json = $default ?: '{}';
35 | }
36 |
37 | if ($remember === true && $store) {
38 | $this->remember = $store;
39 | }
40 | }
41 |
42 | /**
43 | * Get the view / contents that represent the component.
44 | *
45 | * @return \Illuminate\Contracts\View\View|\Closure|string
46 | */
47 | public function render()
48 | {
49 | if ($this->store) {
50 | Splade::addDataStore(new DataStore(
51 | name: $this->store,
52 | remember: $this->remember,
53 | localStorage: $this->localStorage,
54 | data: $this->data,
55 | json: $this->json,
56 | ));
57 |
58 | return '';
59 | }
60 |
61 | return view('splade::functional.data', [
62 | 'data' => $this->data,
63 | 'json' => $this->json,
64 | ]);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/lib/Components/DataStores.vue:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/views/form/submit.blade.php:
--------------------------------------------------------------------------------
1 | @php $customStyling = $hasCustomStyling($attributes) @endphp
2 |
3 |
4 |
31 |
32 |
--------------------------------------------------------------------------------
/resources/views/table/select-rows-dropdown.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
18 |
19 | @if($showPaginator())
20 |
26 | @endif
27 |
28 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/lib/ServerError.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
10 |
11 |
12 |
13 |
69 |
--------------------------------------------------------------------------------
/lib/Components/Lazy.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
83 |
--------------------------------------------------------------------------------
/resources/views/table/table.blade.php:
--------------------------------------------------------------------------------
1 | except('class') }}
2 | :striped="@js($striped)"
3 | :columns="@js($table->columns())"
4 | :search-debounce="@js($searchDebounce)"
5 | :default-visible-toggleable-columns="@js($table->defaultVisibleToggleableColumns())"
6 | :items-on-this-page="@js($table->totalOnThisPage())"
7 | :items-on-all-pages="@js($table->totalOnAllPages())"
8 | :base-url="@js(request()->url())"
9 | :pagination-scroll="@js($paginationScroll)"
10 | :splade-id="@js($spladeId = $table->getSpladeId())"
11 | >
12 |
13 | only('class') }} :class="{ 'opacity-50': table.isLoading }" data-splade-id="{{ $spladeId }}">
14 | @if($hasControls())
15 | @include('splade::table.controls')
16 | @endif
17 |
18 | @foreach($table->searchInputs() as $searchInput)
19 | @includeUnless($searchInput->key === 'global', 'splade::table.search-row')
20 | @endforeach
21 |
22 |
23 |
24 | @unless($headless)
25 | @isset($head)
26 | {{ $head }}
27 | @elseif(count($table->resource))
28 | @include('splade::table.head')
29 | @endisset
30 | @endunless
31 |
32 | @isset($body)
33 | {{ $body }}
34 | @else
35 | @include('splade::table.body')
36 | @endisset
37 |
38 |
39 |
40 | @if($showPaginator())
41 | {{ $table->resource->links($paginationView, ['table' => $table, 'hasPerPageOptions' => $hasPerPageOptions()]) }}
42 | @endif
43 |
44 |
45 |
--------------------------------------------------------------------------------
/resources/views/components/toast-wrapper.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 |
25 |
26 |
27 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/resources/views/table/filters.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
18 | @foreach($table->filters() as $filter)
19 |
20 |
21 | {{ $filter->label }}
22 |
23 |
24 |
25 | @if($filter->type === 'select')
26 |
37 | @endif
38 |
39 |
40 | @endforeach
41 |
42 |
--------------------------------------------------------------------------------
/resources/views/table/simple-pagination.blade.php:
--------------------------------------------------------------------------------
1 |
26 |
--------------------------------------------------------------------------------
/src/Table/Filter.php:
--------------------------------------------------------------------------------
1 | key,
30 | $this->label,
31 | $this->options,
32 | $this->value,
33 | $this->noFilterOption,
34 | $this->noFilterOptionLabel,
35 | $this->type
36 | );
37 | }
38 |
39 | /**
40 | * Returns a boolean whether the value is not null.
41 | */
42 | public function hasValue(): bool
43 | {
44 | return !is_null($this->value);
45 | }
46 |
47 | /**
48 | * Returns the options array, and if set, prepends
49 | * a 'no filter' option to the options array.
50 | */
51 | public function options(): array
52 | {
53 | $options = $this->options;
54 |
55 | if ($this->noFilterOption) {
56 | $options = Arr::prepend($options, $this->noFilterOptionLabel, '');
57 | }
58 |
59 | return $options;
60 | }
61 |
62 | /**
63 | * Returns an array with all properties.
64 | *
65 | * @return array
66 | */
67 | public function toArray()
68 | {
69 | return [
70 | 'key' => $this->key,
71 | 'label' => $this->label,
72 | 'options' => $this->options(),
73 | 'value' => $this->value,
74 | 'type' => $this->type,
75 | ];
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/FormBuilder/Button.php:
--------------------------------------------------------------------------------
1 | danger = $danger;
31 |
32 | return $this;
33 | }
34 |
35 | /**
36 | * Add one or more classes to the fields' wrapper.
37 | *
38 | * @param array|string $classes
39 | * @return $this
40 | */
41 | public function wrapperClass(...$classes): self
42 | {
43 | $classes = Arr::flatten($classes);
44 |
45 | $this->wrapperClass = Arr::toCssClasses($classes);
46 |
47 | return $this;
48 | }
49 |
50 | /**
51 | * Applies secondary-styling to the button.
52 | *
53 | * @return $this
54 | */
55 | public function secondary(bool $secondary = true): self
56 | {
57 | $this->secondary = $secondary;
58 |
59 | return $this;
60 | }
61 |
62 | /**
63 | * Renders the SpladeButton
64 | *
65 | * @return \Closure|\Illuminate\Contracts\View\View|string
66 | */
67 | public function toSpladeComponent()
68 | {
69 | return new SpladeSubmit(
70 | label: $this->label,
71 | type: $this->type,
72 | spinner: $this->spinner,
73 | name: $this->name,
74 | value: $this->value ?? null,
75 | danger: $this->danger,
76 | secondary: $this->secondary,
77 | wrapperClass: $this->wrapperClass
78 | );
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/Meta.php:
--------------------------------------------------------------------------------
1 | attributes)->map(function ($value, $key) {
24 | $value = e($value);
25 |
26 | return "{$key}=\"{$value}\"";
27 | })->implode(' ');
28 |
29 | return "";
30 | }
31 |
32 | /**
33 | * Returns a boolean whether the given attributes match.
34 | */
35 | public function hasAllAttributes(array $attributes): bool
36 | {
37 | foreach ($attributes as $key => $value) {
38 | if (!array_key_exists($key, $this->attributes)) {
39 | return false;
40 | }
41 |
42 | if ($this->attributes[$key] !== $value) {
43 | return false;
44 | }
45 | }
46 |
47 | return true;
48 | }
49 |
50 | /**
51 | * Returns an array with all attributes.
52 | */
53 | public function toArray(): array
54 | {
55 | return Collection::make($this->attributes)
56 | ->mapWithKeys(function ($value, $key) {
57 | return [$key => e($value)];
58 | })
59 | ->all();
60 | }
61 |
62 | /**
63 | * Returns the array from the 'toArray' method.
64 | *
65 | * @return array
66 | */
67 | public function jsonSerialize(): mixed
68 | {
69 | return $this->toArray();
70 | }
71 |
72 | /**
73 | * Dynamic getter for the attributes.
74 | *
75 | * @return mixed
76 | */
77 | public function __get(string $key)
78 | {
79 | return $this->attributes[$key] ?? null;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/lib/Components/OnClickOutside.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@protonemedia/laravel-splade",
3 | "version": "1.4.21",
4 | "description": "Laravel Splade: the magic of Inertia.js with the simplicity of Blade.",
5 | "private": false,
6 | "author": "Pascal Baljet ",
7 | "license": "MIT",
8 | "type": "module",
9 | "main": "./dist/protone-media-laravel-splade.umd.cjs",
10 | "module": "./dist/protone-media-laravel-splade.js",
11 | "files": [
12 | "dist/CompilerErrorMessages*",
13 | "dist/jodit.css",
14 | "dist/protone-media-laravel-splade.cjs",
15 | "dist/protone-media-laravel-splade.js",
16 | "dist/style.css"
17 | ],
18 | "exports": {
19 | ".": {
20 | "import": "./dist/protone-media-laravel-splade.js",
21 | "require": "./dist/protone-media-laravel-splade.umd.cjs"
22 | },
23 | "./dist/style.css": "./dist/style.css",
24 | "./dist/jodit.css": "./dist/jodit.css"
25 | },
26 | "scripts": {
27 | "dev": "vite build --watch",
28 | "build": "vite build",
29 | "eslint": "./node_modules/.bin/eslint app/resources/js/ lib/ stubs/ --ext .js,.vue --fix",
30 | "pre-publish": "composer extract-transitions && npm upgrade && vite build && npm pack"
31 | },
32 | "peerDependencies": {
33 | "axios": "^0.27 || ^1.1.2",
34 | "vue": "^3.2.47"
35 | },
36 | "devDependencies": {
37 | "@headlessui/vue": "1.7.13",
38 | "@popperjs/core": "^2.11.5",
39 | "@vitejs/plugin-vue": "^4.1.0",
40 | "eslint": "^8.20.0",
41 | "eslint-plugin-vue": "^9.2.0",
42 | "lodash-es": "^4.17.21",
43 | "sass": "^1.54.4",
44 | "stylus": "^0.59.0",
45 | "vite": "^4.2.0"
46 | },
47 | "dependencies": {
48 | "autosize": "^5.0.1",
49 | "choices.js": "^10.1.0",
50 | "filepond": "^4.30.4",
51 | "filepond-plugin-file-validate-size": "^2.2.7",
52 | "filepond-plugin-file-validate-type": "^1.2.8",
53 | "filepond-plugin-image-exif-orientation": "^1.0.11",
54 | "filepond-plugin-image-preview": "^4.6.11",
55 | "filepond-plugin-image-validate-size": "^1.2.7",
56 | "flatpickr": "^4.6.13",
57 | "jodit": "^3.24.9",
58 | "nprogress": "^0.2.0"
59 | }
60 | }
--------------------------------------------------------------------------------
/src/FileUploads/TemporaryFileUpload.php:
--------------------------------------------------------------------------------
1 | identifier = $identifier ?: Str::random();
18 | }
19 |
20 | /**
21 | * Decrypts the string and returns a new instance, or null if the string is invalid.
22 | */
23 | public static function fromEncryptedString(string $value): ?static
24 | {
25 | $data = rescue(fn () => decrypt($value), null, false);
26 |
27 | if (!is_array($data)) {
28 | return null;
29 | }
30 |
31 | if (!array_key_exists('splade_temporary_file_upload', $data)) {
32 | return null;
33 | }
34 |
35 | return new static(
36 | $data['path'],
37 | $data['name'],
38 | $data['mime'],
39 | $data['identifier'],
40 | );
41 | }
42 |
43 | /**
44 | * Returns the path to the file.
45 | */
46 | public function getPath(): string
47 | {
48 | return $this->path;
49 | }
50 |
51 | /**
52 | * Returns the name of the file.
53 | */
54 | public function getName(): string
55 | {
56 | return $this->name;
57 | }
58 |
59 | /**
60 | * Returns the mime type of the file.
61 | */
62 | public function getMime(): string
63 | {
64 | return $this->mime;
65 | }
66 |
67 | /**
68 | * Returns the attributes as an encrypted string.
69 | */
70 | public function encryptAttributes(): string
71 | {
72 | return encrypt([
73 | 'splade_temporary_file_upload' => true,
74 |
75 | 'path' => $this->path,
76 | 'name' => $this->name,
77 | 'mime' => $this->mime,
78 | 'identifier' => $this->identifier,
79 | ]);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/lib/Components/Data.vue:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/AbstractForm.php:
--------------------------------------------------------------------------------
1 | build();
32 | }
33 |
34 | /**
35 | * Creates a new SpladeForm instance from the 'build()' method of this class.
36 | */
37 | public function build(): SpladeForm
38 | {
39 | if ($this->for) {
40 | return $this->for;
41 | }
42 |
43 | return $this->for = tap(
44 | SpladeForm::make($this->fields()),
45 | function (SpladeForm $form) {
46 | $form->setConfigurator($this);
47 | $this->configure($form);
48 | }
49 | );
50 | }
51 |
52 | /**
53 | * Configure the given SpladeForm.
54 | *
55 | * @param SpladeForm $table
56 | * @return void
57 | */
58 | public function configure(SpladeForm $form)
59 | {
60 | //
61 | }
62 |
63 | /**
64 | * Get the rules that are configured for the form.
65 | *
66 | * @param mixed ...$arguments
67 | */
68 | public static function rules(...$arguments): array
69 | {
70 | return self::make(...$arguments)->getRules();
71 | }
72 |
73 | /**
74 | * Validate the request with the rules of the form.
75 | *
76 | * @param mixed ...$params
77 | */
78 | public function validate(?Request $request = null, ...$params): array
79 | {
80 | /** @var Request */
81 | $request = $request ?? request();
82 |
83 | return $this->build()->validate($request, ...$params);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/resources/views/table/controls.blade.php:
--------------------------------------------------------------------------------
1 |
2 | @if($table->hasExports() || $table->hasBulkActions())
3 |
4 | @include('splade::table.bulk-actions-exports')
5 |
6 | @endif
7 |
8 | @if($table->hasFilters())
9 |
10 | @include('splade::table.filters')
11 |
12 | @endif
13 |
14 | @if($table->searchInputs('global'))
15 |
16 | @include('splade::table.global-search')
17 |
18 | @endif
19 |
20 |
33 |
34 | @if($table->hasToggleableSearchInputs())
35 |
36 | @include('splade::table.add-search-row')
37 |
38 | @endif
39 |
40 | @if($table->hasToggleableColumns())
41 |
42 | @include('splade::table.columns')
43 |
44 | @endif
45 |
46 |
--------------------------------------------------------------------------------
/resources/views/components/button.blade.php:
--------------------------------------------------------------------------------
1 | @php $customStyling = $hasCustomStyling($attributes) @endphp
2 |
3 | only(['v-bind:spinner', ':spinner']) }}>
4 |
5 | <{{ $type === 'link' ? 'Link' : 'button' }} :disabled="button.spinner" {{ $attributes->class([
6 | 'border rounded-md shadow-sm font-bold py-2 px-4 focus:outline-none focus:ring focus:ring-opacity-50',
7 | 'bg-indigo-500 hover:bg-indigo-700 text-white border-transparent focus:border-indigo-300 focus:ring-indigo-200' => !$customStyling && $primary,
8 | 'bg-red-500 hover:bg-red-700 text-white border-transparent focus:border-red-700 focus:ring-red-200' => !$customStyling && $danger,
9 | 'bg-white hover:bg-gray-100 text-gray-700 border-gray-300 focus:border-indigo-300 focus:ring-indigo-200' => !$customStyling && $secondary,
10 | ])
11 | ->except(['v-bind:spinner', ':spinner'])
12 | ->merge(['type' => $type])
13 | ->when($name, fn($attr) => $attr->merge(['name' => $name, 'value' => $value])) }}
14 | >
15 | @if(trim($slot))
16 | {{ $slot }}
17 | @else
18 |
19 |
26 |
27 |
28 | {{ $label }}
29 |
30 |
31 | @endif
32 | {{ $type === 'link' ? 'Link' : 'button' }}>
33 |
34 |
--------------------------------------------------------------------------------
/src/Http/SpladeResponseData.php:
--------------------------------------------------------------------------------
1 | $this->head,
48 | 'modal' => $this->modal,
49 | 'modalTarget' => $this->modalTarget,
50 | 'flash' => $this->flash,
51 | 'errors' => $this->errors,
52 | 'shared' => $this->shared,
53 | 'toasts' => $this->toasts,
54 | 'preventRefresh' => $this->preventRefresh,
55 | 'preventViewTransition' => $this->preventViewTransition,
56 | 'preserveScroll' => $this->preserveScroll,
57 | 'lazy' => $this->lazy,
58 | 'rehydrate' => $this->rehydrate,
59 | 'persistentLayout' => $this->persistentLayout,
60 | ];
61 | }
62 | }
63 |
--------------------------------------------------------------------------------