@@ -12,6 +12,7 @@ import './image-cropper.element.js';
12
12
import './image-cropper-focus-setter.element.js' ;
13
13
import './image-cropper-preview.element.js' ;
14
14
import './image-cropper-field.element.js' ;
15
+ import { UMB_VALIDATION_EMPTY_LOCALIZATION_KEY , UmbFormControlMixin } from '@umbraco-cms/backoffice/validation' ;
15
16
16
17
const DefaultFocalPoint = { left : 0.5 , top : 0.5 } ;
17
18
const DefaultValue = {
@@ -22,12 +23,23 @@ const DefaultValue = {
22
23
} ;
23
24
24
25
@customElement ( 'umb-input-image-cropper' )
25
- export class UmbInputImageCropperElement extends UmbLitElement {
26
+ export class UmbInputImageCropperElement extends UmbFormControlMixin <
27
+ UmbImageCropperPropertyEditorValue ,
28
+ typeof UmbLitElement ,
29
+ undefined
30
+ > ( UmbLitElement , undefined ) {
26
31
@query ( '#dropzone' )
27
32
private _dropzone ?: UUIFileDropzoneElement ;
28
33
29
- @property ( { attribute : false } )
30
- value : UmbImageCropperPropertyEditorValue = DefaultValue ;
34
+ /**
35
+ * Sets the input to required, meaning validation will fail if the value is empty.
36
+ * @type {boolean }
37
+ */
38
+ @property ( { type : Boolean } )
39
+ required ?: boolean ;
40
+
41
+ @property ( { type : String } )
42
+ requiredMessage ?: string ;
31
43
32
44
@property ( { attribute : false } )
33
45
crops : UmbImageCropperPropertyEditorValue [ 'crops' ] = [ ] ;
@@ -43,6 +55,14 @@ export class UmbInputImageCropperElement extends UmbLitElement {
43
55
constructor ( ) {
44
56
super ( ) ;
45
57
this . #manager = new UmbTemporaryFileManager ( this ) ;
58
+
59
+ this . addValidator (
60
+ 'valueMissing' ,
61
+ ( ) => this . requiredMessage ?? UMB_VALIDATION_EMPTY_LOCALIZATION_KEY ,
62
+ ( ) => {
63
+ return ! ! this . required && ( ! this . value || ( this . value . src === '' && this . value . temporaryFileId == null ) ) ;
64
+ } ,
65
+ ) ;
46
66
}
47
67
48
68
protected override firstUpdated ( ) : void {
@@ -57,7 +77,7 @@ export class UmbInputImageCropperElement extends UmbLitElement {
57
77
this . file = file ;
58
78
this . fileUnique = unique ;
59
79
60
- this . value = assignToFrozenObject ( this . value , { temporaryFileId : unique } ) ;
80
+ this . value = assignToFrozenObject ( this . value ?? DefaultValue , { temporaryFileId : unique } ) ;
61
81
62
82
this . #manager?. uploadOne ( { temporaryUnique : unique , file } ) ;
63
83
@@ -71,7 +91,7 @@ export class UmbInputImageCropperElement extends UmbLitElement {
71
91
}
72
92
73
93
#onRemove = ( ) => {
74
- this . value = assignToFrozenObject ( this . value , DefaultValue ) ;
94
+ this . value = undefined ;
75
95
if ( this . fileUnique ) {
76
96
this . #manager?. removeOne ( this . fileUnique ) ;
77
97
}
@@ -82,25 +102,27 @@ export class UmbInputImageCropperElement extends UmbLitElement {
82
102
} ;
83
103
84
104
#mergeCrops( ) {
85
- // Replace crops from the value with the crops from the config while keeping the coordinates from the value if they exist.
86
- const filteredCrops = this . crops . map ( ( crop ) => {
87
- const cropFromValue = this . value . crops . find ( ( valueCrop ) => valueCrop . alias === crop . alias ) ;
88
- const result = {
89
- ...crop ,
90
- coordinates : cropFromValue ?. coordinates ?? undefined ,
105
+ if ( this . value ) {
106
+ // Replace crops from the value with the crops from the config while keeping the coordinates from the value if they exist.
107
+ const filteredCrops = this . crops . map ( ( crop ) => {
108
+ const cropFromValue = this . value ! . crops . find ( ( valueCrop ) => valueCrop . alias === crop . alias ) ;
109
+ const result = {
110
+ ...crop ,
111
+ coordinates : cropFromValue ?. coordinates ?? undefined ,
112
+ } ;
113
+
114
+ return result ;
115
+ } ) ;
116
+
117
+ this . value = {
118
+ ...this . value ,
119
+ crops : filteredCrops ,
91
120
} ;
92
-
93
- return result ;
94
- } ) ;
95
-
96
- this . value = {
97
- ...this . value ,
98
- crops : filteredCrops ,
99
- } ;
121
+ }
100
122
}
101
123
102
124
override render ( ) {
103
- if ( this . value . src || this . file ) {
125
+ if ( this . value ? .src || this . file ) {
104
126
return this . #renderImageCropper( ) ;
105
127
}
106
128
@@ -119,7 +141,7 @@ export class UmbInputImageCropperElement extends UmbLitElement {
119
141
const value = ( e . target as UmbInputImageCropperFieldElement ) . value ;
120
142
121
143
if ( ! value ) {
122
- this . value = DefaultValue ;
144
+ this . value = undefined ;
123
145
this . dispatchEvent ( new UmbChangeEvent ( ) ) ;
124
146
return ;
125
147
}
@@ -128,7 +150,9 @@ export class UmbInputImageCropperElement extends UmbLitElement {
128
150
value . temporaryFileId = this . value . temporaryFileId ;
129
151
}
130
152
131
- this . value = value ;
153
+ if ( value . temporaryFileId || value . src !== '' ) {
154
+ this . value = value ;
155
+ }
132
156
this . dispatchEvent ( new UmbChangeEvent ( ) ) ;
133
157
}
134
158
0 commit comments