From a156b8dcfae01d2bbf1b0db5ffc807eef6174e21 Mon Sep 17 00:00:00 2001
From: Mostafa Zeinivand
+
+The `image-model` configuration option allows you to specify the path of your **image** model within your Laravel application. This configuration determines which image model will be used for handling images within the CKEditor field.
+
+By default, the `image-model` configuration option is set to `App\Models\Image`, assuming that you have a `Image` model located in the `app/Models` directory of your application. However, you can customize this path to match the location of your own image model.
+
+To configure the `image-model` option, update the value in the configuration file `config/nova-ckeditor.php` with the desired path to your image model.
+
diff --git a/docs/advanced-usage/integrating-novafileartisan-larupload-with-image-resource.md b/docs/advanced-usage/integrating-novafileartisan-larupload-with-image-resource.md
new file mode 100644
index 0000000..27492ee
--- /dev/null
+++ b/docs/advanced-usage/integrating-novafileartisan-larupload-with-image-resource.md
@@ -0,0 +1,137 @@
+---
+description: Since v6.1.0
+---
+
+# Integrating NovaFileArtisan (Larupload) with Image Resource
+
+To enhance your Nova application's image handling capabilities, you can seamlessly integrate [NovaFileArtisan](https://github.com/mostafaznv/nova-file-artisan), a feature-rich file uploader package that serves as a wrapper for [Larupload](https://github.com/mostafaznv/larupload). Follow these steps to incorporate NovaFileArtisan into your Image Resource:
+
+
+
+1. Install NovaFileArtisan and Larupload packages:
+
+```sh
+composer require mostafaznv/nova-file-artisan
+```
+
+2. Modify your images table schema:
+
+```php
+id();
+ $table->string('name')->index();
+ $table->upload('file');
+ $table->timestamps();
+ });
+ }
+
+
+ public function down(): void
+ {
+ Schema::drop('images');
+ }
+};
+```
+
+3. Apply the Larupload trait to your Image model:
+
+```php
+name) {
+ $name = $model->file->meta('name');
+
+ $model->name = pathinfo($name, PATHINFO_FILENAME);
+ }
+ });
+ }
+
+ public function attachments(): array
+ {
+ return [
+ Attachment::make('file')
+ ->disk('image')
+ ->namingMethod(LaruploadNamingMethod::HASH_FILE)
+ ->coverStyle('cover', 500, 500, LaruploadMediaStyle::CROP),
+ ];
+ }
+}
+```
+
+4. Replace ImageUpload with NovaFileArtisan field in your Nova resource:
+
+```php
+showOnPreview()
+ ->help(trans('The file name that should be searched'))
+ ->sortable(),
+
+ NovaFileArtisan::make('File', 'file')
+ ->showOnPreview()
+ ->rules('required', 'mimes:jpg,jpeg,png,gif,webp', 'max:5000')
+ ->help(trans(':size Megabyte Max FileSize.', ['size' => 5])),
+
+ ...NovaFileArtisanMeta::make('file')->all(),
+ ];
+ }
+}
+```
+
+5. You're Done!
+
+
+
+These steps empower your Nova application with advanced file handling capabilities using NovaFileArtisan. Feel free to explore additional features and customization options offered by Larupload and NovaFileArtisan.
From 15658ca03d6031c9c9147281fbe1ead4a2a64638 Mon Sep 17 00:00:00 2001
From: mostafaznv Property Name Type Default image-model string App\Models\Image
0?t[e-1]:null,l=e+1
{this._updateLastFocusedEditableElement(),i?this._showBalloon():this._hideBalloon()})),e.ui.focusTracker.on("change:focusedElement",((e,t,i)=>{this._updateLastFocusedEditableElement(),i&&this._showBalloon()})),e.ui.on("update",(()=>{this._showBalloonThrottled()})))}_createBalloonView(){const e=this.editor,t=this._balloonView=new Xf,i=fp(e),n=new hp(e.locale,i.label);t.content.add(n),t.set({class:"ck-powered-by-balloon"}),e.ui.view.body.add(t),e.ui.focusTracker.add(t.element),this._balloonView=t}_showBalloon(){if(!this._lastFocusedEditableElement)return;const e=function(e,t){const i=fp(e),n="right"===i.side?function(e,t){return mp(e,t,((e,i)=>e.left+e.width-i.width-t.horizontalOffset))}(t,i):function(e,t){return mp(e,t,(e=>e.left+t.horizontalOffset))}(t,i);return{target:t,positions:[n]}}(this.editor,this._lastFocusedEditableElement);e&&(this._balloonView||this._createBalloonView(),this._balloonView.pin(e))}_hideBalloon(){this._balloonView&&this._balloonView.unpin()}_updateLastFocusedEditableElement(){const e=this.editor,t=e.ui.focusTracker.isFocused,i=e.ui.focusTracker.focusedElement;if(!t||!i)return void(this._lastFocusedEditableElement=null);const n=Array.from(e.ui.getEditableElementsNames()).map((t=>e.ui.getEditableElement(t)));n.includes(i)?this._lastFocusedEditableElement=i:this._lastFocusedEditableElement=n[0]}}class hp extends Yo{constructor(e,t){super(e);const i=new vr,n=this.bindTemplate;i.set({content:'\n',isColorInherited:!1}),i.extendTemplate({attributes:{style:{width:"53px",height:"10px"}}}),this.setTemplate({tag:"div",attributes:{class:["ck","ck-powered-by"],"aria-hidden":!0},children:[{tag:"a",attributes:{href:"https://ckeditor.com/?utm_source=ckeditor&utm_medium=referral&utm_campaign=701Dn000000hVgmIAE_powered_by_ckeditor_logo",target:"_blank",tabindex:"-1"},children:[...t?[{tag:"span",attributes:{class:["ck","ck-powered-by__label"]},children:[t]}]:[],i],on:{dragstart:n.to((e=>e.preventDefault()))}}]})}}function mp(e,t,i){return(n,o)=>{const r=new Fn(e);if(r.width
").replace(/\r?\n/g,"
").replace(/\t/g," ").replace(/^\s/," ").replace(/\s$/," ").replace(/\s\s/g," ")).includes("
")||r.includes("
"))&&(r=`
${r}
`),e=r),o=this.editor.data.htmlProcessor.toView(e)}var r;const s=new g(this,"inputTransformation");this.fire(s,{content:o,dataTransfer:n,targetRanges:t.targetRanges,method:t.method}),s.stop.called&&e.stop(),i.scrollToTheSelection()}),{priority:"low"}),this.listenTo(this,"inputTransformation",((e,i)=>{if(i.content.isEmpty)return;const n=this.editor.data.toModel(i.content,"$clipboardHolder");0!=n.childCount&&(e.stop(),t.change((()=>{this.fire("contentInsertion",{content:n,method:i.method,dataTransfer:i.dataTransfer,targetRanges:i.targetRanges})})))}),{priority:"low"}),this.listenTo(this,"contentInsertion",((e,i)=>{i.resultRange=t.insertContent(i.content)}),{priority:"low"})}_setupCopyCut(){const e=this.editor,t=e.model.document,i=e.editing.view.document,n=(e,i)=>{const n=i.dataTransfer;i.preventDefault(),this._fireOutputTransformationEvent(n,t.selection,e.name)};this.listenTo(i,"copy",n,{priority:"low"}),this.listenTo(i,"cut",((t,i)=>{e.model.canEditAt(e.model.document.selection)?n(t,i):i.preventDefault()}),{priority:"low"}),this.listenTo(this,"outputTransformation",((t,n)=>{const o=e.data.toView(n.content);i.fire("clipboardOutput",{dataTransfer:n.dataTransfer,content:o,method:n.method})}),{priority:"low"}),this.listenTo(i,"clipboardOutput",((i,n)=>{n.content.isEmpty||(n.dataTransfer.setData("text/html",this.editor.data.htmlProcessor.toData(n.content)),n.dataTransfer.setData("text/plain",Pk(n.content))),"cut"==n.method&&e.model.deleteContent(t.selection)}),{priority:"low"})}}const Ok=Gn("px");class Mk extends Yo{constructor(){super();const e=this.bindTemplate;this.set({isVisible:!1,left:null,top:null,width:null}),this.setTemplate({tag:"div",attributes:{class:["ck","ck-clipboard-drop-target-line",e.if("isVisible","ck-hidden",(e=>!e))],style:{left:e.to("left",(e=>Ok(e))),top:e.to("top",(e=>Ok(e))),width:e.to("width",(e=>Ok(e)))}}})}}class Rk extends As{constructor(){super(...arguments),this.removeDropMarkerDelayed=Mo((()=>this.removeDropMarker()),40),this._updateDropMarkerThrottled=ap((e=>this._updateDropMarker(e)),40),this._reconvertMarkerThrottled=ap((()=>{this.editor.model.markers.has("drop-target")&&this.editor.editing.reconvertMarker("drop-target")}),0),this._dropTargetLineView=new Mk,this._domEmitter=new(On()),this._scrollables=new Map}static get pluginName(){return"DragDropTarget"}init(){this._setupDropMarker()}destroy(){this._domEmitter.stopListening();for(const{resizeObserver:e}of this._scrollables.values())e.destroy();return this._updateDropMarkerThrottled.cancel(),this.removeDropMarkerDelayed.cancel(),this._reconvertMarkerThrottled.cancel(),super.destroy()}updateDropMarker(e,t,i,n,o){this.removeDropMarkerDelayed.cancel();const r=Nk(this.editor,e,t,i,n,o);r&&this._updateDropMarkerThrottled(r)}getFinalDropRange(e,t,i,n,o){const r=Nk(this.editor,e,t,i,n,o);return this.removeDropMarker(),r}removeDropMarker(){const e=this.editor.model;this.removeDropMarkerDelayed.cancel(),this._updateDropMarkerThrottled.cancel(),this._dropTargetLineView.isVisible=!1,e.markers.has("drop-target")&&e.change((e=>{e.removeMarker("drop-target")}))}_setupDropMarker(){const e=this.editor;e.ui.view.body.add(this._dropTargetLineView),e.conversion.for("editingDowncast").markerToHighlight({model:"drop-target",view:{classes:["ck-clipboard-drop-target-range"]}}),e.conversion.for("editingDowncast").markerToElement({model:"drop-target",view:(t,{writer:i})=>{if(e.model.schema.checkChild(t.markerRange.start,"$text"))return this._dropTargetLineView.isVisible=!1,this._createDropTargetPosition(i);t.markerRange.isCollapsed?this._updateDropTargetLine(t.markerRange):this._dropTargetLineView.isVisible=!1}})}_updateDropMarker(e){const t=this.editor,i=t.model.markers;t.model.change((t=>{i.has("drop-target")?i.get("drop-target").getRange().isEqual(e)||t.updateMarker("drop-target",{range:e}):t.addMarker("drop-target",{range:e,usingOperation:!1,affectsData:!1})}))}_createDropTargetPosition(e){return e.createUIElement("span",{class:"ck ck-clipboard-drop-target-position"},(function(e){const t=this.toDomElement(e);return t.append("",e.createElement("span"),""),t}))}_updateDropTargetLine(e){const t=this.editor.editing,i=e.start.nodeBefore,n=e.start.nodeAfter,o=e.start.parent,r=i?t.mapper.toViewElement(i):null,s=r?t.view.domConverter.mapViewToDom(r):null,a=n?t.mapper.toViewElement(n):null,l=a?t.view.domConverter.mapViewToDom(a):null,c=t.mapper.toViewElement(o),d=t.view.domConverter.mapViewToDom(c),u=this._getScrollableRect(c),{scrollX:h,scrollY:m}=Vn.window,f=s?new Fn(s):null,p=l?new Fn(l):null,g=new Fn(d).excludeScrollbarsAndBorders(),b=f?f.bottom:g.top,w=p?p.top:g.bottom,k=Vn.window.getComputedStyle(d),_=b<=w?(b+w)/2:w;if(u.top<_&&_