From 28df145d2061122b5338b4f918f211713d492229 Mon Sep 17 00:00:00 2001 From: John Gerwin De las Alas Date: Tue, 25 Nov 2025 13:14:38 +0800 Subject: [PATCH] chore: Remove debug logs and improve Nova compatibility - Remove all console.log statements from FormField.vue for production - Add class_exists check in FieldServiceProvider for non-Nova environments - Update PHP version to support 8.3, 8.4, and 8.5 - Update collision to ^8.6 and pest to ^3.7.4 for compatibility - Reduce JS bundle size by ~2.5KB - Fix PHPStan errors and all tests passing --- CHANGELOG.md | 16 ++++ composer.json | 8 +- dist/js/field.js | 2 +- resources/js/components/FormField.vue | 124 ++++++-------------------- src/FieldServiceProvider.php | 13 +-- 5 files changed, 58 insertions(+), 105 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4bc27f..7158904 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,22 @@ All notable changes to `nova-dependency-container` will be documented in this file. +## [1.0.16] - 2025-11-25 + +### Changed +- Removed all console.log debug statements from Vue components for production readiness +- Improved FieldServiceProvider to gracefully handle environments where Nova is not available +- Updated PHP version requirement to support PHP 8.3, 8.4, and 8.5 +- Updated dependency versions for better compatibility (collision ^8.6, pest ^3.7.4) + +### Fixed +- Fixed PHPStan analysis errors by adding Nova availability check in FieldServiceProvider +- Fixed test failures when Nova package is not installed in dev environment + +### Technical +- Reduced JavaScript bundle size by removing debug logging (~2.5KB reduction) +- Added class_exists check before registering Nova assets to prevent errors in non-Nova environments + ## [1.0.15] - 2025-11-25 ### Fixed diff --git a/composer.json b/composer.json index c23e60a..4f80b6e 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "iamgerwin/nova-dependency-container", - "version": "1.0.13", + "version": "1.0.16", "description": "A Laravel Nova 4 and 5 field container allowing to depend on other fields values", "keywords": [ "laravel", @@ -20,15 +20,15 @@ } ], "require": { - "php": "^8.3", + "php": "^8.3|^8.4|^8.5", "laravel/framework": "^11.0|^12.0" }, "require-dev": { "laravel/pint": "^1.14", "larastan/larastan": "^3.0", - "nunomaduro/collision": "^8.0", + "nunomaduro/collision": "^8.6", "orchestra/testbench": "^9.0|^10.0", - "pestphp/pest": "^3.0", + "pestphp/pest": "^3.7.4", "pestphp/pest-plugin-arch": "^3.0", "pestphp/pest-plugin-laravel": "^3.0", "phpstan/extension-installer": "^1.3", diff --git a/dist/js/field.js b/dist/js/field.js index 6da5651..2b6e5ae 100644 --- a/dist/js/field.js +++ b/dist/js/field.js @@ -1 +1 @@ -(()=>{"use strict";var e,t={66:(e,t,n)=>{const i=Vue;const r={props:["resourceName","field"]};var o=n(262);const a=(0,o.A)(r,[["render",function(e,t,n,r,o,a){return(0,i.openBlock)(),(0,i.createElementBlock)("div")}]]);function l(e){return l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},l(e)}function c(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var i,r,o,a,l=[],c=!0,s=!1;try{if(o=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;c=!1}else for(;!(c=(i=o.call(n)).done)&&(l.push(i.value),l.length!==t);c=!0);}catch(e){s=!0,r=e}finally{try{if(!c&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(s)throw r}}return l}}(e,t)||d(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function s(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=d(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var i=0,r=function(){};return{s:r,n:function(){return i>=e.length?{done:!0}:{done:!1,value:e[i++]}},e:function(e){throw e},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,l=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){l=!0,o=e},f:function(){try{a||null==n.return||n.return()}finally{if(l)throw o}}}}function d(e,t){if(e){if("string"==typeof e)return f(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?f(e,t):void 0}}function f(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=Array(t);n0;){var n;if(e.fields&&Array.isArray(e.fields))return e.fields;if(null!==(n=e.$refs)&&void 0!==n&&n.fields&&Array.isArray(e.$refs.fields))return e.$refs.fields.map(function(e){return e.field||e});e=e.$parent}return[]},extractPrefixFromAttribute:function(e){if(!e)return null;var t=e.match(/^(.+__\d+__)/);if(t)return t[1];var n=e.match(/^(.+\[\d+\]\[)/);if(n)return n[1];var i=e.match(/^([a-zA-Z0-9]+__)/);return i?i[1]:null},getFlexibleAttributeFormats:function(e,t){var n=[],i=e.match(/^(.+)__(\d+)__$/),r=e.match(/^(.+)\[(\d+)\]\[$/);if(i){var o=c(i,3),a=o[1],l=o[2];n.push("".concat(a,"[").concat(l,"][").concat(t,"]")),n.push("".concat(a,"_").concat(l,"_").concat(t))}if(r){var s=c(r,3),d=s[1],f=s[2];n.push("".concat(d,"__").concat(f,"__").concat(t)),n.push("".concat(d,"_").concat(f,"_").concat(t))}return n},isEmpty:function(e){return null==e||""===e||Array.isArray(e)&&0===e.length||"object"===l(e)&&0===Object.keys(e).length}}};var h=n(72),v=n.n(h),p=n(254),y={insert:"head",singleton:!1};v()(p.A,y);p.A.locals;const b=(0,o.A)(u,[["render",function(e,t,n,r,o,a){return(0,i.withDirectives)(((0,i.openBlock)(),(0,i.createElementBlock)("div",{class:(0,i.normalizeClass)(a.containerClasses)},[((0,i.openBlock)(!0),(0,i.createElementBlock)(i.Fragment,null,(0,i.renderList)(n.field.fields,function(e,t){return(0,i.openBlock)(),(0,i.createBlock)((0,i.resolveDynamicComponent)("detail-".concat(e.component)),{key:t,"resource-name":n.resourceName,"resource-id":n.resourceId,field:e},null,8,["resource-name","resource-id","field"])}),128))],2)),[[i.vShow,o.isVisible]])}],["__scopeId","data-v-f5f08646"]]);const m=LaravelNova;function x(e){return x="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},x(e)}function g(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var i,r,o,a,l=[],c=!0,s=!1;try{if(o=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;c=!1}else for(;!(c=(i=o.call(n)).done)&&(l.push(i.value),l.length!==t);c=!0);}catch(e){s=!0,r=e}finally{try{if(!c&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(s)throw r}}return l}}(e,t)||F(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function C(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=F(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var i=0,r=function(){};return{s:r,n:function(){return i>=e.length?{done:!0}:{done:!1,value:e[i++]}},e:function(e){throw e},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,l=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){l=!0,o=e},f:function(){try{a||null==n.return||n.return()}finally{if(l)throw o}}}}function F(e,t){if(e){if("string"==typeof e)return A(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?A(e,t):void 0}}function A(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=Array(t);n",t.attribute)}}))},detectFlexibleContextOnMount:function(){var e,t,n=this;console.log("[NovaDependencyContainer] detectFlexibleContextOnMount called");var i=(null===(e=this.field)||void 0===e?void 0:e.attribute)||"";if(console.log("[NovaDependencyContainer] Container attribute:",i),i){var r=this.extractPrefixFromAttribute(i);if(r)return console.log("[NovaDependencyContainer] Detected context from own attribute:",r),this.cachedContextPrefix=r,void(this.contextDetected=!0)}var o,a=C((null===(t=this.field)||void 0===t?void 0:t.fields)||[]);try{for(a.s();!(o=a.n()).done;){var l=o.value;if(l.attribute){var c=this.extractPrefixFromAttribute(l.attribute);if(c)return this.cachedContextPrefix=c,void(this.contextDetected=!0)}}}catch(e){a.e(e)}finally{a.f()}for(var s=this.$parent,d=0;s&&d<20;){var f;if(void 0!==s.layout||void 0!==s.layoutIndex||void 0!==s.groupIndex){var u,h,v,p,y=(null===(u=s.field)||void 0===u?void 0:u.attribute)||s.attribute||"",b=null!==(h=null!==(v=null!==(p=s.layoutIndex)&&void 0!==p?p:s.groupIndex)&&void 0!==v?v:s.index)&&void 0!==h?h:0;if(y)return this.cachedContextPrefix="".concat(y,"__").concat(b,"__"),void(this.contextDetected=!0)}if(null!==(f=s.field)&&void 0!==f&&f.attribute){var m=this.extractPrefixFromAttribute(s.field.attribute);if(m)return this.cachedContextPrefix=m,void(this.contextDetected=!0)}s=s.$parent,d++}this.$nextTick(function(){n.contextDetected||n.detectContextFromDOM()})},detectContextFromDOM:function(){try{for(var e=this.$el,t=0;e&&t<20;){if(e.dataset){var n=e.dataset.flexibleKey||e.dataset.layoutKey,i=e.dataset.flexibleIndex||e.dataset.layoutIndex;if(n&&void 0!==i)return this.cachedContextPrefix="".concat(n,"__").concat(i,"__"),void(this.contextDetected=!0)}var r,o=C(e.querySelectorAll?e.querySelectorAll("input, select, textarea"):[]);try{for(o.s();!(r=o.n()).done;){var a=r.value,l=a.name||a.id;if(l){var c=this.extractPrefixFromAttribute(l);if(c)return this.cachedContextPrefix=c,void(this.contextDetected=!0)}}}catch(e){o.e(e)}finally{o.f()}e=e.parentElement,t++}}catch(e){}},watchDependentFields:function(){var e=this;if(!this.field.dependencies||0===this.field.dependencies.length)return console.log("[NovaDependencyContainer] No dependencies, showing field"),void(this.isVisible=!0);console.log("[NovaDependencyContainer] Watching for field-changed events"),Nova.$on("field-changed",this.handleFieldChanged),this.$nextTick(function(){e.setupDOMWatching(),e.loadInitialValuesFromDOM()})},setupDOMWatching:function(){var e=this;if(this.cachedContextPrefix){var t=this.findFlexibleContainer();if(t){console.log("[NovaDependencyContainer] Setting up DOM watching on Flexible container");var n=t.querySelectorAll("select, input, textarea");n.forEach(function(t){t.addEventListener("change",e.handleDOMChange),t.addEventListener("input",e.handleDOMChange)}),this.watchedElements=n,this.flexibleContainer=t,this.setupMutationObserver(t)}else console.log("[NovaDependencyContainer] Could not find Flexible container for DOM watching")}},setupMutationObserver:function(e){var t=this;this.mutationObserver&&this.mutationObserver.disconnect(),this.mutationObserver=new MutationObserver(function(e){t.loadInitialValuesFromDOM()}),this.mutationObserver.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]})},findFlexibleContainer:function(){for(var e,t,n=this.$el,i=0;n&&i<20;){var r;if(n.classList&&(n.classList.contains("flexible-group")||n.classList.contains("nova-flexible-content-group")||null!==(r=n.dataset)&&void 0!==r&&r.flexibleGroup))return n;if(n.querySelector&&this.cachedContextPrefix)if(n.querySelectorAll('[name^="'.concat(this.cachedContextPrefix,'"], [id^="').concat(this.cachedContextPrefix,'"]')).length>1)return n;n=n.parentElement,i++}return(null===(e=this.$el)||void 0===e?void 0:e.closest("form"))||(null===(t=this.$el)||void 0===t?void 0:t.closest("[data-field-wrapper]"))||document.body},handleDOMChange:function(e){var t=e.target,n=t.name||t.id||"",i="checkbox"===t.type?t.checked:t.value;if(console.log("[NovaDependencyContainer] DOM change detected:",{name:n,value:i}),n){var r=this.extractPrefixFromAttribute(n);if(!this.cachedContextPrefix||!r||r===this.cachedContextPrefix){var o=this.extractBaseAttribute(n);this.field.dependencies.some(function(e){return e.field===o})&&(console.log("[NovaDependencyContainer] Relevant field changed via DOM:",o,"=",i),this.dependentFieldValues[n]=i,this.dependentFieldValues[o]=i,this.checkDependencies())}}},loadInitialValuesFromDOM:function(){if(this.field.dependencies){console.log("[NovaDependencyContainer] Loading initial values from DOM");var e,t=C(this.field.dependencies);try{for(t.s();!(e=t.n()).done;)for(var n=e.value.field,i=this.cachedContextPrefix?"".concat(this.cachedContextPrefix).concat(n):n,r=['[name="'.concat(i,'"]'),'[name="'.concat(n,'"]'),'[id="'.concat(i,'"]'),'[id="'.concat(n,'"]'),'[name$="__'.concat(n,'"]'),'[name$="['.concat(n,']"]')],o=0,a=r;o0;){var i;if(null!==(i=t.$refs)&&void 0!==i&&i.fields&&Array.isArray(t.$refs.fields))return t.$refs.fields;if(t.fields&&Array.isArray(t.fields))return t.fields.map(function(e){return{field:e}});t=t.$parent}return[]},getFlexibleAttributeFormats:function(e,t){var n=[],i=e.match(/^(.+)__(\d+)__$/),r=e.match(/^(.+)\[(\d+)\]\[$/);if(i){var o=g(i,3),a=o[1],l=o[2];n.push("".concat(a,"[").concat(l,"][").concat(t,"]")),n.push("".concat(a,"_").concat(l,"_").concat(t))}if(r){var c=g(r,3),s=c[1],d=c[2];n.push("".concat(s,"__").concat(d,"__").concat(t)),n.push("".concat(s,"_").concat(d,"_").concat(t))}return n},isEmpty:function(e){return null==e||""===e||Array.isArray(e)&&0===e.length||"object"===x(e)&&0===Object.keys(e).length},fill:function(e){var t=this;console.log("[NovaDependencyContainer] fill() called, isVisible:",this.isVisible),console.log("[NovaDependencyContainer] Available fieldRefs:",Object.keys(this.fieldRefs)),this.isVisible?this.field.fields&&this.field.fields.forEach(function(n){var i=t.fieldRefs[n.attribute];console.log("[NovaDependencyContainer] Filling field:",n.attribute,"component:",i?"found":"not found"),i&&"function"==typeof i.fill?(i.fill(e),console.log("[NovaDependencyContainer] Field filled successfully:",n.attribute)):console.warn("[NovaDependencyContainer] Could not fill field:",n.attribute,"ref not found or no fill method")}):console.log("[NovaDependencyContainer] Not visible, skipping fill")}},beforeUnmount:function(){var e=this;Nova.$off("field-changed",this.handleFieldChanged),this.watchedElements&&this.watchedElements.forEach(function(t){t.removeEventListener("change",e.handleDOMChange),t.removeEventListener("input",e.handleDOMChange)}),this.mutationObserver&&this.mutationObserver.disconnect(),this.fieldRefs={}}};var O=n(654),_={insert:"head",singleton:!1};v()(O.A,_);O.A.locals;const P=(0,o.A)(D,[["render",function(e,t,n,r,o,a){return(0,i.withDirectives)(((0,i.openBlock)(),(0,i.createElementBlock)("div",{class:(0,i.normalizeClass)(a.containerClasses)},[((0,i.openBlock)(!0),(0,i.createElementBlock)(i.Fragment,null,(0,i.renderList)(n.field.fields,function(r,o){return(0,i.openBlock)(),(0,i.createBlock)((0,i.resolveDynamicComponent)("form-".concat(r.component)),{key:r.attribute||o,ref_for:!0,ref:function(e){return a.setFieldRef(r.attribute,e)},"resource-name":n.resourceName,"resource-id":n.resourceId,field:r,errors:n.errors,"show-help-text":n.showHelpText,mode:n.mode,"via-resource":n.viaResource,"via-resource-id":n.viaResourceId,"via-relationship":n.viaRelationship,onFieldChanged:a.handleFieldChanged,onFileDeleted:t[0]||(t[0]=function(t){return e.$emit("file-deleted")}),onFileUploadStarted:t[1]||(t[1]=function(t){return e.$emit("file-upload-started")}),onFileUploadFinished:t[2]||(t[2]=function(t){return e.$emit("file-upload-finished")})},null,40,["resource-name","resource-id","field","errors","show-help-text","mode","via-resource","via-resource-id","via-relationship","onFieldChanged"])}),128))],2)),[[i.vShow,o.isVisible]])}],["__scopeId","data-v-9a0edbbc"]]);Nova.booting(function(e,t){e.component("index-nova-dependency-container",a),e.component("detail-nova-dependency-container",b),e.component("form-nova-dependency-container",P)})},72:(e,t,n)=>{var i,r=function(){return void 0===i&&(i=Boolean(window&&document&&document.all&&!window.atob)),i},o=function(){var e={};return function(t){if(void 0===e[t]){var n=document.querySelector(t);if(window.HTMLIFrameElement&&n instanceof window.HTMLIFrameElement)try{n=n.contentDocument.head}catch(e){n=null}e[t]=n}return e[t]}}(),a=[];function l(e){for(var t=-1,n=0;n{n.d(t,{A:()=>o});var i=n(314),r=n.n(i)()(function(e){return e[1]});r.push([e.id,".nova-dependency-container[data-v-f5f08646]{transition:all .3s ease}",""]);const o=r},262:(e,t)=>{t.A=(e,t)=>{const n=e.__vccOpts||e;for(const[e,i]of t)n[e]=i;return n}},314:e=>{e.exports=function(e){var t=[];return t.toString=function(){return this.map(function(t){var n=e(t);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n}).join("")},t.i=function(e,n,i){"string"==typeof e&&(e=[[null,e,""]]);var r={};if(i)for(var o=0;o{n.d(t,{A:()=>o});var i=n(314),r=n.n(i)()(function(e){return e[1]});r.push([e.id,".nova-dependency-container[data-v-9a0edbbc]{transition:all .3s ease}",""]);const o=r},835:()=>{}},n={};function i(e){var r=n[e];if(void 0!==r)return r.exports;var o=n[e]={id:e,exports:{}};return t[e](o,o.exports,i),o.exports}i.m=t,e=[],i.O=(t,n,r,o)=>{if(!n){var a=1/0;for(d=0;d=o)&&Object.keys(i.O).every(e=>i.O[e](n[c]))?n.splice(c--,1):(l=!1,o0&&e[d-1][2]>o;d--)e[d]=e[d-1];e[d]=[n,r,o]},i.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return i.d(t,{a:t}),t},i.d=(e,t)=>{for(var n in t)i.o(t,n)&&!i.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={222:0,101:0};i.O.j=t=>0===e[t];var t=(t,n)=>{var r,o,[a,l,c]=n,s=0;if(a.some(t=>0!==e[t])){for(r in l)i.o(l,r)&&(i.m[r]=l[r]);if(c)var d=c(i)}for(t&&t(n);si(66));var r=i.O(void 0,[101],()=>i(835));r=i.O(r)})(); \ No newline at end of file +(()=>{"use strict";var e,t={72:(e,t,n)=>{var r,i=function(){return void 0===r&&(r=Boolean(window&&document&&document.all&&!window.atob)),r},o=function(){var e={};return function(t){if(void 0===e[t]){var n=document.querySelector(t);if(window.HTMLIFrameElement&&n instanceof window.HTMLIFrameElement)try{n=n.contentDocument.head}catch(e){n=null}e[t]=n}return e[t]}}(),a=[];function c(e){for(var t=-1,n=0;n{const r=Vue;const i={props:["resourceName","field"]};var o=n(262);const a=(0,o.A)(i,[["render",function(e,t,n,i,o,a){return(0,r.openBlock)(),(0,r.createElementBlock)("div")}]]);function c(e){return c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},c(e)}function l(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,i,o,a,c=[],l=!0,s=!1;try{if(o=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;l=!1}else for(;!(l=(r=o.call(n)).done)&&(c.push(r.value),c.length!==t);l=!0);}catch(e){s=!0,i=e}finally{try{if(!l&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(s)throw i}}return c}}(e,t)||d(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function s(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=d(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0,i=function(){};return{s:i,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,c=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){c=!0,o=e},f:function(){try{a||null==n.return||n.return()}finally{if(c)throw o}}}}function d(e,t){if(e){if("string"==typeof e)return u(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?u(e,t):void 0}}function u(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0;){var n;if(e.fields&&Array.isArray(e.fields))return e.fields;if(null!==(n=e.$refs)&&void 0!==n&&n.fields&&Array.isArray(e.$refs.fields))return e.$refs.fields.map(function(e){return e.field||e});e=e.$parent}return[]},extractPrefixFromAttribute:function(e){if(!e)return null;var t=e.match(/^(.+__\d+__)/);if(t)return t[1];var n=e.match(/^(.+\[\d+\]\[)/);if(n)return n[1];var r=e.match(/^([a-zA-Z0-9]+__)/);return r?r[1]:null},getFlexibleAttributeFormats:function(e,t){var n=[],r=e.match(/^(.+)__(\d+)__$/),i=e.match(/^(.+)\[(\d+)\]\[$/);if(r){var o=l(r,3),a=o[1],c=o[2];n.push("".concat(a,"[").concat(c,"][").concat(t,"]")),n.push("".concat(a,"_").concat(c,"_").concat(t))}if(i){var s=l(i,3),d=s[1],u=s[2];n.push("".concat(d,"__").concat(u,"__").concat(t)),n.push("".concat(d,"_").concat(u,"_").concat(t))}return n},isEmpty:function(e){return null==e||""===e||Array.isArray(e)&&0===e.length||"object"===c(e)&&0===Object.keys(e).length}}};var h=n(72),v=n.n(h),p=n(254),y={insert:"head",singleton:!1};v()(p.A,y);p.A.locals;const b=(0,o.A)(f,[["render",function(e,t,n,i,o,a){return(0,r.withDirectives)(((0,r.openBlock)(),(0,r.createElementBlock)("div",{class:(0,r.normalizeClass)(a.containerClasses)},[((0,r.openBlock)(!0),(0,r.createElementBlock)(r.Fragment,null,(0,r.renderList)(n.field.fields,function(e,t){return(0,r.openBlock)(),(0,r.createBlock)((0,r.resolveDynamicComponent)("detail-".concat(e.component)),{key:t,"resource-name":n.resourceName,"resource-id":n.resourceId,field:e},null,8,["resource-name","resource-id","field"])}),128))],2)),[[r.vShow,o.isVisible]])}],["__scopeId","data-v-f5f08646"]]);const m=LaravelNova;function x(e){return x="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},x(e)}function g(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,i,o,a,c=[],l=!0,s=!1;try{if(o=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;l=!1}else for(;!(l=(r=o.call(n)).done)&&(c.push(r.value),c.length!==t);l=!0);}catch(e){s=!0,i=e}finally{try{if(!l&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(s)throw i}}return c}}(e,t)||F(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function A(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=F(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0,i=function(){};return{s:i,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,c=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){c=!0,o=e},f:function(){try{a||null==n.return||n.return()}finally{if(c)throw o}}}}function F(e,t){if(e){if("string"==typeof e)return C(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?C(e,t):void 0}}function C(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1)return n;n=n.parentElement,r++}return(null===(e=this.$el)||void 0===e?void 0:e.closest("form"))||(null===(t=this.$el)||void 0===t?void 0:t.closest("[data-field-wrapper]"))||document.body},handleDOMChange:function(e){var t=e.target,n=t.name||t.id||"",r="checkbox"===t.type?t.checked:t.value;if(n){var i=this.extractPrefixFromAttribute(n);if(!this.cachedContextPrefix||!i||i===this.cachedContextPrefix){var o=this.extractBaseAttribute(n);this.field.dependencies.some(function(e){return e.field===o})&&(this.dependentFieldValues[n]=r,this.dependentFieldValues[o]=r,this.checkDependencies())}}},loadInitialValuesFromDOM:function(){if(this.field.dependencies){var e,t=A(this.field.dependencies);try{for(t.s();!(e=t.n()).done;)for(var n=e.value.field,r=this.cachedContextPrefix?"".concat(this.cachedContextPrefix).concat(n):n,i=['[name="'.concat(r,'"]'),'[name="'.concat(n,'"]'),'[id="'.concat(r,'"]'),'[id="'.concat(n,'"]'),'[name$="__'.concat(n,'"]'),'[name$="['.concat(n,']"]')],o=0,a=i;o0;){var r;if(null!==(r=t.$refs)&&void 0!==r&&r.fields&&Array.isArray(t.$refs.fields))return t.$refs.fields;if(t.fields&&Array.isArray(t.fields))return t.fields.map(function(e){return{field:e}});t=t.$parent}return[]},getFlexibleAttributeFormats:function(e,t){var n=[],r=e.match(/^(.+)__(\d+)__$/),i=e.match(/^(.+)\[(\d+)\]\[$/);if(r){var o=g(r,3),a=o[1],c=o[2];n.push("".concat(a,"[").concat(c,"][").concat(t,"]")),n.push("".concat(a,"_").concat(c,"_").concat(t))}if(i){var l=g(i,3),s=l[1],d=l[2];n.push("".concat(s,"__").concat(d,"__").concat(t)),n.push("".concat(s,"_").concat(d,"_").concat(t))}return n},isEmpty:function(e){return null==e||""===e||Array.isArray(e)&&0===e.length||"object"===x(e)&&0===Object.keys(e).length},fill:function(e){var t=this;this.isVisible&&this.field.fields&&this.field.fields.forEach(function(n){var r=t.fieldRefs[n.attribute];r&&"function"==typeof r.fill&&r.fill(e)})}},beforeUnmount:function(){var e=this;Nova.$off("field-changed",this.handleFieldChanged),this.watchedElements&&this.watchedElements.forEach(function(t){t.removeEventListener("change",e.handleDOMChange),t.removeEventListener("input",e.handleDOMChange)}),this.mutationObserver&&this.mutationObserver.disconnect(),this.fieldRefs={}}};var P=n(541),O={insert:"head",singleton:!1};v()(P.A,O);P.A.locals;const k=(0,o.A)(_,[["render",function(e,t,n,i,o,a){return(0,r.withDirectives)(((0,r.openBlock)(),(0,r.createElementBlock)("div",{class:(0,r.normalizeClass)(a.containerClasses)},[((0,r.openBlock)(!0),(0,r.createElementBlock)(r.Fragment,null,(0,r.renderList)(n.field.fields,function(i,o){return(0,r.openBlock)(),(0,r.createBlock)((0,r.resolveDynamicComponent)("form-".concat(i.component)),{key:i.attribute||o,ref_for:!0,ref:function(e){return a.setFieldRef(i.attribute,e)},"resource-name":n.resourceName,"resource-id":n.resourceId,field:i,errors:n.errors,"show-help-text":n.showHelpText,mode:n.mode,"via-resource":n.viaResource,"via-resource-id":n.viaResourceId,"via-relationship":n.viaRelationship,onFieldChanged:a.handleFieldChanged,onFileDeleted:t[0]||(t[0]=function(t){return e.$emit("file-deleted")}),onFileUploadStarted:t[1]||(t[1]=function(t){return e.$emit("file-upload-started")}),onFileUploadFinished:t[2]||(t[2]=function(t){return e.$emit("file-upload-finished")})},null,40,["resource-name","resource-id","field","errors","show-help-text","mode","via-resource","via-resource-id","via-relationship","onFieldChanged"])}),128))],2)),[[r.vShow,o.isVisible]])}],["__scopeId","data-v-0c9307cb"]]);Nova.booting(function(e,t){e.component("index-nova-dependency-container",a),e.component("detail-nova-dependency-container",b),e.component("form-nova-dependency-container",k)})},254:(e,t,n)=>{n.d(t,{A:()=>o});var r=n(314),i=n.n(r)()(function(e){return e[1]});i.push([e.id,".nova-dependency-container[data-v-f5f08646]{transition:all .3s ease}",""]);const o=i},262:(e,t)=>{t.A=(e,t)=>{const n=e.__vccOpts||e;for(const[e,r]of t)n[e]=r;return n}},314:e=>{e.exports=function(e){var t=[];return t.toString=function(){return this.map(function(t){var n=e(t);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n}).join("")},t.i=function(e,n,r){"string"==typeof e&&(e=[[null,e,""]]);var i={};if(r)for(var o=0;o{n.d(t,{A:()=>o});var r=n(314),i=n.n(r)()(function(e){return e[1]});i.push([e.id,".nova-dependency-container[data-v-0c9307cb]{transition:all .3s ease}",""]);const o=i},835:()=>{}},n={};function r(e){var i=n[e];if(void 0!==i)return i.exports;var o=n[e]={id:e,exports:{}};return t[e](o,o.exports,r),o.exports}r.m=t,e=[],r.O=(t,n,i,o)=>{if(!n){var a=1/0;for(d=0;d=o)&&Object.keys(r.O).every(e=>r.O[e](n[l]))?n.splice(l--,1):(c=!1,o0&&e[d-1][2]>o;d--)e[d]=e[d-1];e[d]=[n,i,o]},r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={222:0,101:0};r.O.j=t=>0===e[t];var t=(t,n)=>{var i,o,[a,c,l]=n,s=0;if(a.some(t=>0!==e[t])){for(i in c)r.o(c,i)&&(r.m[i]=c[i]);if(l)var d=l(r)}for(t&&t(n);sr(99));var i=r.O(void 0,[101],()=>r(835));i=r.O(i)})(); \ No newline at end of file diff --git a/resources/js/components/FormField.vue b/resources/js/components/FormField.vue index 546f65e..80f7efa 100644 --- a/resources/js/components/FormField.vue +++ b/resources/js/components/FormField.vue @@ -72,8 +72,6 @@ export default { }, mounted() { - console.log('[NovaDependencyContainer] Mounted with field:', this.field); - console.log('[NovaDependencyContainer] Dependencies:', this.field.dependencies); this.detectFlexibleContextOnMount(); this.applyFlexiblePrefixToChildFields(); this.watchDependentFields(); @@ -103,24 +101,16 @@ export default { return; } - console.log('[NovaDependencyContainer] Applying Flexible prefix to child fields:', this.cachedContextPrefix); - this.field.fields.forEach(childField => { if (!childField.attribute) return; // Check if the attribute already has the prefix if (childField.attribute.startsWith(this.cachedContextPrefix)) { - console.log('[NovaDependencyContainer] Child field already has prefix:', childField.attribute); return; } - // Store original attribute for reference - const originalAttribute = childField.attribute; - // Apply the Flexible prefix childField.attribute = `${this.cachedContextPrefix}${childField.attribute}`; - - console.log('[NovaDependencyContainer] Prefixed child field attribute:', originalAttribute, '->', childField.attribute); }); }, @@ -129,15 +119,11 @@ export default { * This is critical for proper event filtering in multi-group scenarios. */ detectFlexibleContextOnMount() { - console.log('[NovaDependencyContainer] detectFlexibleContextOnMount called'); - // Method 1: Check container's own attribute const ownAttribute = this.field?.attribute || ''; - console.log('[NovaDependencyContainer] Container attribute:', ownAttribute); if (ownAttribute) { const prefix = this.extractPrefixFromAttribute(ownAttribute); if (prefix) { - console.log('[NovaDependencyContainer] Detected context from own attribute:', prefix); this.cachedContextPrefix = prefix; this.contextDetected = true; return; @@ -242,20 +228,20 @@ export default { } }, + /** + * Set up watchers for dependent field changes. + */ watchDependentFields() { if (!this.field.dependencies || this.field.dependencies.length === 0) { - console.log('[NovaDependencyContainer] No dependencies, showing field'); this.isVisible = true; return; } - console.log('[NovaDependencyContainer] Watching for field-changed events'); Nova.$on('field-changed', this.handleFieldChanged); // Also set up DOM-based watching for Flexible fields where Nova events might not work this.$nextTick(() => { this.setupDOMWatching(); - // Try to get initial values from DOM this.loadInitialValuesFromDOM(); }); }, @@ -267,15 +253,11 @@ export default { setupDOMWatching() { if (!this.cachedContextPrefix) return; - // Find the Flexible layout container const flexibleContainer = this.findFlexibleContainer(); if (!flexibleContainer) { - console.log('[NovaDependencyContainer] Could not find Flexible container for DOM watching'); return; } - console.log('[NovaDependencyContainer] Setting up DOM watching on Flexible container'); - // Watch for changes on select, input, and textarea elements const watchElements = flexibleContainer.querySelectorAll('select, input, textarea'); watchElements.forEach(el => { @@ -299,8 +281,7 @@ export default { this.mutationObserver.disconnect(); } - this.mutationObserver = new MutationObserver((mutations) => { - // When DOM changes, re-check dependencies + this.mutationObserver = new MutationObserver(() => { this.loadInitialValuesFromDOM(); }); @@ -354,21 +335,18 @@ export default { const name = element.name || element.id || ''; const value = element.type === 'checkbox' ? element.checked : element.value; - console.log('[NovaDependencyContainer] DOM change detected:', { name, value }); - if (!name) return; // Check if this element belongs to our Flexible context const elementPrefix = this.extractPrefixFromAttribute(name); if (this.cachedContextPrefix && elementPrefix && elementPrefix !== this.cachedContextPrefix) { - return; // Different Flexible group + return; } const baseAttribute = this.extractBaseAttribute(name); const isRelevantField = this.field.dependencies.some(dep => dep.field === baseAttribute); if (isRelevantField) { - console.log('[NovaDependencyContainer] Relevant field changed via DOM:', baseAttribute, '=', value); this.dependentFieldValues[name] = value; this.dependentFieldValues[baseAttribute] = value; this.checkDependencies(); @@ -381,13 +359,10 @@ export default { loadInitialValuesFromDOM() { if (!this.field.dependencies) return; - console.log('[NovaDependencyContainer] Loading initial values from DOM'); - for (const dependency of this.field.dependencies) { const fieldName = dependency.field; const prefixedName = this.cachedContextPrefix ? `${this.cachedContextPrefix}${fieldName}` : fieldName; - // Try to find the element by various selectors const selectors = [ `[name="${prefixedName}"]`, `[name="${fieldName}"]`, @@ -402,7 +377,6 @@ export default { const element = document.querySelector(selector); if (element) { const value = element.type === 'checkbox' ? element.checked : element.value; - console.log('[NovaDependencyContainer] Found initial value from DOM:', selector, '=', value); if (value !== undefined && value !== null && value !== '') { this.dependentFieldValues[element.name || element.id] = value; @@ -418,43 +392,28 @@ export default { } }, + /** + * Handle Nova field-changed events. + */ handleFieldChanged(event) { - console.log('[NovaDependencyContainer] field-changed event received:', event); const fullAttribute = event.field.attribute; const eventPrefix = this.extractPrefixFromAttribute(fullAttribute); const baseAttribute = this.extractBaseAttribute(fullAttribute); - console.log('[NovaDependencyContainer] Event details:', { - fullAttribute, - eventPrefix, - baseAttribute, - value: event.value, - cachedContextPrefix: this.cachedContextPrefix, - contextDetected: this.contextDetected - }); - - // Check if this event is for a field we depend on const isRelevantField = this.field.dependencies.some(dep => dep.field === baseAttribute); - console.log('[NovaDependencyContainer] Is relevant field:', isRelevantField, 'Dependencies:', this.field.dependencies.map(d => d.field)); // If we have a detected context, filter events strictly if (this.contextDetected && this.cachedContextPrefix) { if (eventPrefix && eventPrefix !== this.cachedContextPrefix) { - // Event is from a different Flexible group, ignore it return; } } else if (eventPrefix && isRelevantField) { - // No context detected yet - this relevant event can set our context - // Only claim context from events that match our dependencies this.cachedContextPrefix = eventPrefix; this.contextDetected = true; } - // Store by full attribute (always safe, no cross-contamination) this.dependentFieldValues[fullAttribute] = event.value; - // Only store by base attribute if we're sure about our context - // or if this is a non-Flexible field (no prefix) if (!eventPrefix || (this.contextDetected && this.cachedContextPrefix === eventPrefix)) { this.dependentFieldValues[baseAttribute] = event.value; } @@ -468,25 +427,23 @@ export default { * - "overlay_items__0__field_name" -> "overlay_items__0__" * - "overlay_items[0][field_name]" -> "overlay_items[0][" * - "cSkn6uKpVHMkMLmI__field_name" -> "cSkn6uKpVHMkMLmI__" (random key format) - * - "cSkn6uKpVHMkMLmI__" -> "cSkn6uKpVHMkMLmI__" (prefix only) */ extractPrefixFromAttribute(attribute) { if (!attribute) return null; - // Pattern 1: Double underscore with numeric index (e.g., "overlay_items__0__field_name") + // Pattern 1: Double underscore with numeric index const numericUnderscoreMatch = attribute.match(/^(.+__\d+__)/); if (numericUnderscoreMatch) { return numericUnderscoreMatch[1]; } - // Pattern 2: Bracket format (e.g., "overlay_items[0][field_name]") + // Pattern 2: Bracket format const bracketMatch = attribute.match(/^(.+\[\d+\]\[)/); if (bracketMatch) { return bracketMatch[1]; } - // Pattern 3: Random key format (e.g., "cSkn6uKpVHMkMLmI__field_name" or just "cSkn6uKpVHMkMLmI__") - // This handles nova-flexible-content's random key format + // Pattern 3: Random key format (nova-flexible-content) const randomKeyMatch = attribute.match(/^([a-zA-Z0-9]+__)/); if (randomKeyMatch) { return randomKeyMatch[1]; @@ -505,20 +462,19 @@ export default { extractBaseAttribute(attribute) { if (!attribute) return null; - // Pattern 1: Double underscore with numeric index (e.g., "overlay_items__0__field_name") + // Pattern 1: Double underscore with numeric index const numericUnderscoreMatch = attribute.match(/^.+__\d+__(.+)$/); if (numericUnderscoreMatch) { return numericUnderscoreMatch[1]; } - // Pattern 2: Bracket format (e.g., "overlay_items[0][field_name]") + // Pattern 2: Bracket format const bracketMatch = attribute.match(/^.+\[\d+\]\[(.+)\]$/); if (bracketMatch) { return bracketMatch[1]; } - // Pattern 3: Random key format (e.g., "cSkn6uKpVHMkMLmI__type") - // This handles nova-flexible-content's random key format + // Pattern 3: Random key format (nova-flexible-content) const randomKeyMatch = attribute.match(/^[a-zA-Z0-9]+__(.+)$/); if (randomKeyMatch) { return randomKeyMatch[1]; @@ -527,10 +483,10 @@ export default { return attribute; }, + /** + * Check if all dependencies are satisfied and update visibility. + */ checkDependencies() { - console.log('[NovaDependencyContainer] checkDependencies called'); - console.log('[NovaDependencyContainer] Cached values:', this.dependentFieldValues); - if (!this.field.dependencies || this.field.dependencies.length === 0) { this.isVisible = true; return; @@ -540,7 +496,6 @@ export default { for (const dependency of this.field.dependencies) { const fieldValue = this.getFieldValue(dependency.field); - console.log('[NovaDependencyContainer] Checking dependency:', dependency.field, '=', dependency.value, ', current value:', fieldValue); if (dependency.hasOwnProperty('value')) { if (Array.isArray(dependency.value)) { @@ -586,7 +541,6 @@ export default { } this.isVisible = satisfied; - console.log('[NovaDependencyContainer] Setting isVisible to:', satisfied); if (this.field.applyToFields && this.field.fields) { this.field.fields.forEach(field => { @@ -598,20 +552,20 @@ export default { } }, + /** + * Get the current value of a dependent field. + */ getFieldValue(fieldAttribute) { - // First check exact match in cache if (this.dependentFieldValues.hasOwnProperty(fieldAttribute)) { return this.dependentFieldValues[fieldAttribute]; } - // Check for prefixed version in cache (for Flexible field contexts) if (this.cachedContextPrefix) { const prefixedAttribute = `${this.cachedContextPrefix}${fieldAttribute}`; if (this.dependentFieldValues.hasOwnProperty(prefixedAttribute)) { return this.dependentFieldValues[prefixedAttribute]; } - // Try alternative formats const alternativeFormats = this.getFlexibleAttributeFormats(this.cachedContextPrefix, fieldAttribute); for (const format of alternativeFormats) { if (this.dependentFieldValues.hasOwnProperty(format)) { @@ -620,7 +574,6 @@ export default { } } - // Fallback to finding field in DOM const field = this.findFieldByAttribute(fieldAttribute); if (field) { return field.value; @@ -629,25 +582,24 @@ export default { return null; }, + /** + * Find a field component by its attribute name. + */ findFieldByAttribute(attribute) { const allFields = this.getAllFields(); - // First try exact match const exactMatch = allFields.find(f => f.field && f.field.attribute === attribute); if (exactMatch) { return exactMatch; } - // For Flexible fields: resolve attribute relative to current context if (this.cachedContextPrefix) { - // Try to find field with same prefix (within same Flexible group) const prefixedAttribute = `${this.cachedContextPrefix}${attribute}`; const prefixedMatch = allFields.find(f => f.field && f.field.attribute === prefixedAttribute); if (prefixedMatch) { return prefixedMatch; } - // Also try alternative Flexible attribute formats const alternativeFormats = this.getFlexibleAttributeFormats(this.cachedContextPrefix, attribute); for (const format of alternativeFormats) { const match = allFields.find(f => f.field && f.field.attribute === format); @@ -657,11 +609,9 @@ export default { } } - // Fallback: find any field that ends with the attribute name (for nested contexts) const suffixMatch = allFields.find(f => { if (!f.field || !f.field.attribute) return false; const attr = f.field.attribute; - // Match patterns like: prefix__attribute, prefix[index][attribute] return attr.endsWith(`__${attribute}`) || attr.endsWith(`][${attribute}]`) || attr.endsWith(`[${attribute}]`); @@ -672,24 +622,19 @@ export default { /** * Get all rendered fields from the Nova form. - * Handles both standard Nova forms and nested Flexible field contexts. */ getAllFields() { - // Try Nova's global field reference first if (Nova.$parent?.$refs?.fields) { return Nova.$parent.$refs.fields; } - // Walk up the component tree to find fields let parent = this.$parent; let maxDepth = 10; while (parent && maxDepth-- > 0) { - // Check for fields in parent's refs if (parent.$refs?.fields && Array.isArray(parent.$refs.fields)) { return parent.$refs.fields; } - // Check for fields array directly on parent if (parent.fields && Array.isArray(parent.fields)) { return parent.fields.map(f => ({ field: f })); } @@ -705,21 +650,17 @@ export default { getFlexibleAttributeFormats(prefix, attribute) { const formats = []; - // Extract the base key and index from the prefix const underscoreMatch = prefix.match(/^(.+)__(\d+)__$/); const bracketMatch = prefix.match(/^(.+)\[(\d+)\]\[$/); if (underscoreMatch) { const [, key, index] = underscoreMatch; - // Generate bracket format alternative formats.push(`${key}[${index}][${attribute}]`); - // Single underscore variant formats.push(`${key}_${index}_${attribute}`); } if (bracketMatch) { const [, key, index] = bracketMatch; - // Generate underscore format alternative formats.push(`${key}__${index}__${attribute}`); formats.push(`${key}_${index}_${attribute}`); } @@ -727,6 +668,9 @@ export default { return formats; }, + /** + * Check if a value is empty. + */ isEmpty(value) { return value === null || value === undefined || @@ -735,27 +679,20 @@ export default { (typeof value === 'object' && Object.keys(value).length === 0); }, + /** + * Fill form data with child field values. + */ fill(formData) { - console.log('[NovaDependencyContainer] fill() called, isVisible:', this.isVisible); - console.log('[NovaDependencyContainer] Available fieldRefs:', Object.keys(this.fieldRefs)); - if (!this.isVisible) { - console.log('[NovaDependencyContainer] Not visible, skipping fill'); return; } if (this.field.fields) { this.field.fields.forEach(field => { - // Use Vue 3 function refs stored in fieldRefs object const fieldComponent = this.fieldRefs[field.attribute]; - console.log('[NovaDependencyContainer] Filling field:', field.attribute, 'component:', fieldComponent ? 'found' : 'not found'); - if (fieldComponent && typeof fieldComponent.fill === 'function') { fieldComponent.fill(formData); - console.log('[NovaDependencyContainer] Field filled successfully:', field.attribute); - } else { - console.warn('[NovaDependencyContainer] Could not fill field:', field.attribute, 'ref not found or no fill method'); } }); } @@ -765,7 +702,6 @@ export default { beforeUnmount() { Nova.$off('field-changed', this.handleFieldChanged); - // Clean up DOM watchers if (this.watchedElements) { this.watchedElements.forEach(el => { el.removeEventListener('change', this.handleDOMChange); @@ -773,12 +709,10 @@ export default { }); } - // Disconnect MutationObserver if (this.mutationObserver) { this.mutationObserver.disconnect(); } - // Clean up field refs this.fieldRefs = {}; }, }; diff --git a/src/FieldServiceProvider.php b/src/FieldServiceProvider.php index 703f6f2..1b9e7b9 100644 --- a/src/FieldServiceProvider.php +++ b/src/FieldServiceProvider.php @@ -5,8 +5,6 @@ namespace Iamgerwin\NovaDependencyContainer; use Illuminate\Support\ServiceProvider; -use Laravel\Nova\Events\ServingNova; -use Laravel\Nova\Nova; class FieldServiceProvider extends ServiceProvider { @@ -15,9 +13,14 @@ class FieldServiceProvider extends ServiceProvider */ public function boot(): void { - Nova::serving(function (ServingNova $event): void { - Nova::script('nova-dependency-container', __DIR__ . '/../dist/js/field.js'); - Nova::style('nova-dependency-container', __DIR__ . '/../dist/css/field.css'); + // Only register Nova assets when Nova is available + if (! class_exists(\Laravel\Nova\Nova::class)) { + return; + } + + \Laravel\Nova\Nova::serving(function (mixed $event): void { + \Laravel\Nova\Nova::script('nova-dependency-container', __DIR__ . '/../dist/js/field.js'); + \Laravel\Nova\Nova::style('nova-dependency-container', __DIR__ . '/../dist/css/field.css'); }); }