Skip to content

Commit 91db741

Browse files
authored
Merge pull request #2037 from umbraco/v14/feature/media-picker-cropper-editor-modal-ui
V14/feature/media picker cropper editor modal UI
2 parents 8606a34 + 5a95979 commit 91db741

File tree

6 files changed

+167
-31
lines changed

6 files changed

+167
-31
lines changed

src/packages/media/media/components/input-image-cropper/image-cropper-field.element.ts

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export class UmbInputImageCropperFieldElement extends UmbLitElement {
7979
}
8080
}
8181

82-
#onCropClick(crop: any) {
82+
protected onCropClick(crop: any) {
8383
const index = this.crops.findIndex((c) => c.alias === crop.alias);
8484

8585
if (index === -1) return;
@@ -117,19 +117,19 @@ export class UmbInputImageCropperFieldElement extends UmbLitElement {
117117
this.dispatchEvent(new UmbChangeEvent());
118118
}
119119

120-
#onResetFocalPoint = () => {
120+
protected onResetFocalPoint = () => {
121121
this.focalPoint = { left: 0.5, top: 0.5 };
122122
this.#updateValue();
123123
};
124124

125125
override render() {
126126
return html`
127-
<div id="main">${this.#renderMain()}</div>
128-
<div id="side">${this.#renderSide()}</div>
127+
<div id="main">${this.renderMain()}</div>
128+
<div id="side">${this.renderSide()}</div>
129129
`;
130130
}
131131

132-
#renderMain() {
132+
protected renderMain() {
133133
if (this.currentCrop) {
134134
return html`
135135
<umb-image-cropper
@@ -149,28 +149,30 @@ export class UmbInputImageCropperFieldElement extends UmbLitElement {
149149
?hideFocalPoint=${this.hideFocalPoint}
150150
@change=${this.#onFocalPointChange}>
151151
</umb-image-cropper-focus-setter>
152-
<div id="actions">
153-
<slot name="actions"></slot>
154-
${when(
155-
!this.hideFocalPoint,
156-
() =>
157-
html`<uui-button
158-
label=${this.localize.term('content_resetFocalPoint')}
159-
@click=${this.#onResetFocalPoint}></uui-button>`,
160-
)}
161-
</div>
152+
<div id="actions">${this.renderActions()}</div>
162153
`;
163154
}
164155

165-
#renderSide() {
156+
protected renderActions() {
157+
return html`<slot name="actions"></slot>
158+
${when(
159+
!this.hideFocalPoint,
160+
() =>
161+
html`<uui-button
162+
label=${this.localize.term('content_resetFocalPoint')}
163+
@click=${this.onResetFocalPoint}></uui-button>`,
164+
)} `;
165+
}
166+
167+
protected renderSide() {
166168
if (!this.value || !this.crops) return;
167169

168170
return repeat(
169171
this.crops,
170172
(crop) => crop.alias + JSON.stringify(crop.coordinates),
171173
(crop) =>
172174
html` <umb-image-cropper-preview
173-
@click=${() => this.#onCropClick(crop)}
175+
@click=${() => this.onCropClick(crop)}
174176
.crop=${crop}
175177
.focalPoint=${this.focalPoint}
176178
.src=${this.source}></umb-image-cropper-preview>`,
@@ -184,6 +186,7 @@ export class UmbInputImageCropperFieldElement extends UmbLitElement {
184186
gap: var(--uui-size-space-3);
185187
height: 400px;
186188
}
189+
187190
#main {
188191
max-width: 500px;
189192
min-width: 300px;
@@ -193,13 +196,16 @@ export class UmbInputImageCropperFieldElement extends UmbLitElement {
193196
gap: var(--uui-size-space-1);
194197
flex-direction: column;
195198
}
199+
196200
#actions {
197201
display: flex;
198202
justify-content: space-between;
199203
}
204+
200205
umb-image-cropper-focus-setter {
201206
height: calc(100% - 33px - var(--uui-size-space-1)); /* Temp solution to make room for actions */
202207
}
208+
203209
#side {
204210
display: grid;
205211
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));

src/packages/media/media/components/input-image-cropper/image-cropper-preview.element.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ export class UmbImageCropperPreviewElement extends LitElement {
1313
@property({ type: String, attribute: false })
1414
src: string = '';
1515

16+
@property({ type: String })
17+
label?: string;
18+
1619
@property({ attribute: false })
1720
get focalPoint() {
1821
return this.#focalPoint;
@@ -140,14 +143,14 @@ export class UmbImageCropperPreviewElement extends LitElement {
140143

141144
override render() {
142145
if (!this.crop) {
143-
return nothing;
146+
return html`<span id="label">${this.label}</span>`;
144147
}
145148

146149
return html`
147150
<div id="container">
148151
<img id="image" src=${this.src} alt="" />
149152
</div>
150-
<span id="alias">${this.crop.alias}</span>
153+
<span id="alias">${this.label ?? this.crop.alias}</span>
151154
<span id="dimensions">${this.crop.width} x ${this.crop.height}</span>
152155
${this.crop.coordinates
153156
? html`<span id="user-defined"><umb-localize key="imagecropper_customCrop">User defined</umb-localize></span>`
@@ -178,6 +181,9 @@ export class UmbImageCropperPreviewElement extends LitElement {
178181
max-height: 200px;
179182
user-select: none;
180183
}
184+
#label {
185+
font-weight: bold;
186+
}
181187
#alias {
182188
font-weight: bold;
183189
margin-top: var(--uui-size-space-3);
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { UmbInputImageCropperFieldElement } from '../../../components/input-image-cropper/image-cropper-field.element.js';
2+
import { css, customElement, html, repeat, when } from '@umbraco-cms/backoffice/external/lit';
3+
4+
@customElement('umb-image-cropper-editor-field')
5+
export class UmbImageCropperEditorFieldElement extends UmbInputImageCropperFieldElement {
6+
#resetCurrentCrop() {
7+
this.currentCrop = undefined;
8+
}
9+
10+
override renderActions() {
11+
return html`
12+
<slot name="actions"></slot>
13+
${when(
14+
!this.hideFocalPoint,
15+
() => html`
16+
<uui-button
17+
compact
18+
id="reset-focal-point"
19+
label=${this.localize.term('content_resetFocalPoint')}
20+
@click=${this.onResetFocalPoint}>
21+
<uui-icon name="icon-axis-rotation"></uui-icon>
22+
${this.localize.term('content_resetFocalPoint')}
23+
</uui-button>
24+
`,
25+
)}
26+
`;
27+
}
28+
29+
override renderSide() {
30+
if (!this.value || !this.crops) return;
31+
32+
return html` <umb-image-cropper-preview
33+
@click=${this.#resetCurrentCrop}
34+
?active=${!this.currentCrop}
35+
.label=${this.localize.term('general_media')}></umb-image-cropper-preview>
36+
37+
${repeat(
38+
this.crops,
39+
(crop) => crop.alias + JSON.stringify(crop.coordinates),
40+
(crop) => html`
41+
<umb-image-cropper-preview
42+
?active=${this.currentCrop?.alias === crop.alias}
43+
@click=${() => this.onCropClick(crop)}
44+
.crop=${crop}
45+
.focalPoint=${this.focalPoint}
46+
.src=${this.source}></umb-image-cropper-preview>
47+
`,
48+
)}`;
49+
}
50+
51+
static override styles = css`
52+
:host {
53+
display: flex;
54+
width: 100%;
55+
box-sizing: border-box;
56+
gap: var(--uui-size-space-3);
57+
height: 400px;
58+
}
59+
60+
#main {
61+
width: 100%;
62+
height: 100%;
63+
display: flex;
64+
gap: var(--uui-size-space-1);
65+
flex-direction: column;
66+
}
67+
68+
#actions {
69+
display: flex;
70+
justify-content: space-between;
71+
}
72+
73+
#reset-focal-point uui-icon {
74+
padding-right: var(--uui-size-3);
75+
}
76+
77+
slot[name='actions'] {
78+
display: block;
79+
flex: 1;
80+
}
81+
82+
#reset-current-crop[active],
83+
[active] {
84+
background-color: var(--uui-color-current);
85+
}
86+
87+
umb-image-cropper-focus-setter {
88+
height: calc(100% - 33px - var(--uui-size-space-1)); /* Temp solution to make room for actions */
89+
}
90+
91+
#side {
92+
display: grid;
93+
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
94+
flex: none;
95+
gap: var(--uui-size-space-3);
96+
flex-grow: 1;
97+
overflow-y: auto;
98+
height: fit-content;
99+
max-height: 100%;
100+
}
101+
`;
102+
}
103+
104+
declare global {
105+
interface HTMLElementTagNameMap {
106+
'umb-image-cropper-editor-field': UmbImageCropperEditorFieldElement;
107+
}
108+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './image-cropper-editor-field.element.js';

src/packages/media/media/modals/image-cropper-editor/image-cropper-editor-modal.element.ts

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { css, customElement, html, state } from '@umbraco-cms/backoffice/externa
1111
import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router';
1212
import { UMB_MODAL_MANAGER_CONTEXT, UMB_WORKSPACE_MODAL, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
1313
import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal';
14+
import './components/image-cropper-editor-field.element.js';
1415

1516
/** TODO Make some of the components from property editor image cropper reuseable for this modal... */
1617

@@ -131,20 +132,22 @@ export class UmbImageCropperEditorModalElement extends UmbModalBaseElement<
131132
#renderBody() {
132133
return html`
133134
<div id="layout">
134-
<umb-image-cropper-field
135+
<umb-image-cropper-editor-field
135136
.value=${this._imageCropperValue}
136137
?hideFocalPoint=${this._hideFocalPoint}
137-
@change=${this.#onChange}></umb-image-cropper-field>
138-
<div id="options">
139-
<uui-menu-item @click=${this.#openMediaPicker} label=${this.localize.term('mediaPicker_changeMedia')}>
140-
<umb-icon slot="icon" name="icon-search"></umb-icon>
141-
</uui-menu-item>
142-
<uui-menu-item
143-
href=${this._editMediaPath + 'edit/' + this._unique}
144-
label=${this.localize.term('mediaPicker_openMedia')}>
145-
<umb-icon slot="icon" name="icon-out"></umb-icon>
146-
</uui-menu-item>
147-
</div>
138+
@change=${this.#onChange}>
139+
<div id="actions" slot="actions">
140+
<uui-button compact @click=${this.#openMediaPicker} label=${this.localize.term('mediaPicker_changeMedia')}>
141+
<uui-icon name="icon-search"></uui-icon>${this.localize.term('mediaPicker_changeMedia')}
142+
</uui-button>
143+
<uui-button
144+
compact
145+
href=${this._editMediaPath + 'edit/' + this._unique}
146+
label=${this.localize.term('mediaPicker_openMedia')}>
147+
<uui-icon name="icon-out"></uui-icon>${this.localize.term('mediaPicker_openMedia')}
148+
</uui-button>
149+
</div>
150+
</umb-image-cropper-editor-field>
148151
</div>
149152
`;
150153
}
@@ -157,6 +160,17 @@ export class UmbImageCropperEditorModalElement extends UmbModalBaseElement<
157160
flex-direction: column;
158161
justify-content: space-between;
159162
}
163+
umb-image-cropper-editor-field {
164+
flex-grow: 1;
165+
}
166+
167+
#actions {
168+
display: inline-flex;
169+
gap: var(--uui-size-space-3);
170+
}
171+
uui-icon {
172+
padding-right: var(--uui-size-3);
173+
}
160174
161175
#options {
162176
display: flex;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
export * from './components/index.js';
12
export * from './image-cropper-editor-modal.element.js';
23
export * from './image-cropper-editor-modal.token.js';

0 commit comments

Comments
 (0)