diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 8fa85ce..8511f77 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -1,7 +1,7 @@ name: Bug Report description: Report an Issue or Bug with the Package -title: "[Bug]: " -labels: ["bug"] +title: '[Bug]: ' +labels: ['bug'] body: - type: markdown attributes: diff --git a/.github/workflows/fix-php-code-style-issues.yml b/.github/workflows/fix-php-code-style-issues.yml index 756a961..5a2daaa 100644 --- a/.github/workflows/fix-php-code-style-issues.yml +++ b/.github/workflows/fix-php-code-style-issues.yml @@ -1,4 +1,4 @@ -name: "Fix PHP Code Styling" +name: 'Fix PHP Code Styling' on: push: diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml index ec40921..5f214d8 100644 --- a/.github/workflows/update-changelog.yml +++ b/.github/workflows/update-changelog.yml @@ -1,4 +1,4 @@ -name: "Update Changelog" +name: 'Update Changelog' on: release: diff --git a/bin/build.js b/bin/build.js index 94a3cbc..59286d6 100755 --- a/bin/build.js +++ b/bin/build.js @@ -25,22 +25,31 @@ const defaultOptions = { treeShaking: true, target: ['es2020'], minify: !isDev, - plugins: [{ - name: 'watchPlugin', - setup: function (build) { - build.onStart(() => { - console.log(`Build started at ${new Date(Date.now()).toLocaleTimeString()}: ${build.initialOptions.outfile}`) - }) + plugins: [ + { + name: 'watchPlugin', + setup: function (build) { + build.onStart(() => { + console.log( + `Build started at ${new Date(Date.now()).toLocaleTimeString()}: ${build.initialOptions.outfile}`, + ) + }) - build.onEnd((result) => { - if (result.errors.length > 0) { - console.log(`Build failed at ${new Date(Date.now()).toLocaleTimeString()}: ${build.initialOptions.outfile}`, result.errors) - } else { - console.log(`Build finished at ${new Date(Date.now()).toLocaleTimeString()}: ${build.initialOptions.outfile}`) - } - }) - } - }], + build.onEnd((result) => { + if (result.errors.length > 0) { + console.log( + `Build failed at ${new Date(Date.now()).toLocaleTimeString()}: ${build.initialOptions.outfile}`, + result.errors, + ) + } else { + console.log( + `Build finished at ${new Date(Date.now()).toLocaleTimeString()}: ${build.initialOptions.outfile}`, + ) + } + }) + }, + }, + ], } compile({ diff --git a/composer.json b/composer.json index 6185387..83d210b 100644 --- a/composer.json +++ b/composer.json @@ -68,4 +68,4 @@ }, "minimum-stability": "dev", "prefer-stable": true -} \ No newline at end of file +} diff --git a/database/migrations/create_menus_table.php.stub b/database/migrations/create_menus_table.php.stub index 28d49f2..094b02b 100644 --- a/database/migrations/create_menus_table.php.stub +++ b/database/migrations/create_menus_table.php.stub @@ -13,7 +13,6 @@ return new class extends Migration Schema::create(config('filament-menu-builder.tables.menus'), function (Blueprint $table) { $table->id(); $table->string('name'); - $table->string('location', 50)->nullable(); $table->boolean('is_visible')->default(true); $table->timestamps(); }); @@ -24,7 +23,7 @@ return new class extends Migration $table->foreignIdFor(Menu::class, 'parent_id')->nullable(); $table->nullableMorphs('linkable'); $table->string('title'); - $table->string('url'); + $table->string('url')->nullable(); $table->string('target', 10)->default(LinkTarget::Self); $table->integer('order')->default(0); $table->timestamps(); diff --git a/postcss.config.cjs b/postcss.config.cjs index 2855394..273c66d 100644 --- a/postcss.config.cjs +++ b/postcss.config.cjs @@ -1,7 +1,7 @@ module.exports = { plugins: { - "postcss-import": {}, - "tailwindcss/nesting": {}, + 'postcss-import': {}, + 'tailwindcss/nesting': {}, tailwindcss: {}, autoprefixer: {}, }, diff --git a/resources/dist/filament-menu-builder.css b/resources/dist/filament-menu-builder.css index aaa117b..295c7a7 100644 --- a/resources/dist/filament-menu-builder.css +++ b/resources/dist/filament-menu-builder.css @@ -1 +1,529 @@ -/*! tailwindcss v3.4.7 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border-width:0;border-style:solid;border-color:rgba(var(--gray-200),1)}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:var(--font-family),ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:rgba(var(--gray-400),1)}input::placeholder,textarea::placeholder{opacity:1;color:rgba(var(--gray-400),1)}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],input:where(:not([type])),select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:rgba(var(--gray-500),var(--tw-border-opacity,1));border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow:0 0 #0000}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,input:where(:not([type])):focus,select:focus,textarea:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#2563eb}input::-moz-placeholder,textarea::-moz-placeholder{color:rgba(var(--gray-500),var(--tw-text-opacity,1));opacity:1}input::placeholder,textarea::placeholder{color:rgba(var(--gray-500),var(--tw-text-opacity,1));opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-meridiem-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-year-field{padding-top:0;padding-bottom:0}select{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='rgba(var(--gray-500), var(--tw-stroke-opacity, 1))' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple],[size]:where(select:not([size="1"])){background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:rgba(var(--gray-500),var(--tw-border-opacity,1));border-width:1px;--tw-shadow:0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}[type=checkbox]:checked,[type=radio]:checked{border-color:#0000;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0z'/%3E%3C/svg%3E")}@media (forced-colors:active){[type=checkbox]:checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}@media (forced-colors:active){[type=radio]:checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=checkbox]:checked:focus,[type=checkbox]:checked:hover,[type=checkbox]:indeterminate,[type=radio]:checked:focus,[type=radio]:checked:hover{border-color:#0000;background-color:currentColor}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");background-size:100% 100%;background-position:50%;background-repeat:no-repeat}@media (forced-colors:active){[type=checkbox]:indeterminate{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{border-color:#0000;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}[data-field-wrapper]{scroll-margin-top:8rem}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.col-span-12{grid-column:span 12/span 12}.ms-4{margin-inline-start:1rem}.rotate-90{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.text-ellipsis{text-overflow:ellipsis}.p-2\.5{padding:.625rem}@media (min-width:640px){.sm\:col-span-4{grid-column:span 4/span 4}.sm\:col-span-8{grid-column:span 8/span 8}} \ No newline at end of file +/*! tailwindcss v3.4.7 | MIT License | https://tailwindcss.com*/ +*, +:after, +:before { + box-sizing: border-box; + border-width: 0; + border-style: solid; + border-color: rgba(var(--gray-200), 1); +} +:after, +:before { + --tw-content: ''; +} +:host, +html { + line-height: 1.5; + -webkit-text-size-adjust: 100%; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + font-family: var(--font-family), ui-sans-serif, system-ui, sans-serif, + 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', + 'Noto Color Emoji'; + font-feature-settings: normal; + font-variation-settings: normal; + -webkit-tap-highlight-color: transparent; +} +body { + margin: 0; + line-height: inherit; +} +hr { + height: 0; + color: inherit; + border-top-width: 1px; +} +abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} +a { + color: inherit; + text-decoration: inherit; +} +b, +strong { + font-weight: bolder; +} +code, +kbd, +pre, +samp { + font-family: + ui-monospace, + SFMono-Regular, + Menlo, + Monaco, + Consolas, + Liberation Mono, + Courier New, + monospace; + font-feature-settings: normal; + font-variation-settings: normal; + font-size: 1em; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: initial; +} +sub { + bottom: -0.25em; +} +sup { + top: -0.5em; +} +table { + text-indent: 0; + border-color: inherit; + border-collapse: collapse; +} +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + font-feature-settings: inherit; + font-variation-settings: inherit; + font-size: 100%; + font-weight: inherit; + line-height: inherit; + letter-spacing: inherit; + color: inherit; + margin: 0; + padding: 0; +} +button, +select { + text-transform: none; +} +button, +input:where([type='button']), +input:where([type='reset']), +input:where([type='submit']) { + -webkit-appearance: button; + background-color: initial; + background-image: none; +} +:-moz-focusring { + outline: auto; +} +:-moz-ui-invalid { + box-shadow: none; +} +progress { + vertical-align: initial; +} +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} +[type='search'] { + -webkit-appearance: textfield; + outline-offset: -2px; +} +::-webkit-search-decoration { + -webkit-appearance: none; +} +::-webkit-file-upload-button { + -webkit-appearance: button; + font: inherit; +} +summary { + display: list-item; +} +blockquote, +dd, +dl, +figure, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +p, +pre { + margin: 0; +} +fieldset { + margin: 0; +} +fieldset, +legend { + padding: 0; +} +menu, +ol, +ul { + list-style: none; + margin: 0; + padding: 0; +} +dialog { + padding: 0; +} +textarea { + resize: vertical; +} +input::-moz-placeholder, +textarea::-moz-placeholder { + opacity: 1; + color: rgba(var(--gray-400), 1); +} +input::placeholder, +textarea::placeholder { + opacity: 1; + color: rgba(var(--gray-400), 1); +} +[role='button'], +button { + cursor: pointer; +} +:disabled { + cursor: default; +} +audio, +canvas, +embed, +iframe, +img, +object, +svg, +video { + display: block; + vertical-align: middle; +} +img, +video { + max-width: 100%; + height: auto; +} +[hidden] { + display: none; +} +[multiple], +[type='date'], +[type='datetime-local'], +[type='email'], +[type='month'], +[type='number'], +[type='password'], +[type='search'], +[type='tel'], +[type='text'], +[type='time'], +[type='url'], +[type='week'], +input:where(:not([type])), +select, +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background-color: #fff; + border-color: rgba(var(--gray-500), var(--tw-border-opacity, 1)); + border-width: 1px; + border-radius: 0; + padding: 0.5rem 0.75rem; + font-size: 1rem; + line-height: 1.5rem; + --tw-shadow: 0 0 #0000; +} +[multiple]:focus, +[type='date']:focus, +[type='datetime-local']:focus, +[type='email']:focus, +[type='month']:focus, +[type='number']:focus, +[type='password']:focus, +[type='search']:focus, +[type='tel']:focus, +[type='text']:focus, +[type='time']:focus, +[type='url']:focus, +[type='week']:focus, +input:where(:not([type])):focus, +select:focus, +textarea:focus { + outline: 2px solid #0000; + outline-offset: 2px; + --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/); + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: #2563eb; + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 + var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 + calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), + var(--tw-shadow); + border-color: #2563eb; +} +input::-moz-placeholder, +textarea::-moz-placeholder { + color: rgba(var(--gray-500), var(--tw-text-opacity, 1)); + opacity: 1; +} +input::placeholder, +textarea::placeholder { + color: rgba(var(--gray-500), var(--tw-text-opacity, 1)); + opacity: 1; +} +::-webkit-datetime-edit-fields-wrapper { + padding: 0; +} +::-webkit-date-and-time-value { + min-height: 1.5em; + text-align: inherit; +} +::-webkit-datetime-edit { + display: inline-flex; +} +::-webkit-datetime-edit, +::-webkit-datetime-edit-day-field, +::-webkit-datetime-edit-hour-field, +::-webkit-datetime-edit-meridiem-field, +::-webkit-datetime-edit-millisecond-field, +::-webkit-datetime-edit-minute-field, +::-webkit-datetime-edit-month-field, +::-webkit-datetime-edit-second-field, +::-webkit-datetime-edit-year-field { + padding-top: 0; + padding-bottom: 0; +} +select { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='rgba(var(--gray-500), var(--tw-stroke-opacity, 1))' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E"); + background-position: right 0.5rem center; + background-repeat: no-repeat; + background-size: 1.5em 1.5em; + padding-right: 2.5rem; + -webkit-print-color-adjust: exact; + print-color-adjust: exact; +} +[multiple], +[size]:where(select:not([size='1'])) { + background-image: none; + background-position: 0 0; + background-repeat: unset; + background-size: initial; + padding-right: 0.75rem; + -webkit-print-color-adjust: unset; + print-color-adjust: unset; +} +[type='checkbox'], +[type='radio'] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + padding: 0; + -webkit-print-color-adjust: exact; + print-color-adjust: exact; + display: inline-block; + vertical-align: middle; + background-origin: border-box; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + flex-shrink: 0; + height: 1rem; + width: 1rem; + color: #2563eb; + background-color: #fff; + border-color: rgba(var(--gray-500), var(--tw-border-opacity, 1)); + border-width: 1px; + --tw-shadow: 0 0 #0000; +} +[type='checkbox'] { + border-radius: 0; +} +[type='radio'] { + border-radius: 100%; +} +[type='checkbox']:focus, +[type='radio']:focus { + outline: 2px solid #0000; + outline-offset: 2px; + --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/); + --tw-ring-offset-width: 2px; + --tw-ring-offset-color: #fff; + --tw-ring-color: #2563eb; + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 + var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 + calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), + var(--tw-shadow); +} +[type='checkbox']:checked, +[type='radio']:checked { + border-color: #0000; + background-color: currentColor; + background-size: 100% 100%; + background-position: 50%; + background-repeat: no-repeat; +} +[type='checkbox']:checked { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0z'/%3E%3C/svg%3E"); +} +@media (forced-colors: active) { + [type='checkbox']:checked { + -webkit-appearance: auto; + -moz-appearance: auto; + appearance: auto; + } +} +[type='radio']:checked { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E"); +} +@media (forced-colors: active) { + [type='radio']:checked { + -webkit-appearance: auto; + -moz-appearance: auto; + appearance: auto; + } +} +[type='checkbox']:checked:focus, +[type='checkbox']:checked:hover, +[type='checkbox']:indeterminate, +[type='radio']:checked:focus, +[type='radio']:checked:hover { + border-color: #0000; + background-color: currentColor; +} +[type='checkbox']:indeterminate { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E"); + background-size: 100% 100%; + background-position: 50%; + background-repeat: no-repeat; +} +@media (forced-colors: active) { + [type='checkbox']:indeterminate { + -webkit-appearance: auto; + -moz-appearance: auto; + appearance: auto; + } +} +[type='checkbox']:indeterminate:focus, +[type='checkbox']:indeterminate:hover { + border-color: #0000; + background-color: currentColor; +} +[type='file'] { + background: unset; + border-color: inherit; + border-width: 0; + border-radius: 0; + padding: 0; + font-size: unset; + line-height: inherit; +} +[type='file']:focus { + outline: 1px solid ButtonText; + outline: 1px auto -webkit-focus-ring-color; +} +[data-field-wrapper] { + scroll-margin-top: 8rem; +} +*, +::backdrop, +:after, +:before { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: #3b82f680; + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} +.col-span-12 { + grid-column: span 12 / span 12; +} +.ms-4 { + margin-inline-start: 1rem; +} +.rotate-90 { + --tw-rotate: 90deg; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) + rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) + scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.grid-cols-12 { + grid-template-columns: repeat(12, minmax(0, 1fr)); +} +.text-ellipsis { + text-overflow: ellipsis; +} +.p-2\.5 { + padding: 0.625rem; +} +@media (min-width: 640px) { + .sm\:col-span-4 { + grid-column: span 4 / span 4; + } + .sm\:col-span-8 { + grid-column: span 8 / span 8; + } +} diff --git a/resources/dist/filament-menu-builder.js b/resources/dist/filament-menu-builder.js index 2297385..55b8564 100644 --- a/resources/dist/filament-menu-builder.js +++ b/resources/dist/filament-menu-builder.js @@ -1,25 +1,23 @@ // resources/js/index.js var js_default = ({ parentId }) => ({ - parentId, - sortable: null, - init() { - this.sortable = new Sortable(this.$el, { - group: "nested", - draggable: "[data-sortable-item]", - handle: "[data-sortable-handle]", - animation: 300, - ghostClass: "fi-sortable-ghost", - dataIdAttr: "data-sortable-item", - onSort: () => { - this.$wire.reorder( - this.sortable.toArray(), - this.parentId === 0 ? null : this.parentId - ); - } - }); - } -}); -export { - js_default as default -}; + parentId, + sortable: null, + init() { + this.sortable = new Sortable(this.$el, { + group: 'nested', + draggable: '[data-sortable-item]', + handle: '[data-sortable-handle]', + animation: 300, + ghostClass: 'fi-sortable-ghost', + dataIdAttr: 'data-sortable-item', + onSort: () => { + this.$wire.reorder( + this.sortable.toArray(), + this.parentId === 0 ? null : this.parentId, + ) + }, + }) + }, +}) +export { js_default as default } //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vanMvaW5kZXguanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImV4cG9ydCBkZWZhdWx0ICh7IHBhcmVudElkIH0pID0+ICh7XG4gICAgcGFyZW50SWQsXG4gICAgc29ydGFibGU6IG51bGwsXG5cbiAgICBpbml0KCkge1xuICAgICAgICB0aGlzLnNvcnRhYmxlID0gbmV3IFNvcnRhYmxlKHRoaXMuJGVsLCB7XG4gICAgICAgICAgICBncm91cDogJ25lc3RlZCcsXG4gICAgICAgICAgICBkcmFnZ2FibGU6ICdbZGF0YS1zb3J0YWJsZS1pdGVtXScsXG4gICAgICAgICAgICBoYW5kbGU6ICdbZGF0YS1zb3J0YWJsZS1oYW5kbGVdJyxcbiAgICAgICAgICAgIGFuaW1hdGlvbjogMzAwLFxuICAgICAgICAgICAgZ2hvc3RDbGFzczogJ2ZpLXNvcnRhYmxlLWdob3N0JyxcbiAgICAgICAgICAgIGRhdGFJZEF0dHI6ICdkYXRhLXNvcnRhYmxlLWl0ZW0nLFxuICAgICAgICAgICAgb25Tb3J0OiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy4kd2lyZS5yZW9yZGVyKFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnNvcnRhYmxlLnRvQXJyYXkoKSxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wYXJlbnRJZCA9PT0gMCA/IG51bGwgOiB0aGlzLnBhcmVudElkXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuICAgIH0sXG59KVxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUFBLElBQU8sYUFBUSxDQUFDLEVBQUUsU0FBUyxPQUFPO0FBQUEsRUFDOUI7QUFBQSxFQUNBLFVBQVU7QUFBQSxFQUVWLE9BQU87QUFDSCxTQUFLLFdBQVcsSUFBSSxTQUFTLEtBQUssS0FBSztBQUFBLE1BQ25DLE9BQU87QUFBQSxNQUNQLFdBQVc7QUFBQSxNQUNYLFFBQVE7QUFBQSxNQUNSLFdBQVc7QUFBQSxNQUNYLFlBQVk7QUFBQSxNQUNaLFlBQVk7QUFBQSxNQUNaLFFBQVEsTUFBTTtBQUNWLGFBQUssTUFBTTtBQUFBLFVBQ1AsS0FBSyxTQUFTLFFBQVE7QUFBQSxVQUN0QixLQUFLLGFBQWEsSUFBSSxPQUFPLEtBQUs7QUFBQSxRQUN0QztBQUFBLE1BQ0o7QUFBQSxJQUNKLENBQUM7QUFBQSxFQUNMO0FBQ0o7IiwKICAibmFtZXMiOiBbXQp9Cg== diff --git a/resources/js/index.js b/resources/js/index.js index 10c74a7..9d69b31 100644 --- a/resources/js/index.js +++ b/resources/js/index.js @@ -13,9 +13,9 @@ export default ({ parentId }) => ({ onSort: () => { this.$wire.reorder( this.sortable.toArray(), - this.parentId === 0 ? null : this.parentId + this.parentId === 0 ? null : this.parentId, ) - } + }, }) }, }) diff --git a/resources/lang/en/menu-builder.php b/resources/lang/en/menu-builder.php index b0d1a00..28c3c08 100644 --- a/resources/lang/en/menu-builder.php +++ b/resources/lang/en/menu-builder.php @@ -2,7 +2,24 @@ declare(strict_types=1); -// translations for Datlechin/FilamentMenuBuilder return [ - // + 'title' => 'Title', + 'url' => 'URL', + 'add_to_menu' => 'Add to Menu', + 'custom_link' => 'Custom Link', + 'open_in' => [ + 'label' => 'Open in', + 'options' => [ + 'self' => 'Same tab', + 'blank' => 'New tab', + 'parent' => 'Parent tab', + 'top' => 'Top tab', + ], + ], + + 'notifications' => [ + 'created' => [ + 'title' => 'Link created', + ], + ], ]; diff --git a/resources/views/components/menu-item.blade.php b/resources/views/components/menu-item.blade.php index 639f62c..c4bb913 100644 --- a/resources/views/components/menu-item.blade.php +++ b/resources/views/components/menu-item.blade.php @@ -12,7 +12,7 @@ x-data="{ open: $persist(true).as('menu-item-' + {{ $item->getKey() }}) }" >
{{ $this->reorderAction }} @@ -23,7 +23,7 @@ class="flex justify-between rounded-xl bg-white shadow-sm ring-1 ring-gray-950/5 x-on:click="open = !open" title="Mở rộng" color="gray" - class="transition ease-in-out duration-200" + class="transition duration-200 ease-in-out" x-bind:class="{ 'rotate-90': open }" size="sm" /> @@ -33,7 +33,7 @@ class="transition ease-in-out duration-200" {{ $item->title }}
- @@ -51,7 +51,7 @@ class="transition ease-in-out duration-200" x-show="open" wire:key="{{ $item->getKey() }}.children" x-data="menuBuilder({ parentId: {{ $item->getKey() }} })" - class="ms-4 space-y-2 mt-2" + class="mt-2 space-y-2 ms-4" > @foreach($item->children as $child) diff --git a/resources/views/edit-record.blade.php b/resources/views/edit-record.blade.php index 1e33733..aa46ced 100644 --- a/resources/views/edit-record.blade.php +++ b/resources/views/edit-record.blade.php @@ -33,7 +33,7 @@ @endif -
+
@foreach (\Datlechin\FilamentMenuBuilder\FilamentMenuBuilderPlugin::get()->getMenuPanels() as $menuPanel) diff --git a/resources/views/livewire/create-custom-link.blade.php b/resources/views/livewire/create-custom-link.blade.php index f32c27f..cc2fc0e 100644 --- a/resources/views/livewire/create-custom-link.blade.php +++ b/resources/views/livewire/create-custom-link.blade.php @@ -1,6 +1,6 @@
- Thêm vào menu + {{ __('filament-menu-builder::menu-builder.add_to_menu') }} diff --git a/resources/views/livewire/panel.blade.php b/resources/views/livewire/panel.blade.php index 316f696..001568d 100644 --- a/resources/views/livewire/panel.blade.php +++ b/resources/views/livewire/panel.blade.php @@ -1,10 +1,15 @@ - + {{ $this->form }} - Thêm vào menu + {{ __('filament-menu-builder::menu-builder.add_to_menu') }} diff --git a/src/Concerns/HasMenuPanel.php b/src/Concerns/HasMenuPanel.php new file mode 100644 index 0000000..92574b0 --- /dev/null +++ b/src/Concerns/HasMenuPanel.php @@ -0,0 +1,22 @@ +getTable()) + ->title() + ->toString(); + } + + public function getMenuPanelModifyQueryUsing(): callable + { + return fn(Builder $query) => $query; + } +} diff --git a/src/Contracts/MenuPanel.php b/src/Contracts/MenuPanel.php index 0fe432e..4f0f42e 100644 --- a/src/Contracts/MenuPanel.php +++ b/src/Contracts/MenuPanel.php @@ -6,6 +6,8 @@ interface MenuPanel { + public function getIdentifier(): string; + public function getName(): string; public function getItems(): array; diff --git a/src/Contracts/MenuPanelable.php b/src/Contracts/MenuPanelable.php new file mode 100644 index 0000000..743a68d --- /dev/null +++ b/src/Contracts/MenuPanelable.php @@ -0,0 +1,16 @@ + 'Cùng tab', - self::Blank => 'Tab mới', - self::Parent => 'Tab cha', - self::Top => 'Tab trên cùng', + self::Self => __('filament-menu-builder::menu-builder.open_in.options.self'), + self::Blank => __('filament-menu-builder::menu-builder.open_in.options.blank'), + self::Parent => __('filament-menu-builder::menu-builder.open_in.options.parent'), + self::Top => __('filament-menu-builder::menu-builder.open_in.options.top'), }; } } diff --git a/src/Livewire/CreateCustomLink.php b/src/Livewire/CreateCustomLink.php index 2d970ff..1cae391 100644 --- a/src/Livewire/CreateCustomLink.php +++ b/src/Livewire/CreateCustomLink.php @@ -46,7 +46,7 @@ public function save(): void ]); Notification::make() - ->title('Đã thêm liên kết tùy chỉnh vào menu.') + ->title(__('filament-menu-builder::menu-builder.notifications.created.title')) ->success() ->send(); @@ -59,13 +59,13 @@ public function form(Form $form): Form return $form ->schema([ TextInput::make('title') - ->label('Tiêu đề') + ->label(__('filament-menu-builder::menu-builder.title')) ->required(), TextInput::make('url') - ->label('URL') + ->label(__('filament-menu-builder::menu-builder.url')) ->required(), Select::make('target') - ->label('Mở trong') + ->label(__('filament-menu-builder::menu-builder.open_in.label')) ->options(LinkTarget::class) ->default(LinkTarget::Self), ]); diff --git a/src/Livewire/MenuItems.php b/src/Livewire/MenuItems.php index 6087df0..5ae71c2 100644 --- a/src/Livewire/MenuItems.php +++ b/src/Livewire/MenuItems.php @@ -10,6 +10,7 @@ use Filament\Actions\Action; use Filament\Actions\Concerns\InteractsWithActions; use Filament\Actions\Contracts\HasActions; +use Filament\Forms\Components\Placeholder; use Filament\Forms\Components\Select; use Filament\Forms\Components\TextInput; use Filament\Forms\Concerns\InteractsWithForms; @@ -78,26 +79,33 @@ public function editAction(): Action ->icon('heroicon-m-pencil-square') ->fillForm(fn(array $arguments): array => MenuItem::query() ->where('id', $arguments['id']) - ->select(['id', 'title', 'url', 'target']) + ->with('linkable') ->first() ->toArray()) ->form([ TextInput::make('title') - ->label('Tiêu đề') + ->label(__('filament-menu-builder::menu-builder.title')) ->required(), TextInput::make('url') - ->label('URL') + ->hidden(fn(?string $state): bool => empty($state)) + ->label(__('filament-menu-builder::menu-builder.url')) ->required(), + Placeholder::make('linkable_type') + ->hidden(fn(?string $state): bool => empty($state)) + ->content(fn(string $state) => $state), + Placeholder::make('linkable_id') + ->hidden(fn(?string $state): bool => empty($state)) + ->content(fn(string $state) => $state), Select::make('target') - ->label('Mở trong') + ->label(__('filament-menu-builder::menu-builder.open_in.label')) ->options(LinkTarget::class) ->default(LinkTarget::Self), ]) - ->action(function (array $data, array $arguments) { - MenuItem::query() + ->action( + fn(array $data, array $arguments) => MenuItem::query() ->where('id', $arguments['id']) - ->update($data); - }) + ->update($data), + ) ->modalWidth(MaxWidth::Medium) ->slideOver(); } diff --git a/src/Livewire/MenuPanel.php b/src/Livewire/MenuPanel.php index 0d4dcf6..a0afa88 100644 --- a/src/Livewire/MenuPanel.php +++ b/src/Livewire/MenuPanel.php @@ -10,6 +10,7 @@ use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Contracts\HasForms; use Filament\Forms\Form; +use Filament\Notifications\Notification; use Illuminate\Contracts\View\View; use Livewire\Attributes\Validate; use Livewire\Component; @@ -20,6 +21,8 @@ class MenuPanel extends Component implements HasForms public Menu $menu; + public string $id; + public string $name; public array $items = []; @@ -29,13 +32,15 @@ class MenuPanel extends Component implements HasForms public function mount(ContractsMenuPanel $menuPanel): void { + $this->id = $menuPanel->getIdentifier(); $this->name = $menuPanel->getName(); - $this->items = collect($menuPanel->getItems())->map(function ($item) { - return [ - 'title' => $item['title'], - 'url' => value($item['url']), - ]; - })->all(); + $this->items = array_map(function ($item) { + if (isset($item['url']) && is_callable($item['url'])) { + $item['url'] = $item['url'](); + } + + return $item; + }, $menuPanel->getItems()); } public function add(): void @@ -61,6 +66,11 @@ public function add(): void $this->reset('data'); $this->dispatch('menu:created'); + + Notification::make() + ->title(__('filament-menu-builder::menu-builder.notifications.created.title')) + ->success() + ->send(); } public function form(Form $form): Form diff --git a/src/MenuPanel/AbstractMenuPanel.php b/src/MenuPanel/AbstractMenuPanel.php index 75cfa81..36d5f9c 100644 --- a/src/MenuPanel/AbstractMenuPanel.php +++ b/src/MenuPanel/AbstractMenuPanel.php @@ -8,7 +8,26 @@ abstract class AbstractMenuPanel implements MenuPanel { - protected int $sort = 0; + protected string $name; + + protected int $sort = 999; + + public function __construct(string $name) + { + $this->name = $name; + } + + public static function make(string $name = 'Static Menu'): static + { + return new static($name); + } + + public function getIdentifier(): string + { + return str($this->getName()) + ->slug() + ->toString(); + } public function sort(int $sort): static { diff --git a/src/MenuPanel/ModelMenuPanel.php b/src/MenuPanel/ModelMenuPanel.php new file mode 100644 index 0000000..548f868 --- /dev/null +++ b/src/MenuPanel/ModelMenuPanel.php @@ -0,0 +1,45 @@ + $model + */ + public function model(string $model): static + { + $this->model = new $model(); + + return $this; + } + + public function getName(): string + { + return $this->model->getMenuPanelName(); + } + + public function getItems(): array + { + return ($this->model->getMenuPanelModifyQueryUsing())($this->model->newQuery()) + ->get() + ->map(fn(Model $model) => [ + 'title' => $model->{$this->model->getMenuPanelTitleColumn()}, + 'linkable_type' => $model::class, + 'linkable_id' => $model->getKey(), + ]) + ->all(); + } +} diff --git a/src/MenuPanel/StaticMenuPanel.php b/src/MenuPanel/StaticMenuPanel.php index 8981822..abb3e22 100644 --- a/src/MenuPanel/StaticMenuPanel.php +++ b/src/MenuPanel/StaticMenuPanel.php @@ -8,22 +8,8 @@ class StaticMenuPanel extends AbstractMenuPanel { - protected string $name = 'Static Menu'; - protected array $items = []; - public function __construct(?string $name = null) - { - if ($name) { - $this->name = $name; - } - } - - public static function make(?string $name = null): static - { - return new static($name); - } - public function add(string $title, Closure | string $url): static { $this->items[] = [ diff --git a/src/Models/MenuItem.php b/src/Models/MenuItem.php index a45b2fe..ff48d19 100644 --- a/src/Models/MenuItem.php +++ b/src/Models/MenuItem.php @@ -4,6 +4,7 @@ namespace Datlechin\FilamentMenuBuilder\Models; +use Datlechin\FilamentMenuBuilder\Contracts\MenuPanelable; use Datlechin\FilamentMenuBuilder\Enums\LinkTarget; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Model; @@ -59,6 +60,11 @@ public function linkable(): MorphTo protected function type(): Attribute { - return Attribute::get(fn() => $this->linkable ? $this->linkable->title : 'Liên kết tùy chỉnh'); + return Attribute::get(function () { + return match (true) { + $this->linkable instanceof MenuPanelable => $this->linkable->getMenuPanelName(), + default => __('filament-menu-builder::menu-builder.custom_link'), + }; + }); } }