Skip to content

Commit e62e55d

Browse files
leekelleherCopilotiOvergaard
authored
Media Picker Modal File Previews (#19335)
* Ordered `@property` setters/getters * JSDocs + comments * Removed unneeded CSS * Markup code formatting * Hides "Reset focal point" button when focal point has default value * Image Cropper field element: adds active state to crops * Image Cropper Editor Field element: reduced the markup and styles Removing duplications from inherited class * Removed unused code from Image Cropper Focus Setter element * Big refactor of Image Cropper Editor modal to support File Upload Previews * Added `<umb-file-upload-preview>` to handle the logic of rendering the relevant `fileUploadPreview` extension. * Refactored SVG File Upload Preview component Removes the `<uui-card-media>` container. Controversially removes the link, but this was inconsistent with other file previews. * Refactored General File Upload Preview component Removes the `<uui-card-media>` container. Controversially removes the link, but this was inconsistent with other file previews. * Refactored Image File Upload Preview component Removes the `<uui-card-media>` container. Controversially removes the link, but this was inconsistent with other file previews. * Refactored Audio and Video File Upload Preview component To align code with the other file previews. * Update src/Umbraco.Web.UI.Client/src/packages/media/media/modals/image-cropper-editor/image-cropper-editor-modal.element.ts Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]> Co-authored-by: Jacob Overgaard <[email protected]>
1 parent 76fcb4a commit e62e55d

File tree

18 files changed

+406
-307
lines changed

18 files changed

+406
-307
lines changed

src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,14 @@ export class UmbExtensionSlotElement extends UmbLitElement {
3939
* <umb-extension-slot .type=${['my-extension-type','another-extension-type']}></umb-extension-slot>
4040
*/
4141
@property({ type: String })
42-
public get type(): string | string[] | undefined {
43-
return this.#type;
44-
}
4542
public set type(value: string | string[] | undefined) {
4643
if (value === this.#type) return;
4744
this.#type = value;
4845
this.#observeExtensions();
4946
}
47+
public get type(): string | string[] | undefined {
48+
return this.#type;
49+
}
5050
#type?: string | string[] | undefined;
5151

5252
/**
@@ -58,14 +58,14 @@ export class UmbExtensionSlotElement extends UmbLitElement {
5858
* <umb-extension-slot type="my-extension-type" .filter=${(ext) => ext.meta.anyPropToFilter === 'foo'}></umb-extension-slot>
5959
*/
6060
@property({ type: Object, attribute: false })
61-
public get filter(): (manifest: any) => boolean {
62-
return this.#filter;
63-
}
6461
public set filter(value: (manifest: any) => boolean) {
6562
if (value === this.#filter) return;
6663
this.#filter = value;
6764
this.#observeExtensions();
6865
}
66+
public get filter(): (manifest: any) => boolean {
67+
return this.#filter;
68+
}
6969
#filter: (manifest: any) => boolean = () => true;
7070

7171
/**
@@ -77,15 +77,15 @@ export class UmbExtensionSlotElement extends UmbLitElement {
7777
* <umb-extension-slot type="my-extension-type" .props=${{foo: 'bar'}}></umb-extension-slot>
7878
*/
7979
@property({ type: Object, attribute: false })
80-
get props(): Record<string, unknown> | undefined {
81-
return this.#props;
82-
}
8380
set props(newVal: Record<string, unknown> | undefined) {
8481
this.#props = newVal;
8582
if (this.#extensionsController) {
8683
this.#extensionsController.properties = newVal;
8784
}
8885
}
86+
get props(): Record<string, unknown> | undefined {
87+
return this.#props;
88+
}
8989
#props?: Record<string, unknown> = {};
9090

9191
@property({ type: String, attribute: 'default-element' })

src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/config/config.repository.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export class UmbTemporaryFileConfigRepository extends UmbRepositoryBase implemen
4444

4545
/**
4646
* Subscribe to the entire configuration.
47+
* @returns {Observable<UmbTemporaryFileConfigurationModel>}
4748
*/
4849
all() {
4950
if (!this.#dataStore) {
@@ -56,6 +57,7 @@ export class UmbTemporaryFileConfigRepository extends UmbRepositoryBase implemen
5657
/**
5758
* Subscribe to a part of the configuration.
5859
* @param part
60+
* @returns {Observable<UmbTemporaryFileConfigurationModel[Part]>}
5961
*/
6062
part<Part extends keyof UmbTemporaryFileConfigurationModel>(
6163
part: Part,

src/Umbraco.Web.UI.Client/src/packages/media/imaging/components/imaging-thumbnail.element.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,8 @@ export class UmbImagingThumbnailElement extends UmbLitElement {
9999

100100
return when(
101101
this._thumbnailUrl,
102-
() =>
103-
html`<img
104-
id="figure"
105-
src="${this._thumbnailUrl}"
106-
alt="${this.alt}"
107-
loading="${this.loading}"
108-
draggable="false" />`,
109-
() => html`<umb-icon id="icon" name="${this.icon}"></umb-icon>`,
102+
(url) => html`<img id="figure" src=${url} alt=${this.alt} loading=${this.loading} draggable="false" />`,
103+
() => html`<umb-icon id="icon" name=${this.icon}></umb-icon>`,
110104
);
111105
}
112106

src/Umbraco.Web.UI.Client/src/packages/media/media/collection/media-collection.context.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export class UmbMediaCollectionContext extends UmbDefaultCollectionContext<
1111
> {
1212
/**
1313
* The thumbnail items that are currently displayed in the collection.
14-
* @deprecated Use the `<umb-imaging-thumbnail>` element instead.
14+
* @deprecated Use the `<umb-imaging-thumbnail>` element instead. This will be removed in Umbraco 17.
1515
*/
1616
public readonly thumbnailItems = this.items;
1717

src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper-field.element.ts

Lines changed: 69 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -175,69 +175,91 @@ export class UmbInputImageCropperFieldElement extends UmbLitElement {
175175
}
176176

177177
protected renderActions() {
178-
return html`<slot name="actions"></slot>
178+
return html`
179+
<slot name="actions"></slot>
179180
${when(
180-
!this.hideFocalPoint,
181-
() =>
182-
html`<uui-button
183-
label=${this.localize.term('content_resetFocalPoint')}
184-
@click=${this.onResetFocalPoint}></uui-button>`,
185-
)} `;
181+
!this.hideFocalPoint && this.focalPoint.left !== 0.5 && this.focalPoint.top !== 0.5,
182+
() => html`
183+
<uui-button compact label=${this.localize.term('content_resetFocalPoint')} @click=${this.onResetFocalPoint}>
184+
<uui-icon name="icon-axis-rotation"></uui-icon>
185+
${this.localize.term('content_resetFocalPoint')}
186+
</uui-button>
187+
`,
188+
)}
189+
`;
186190
}
187191

188192
protected renderSide() {
189193
if (!this.value || !this.crops) return;
190-
191194
return repeat(
192195
this.crops,
193196
(crop) => crop.alias + JSON.stringify(crop.coordinates),
194-
(crop) =>
195-
html` <umb-image-cropper-preview
196-
@click=${() => this.onCropClick(crop)}
197+
(crop) => html`
198+
<umb-image-cropper-preview
197199
.crop=${crop}
198200
.focalPoint=${this.focalPoint}
199-
.src=${this.source}></umb-image-cropper-preview>`,
201+
.src=${this.source}
202+
?active=${this.currentCrop?.alias === crop.alias}
203+
@click=${() => this.onCropClick(crop)}>
204+
</umb-image-cropper-preview>
205+
`,
200206
);
201207
}
202-
static override styles = css`
203-
:host {
204-
display: flex;
205-
width: 100%;
206-
box-sizing: border-box;
207-
gap: var(--uui-size-space-3);
208-
height: 400px;
209-
}
210208

211-
#main {
212-
max-width: 500px;
213-
min-width: 300px;
214-
width: 100%;
215-
height: 100%;
216-
display: flex;
217-
gap: var(--uui-size-space-1);
218-
flex-direction: column;
219-
}
209+
static override styles = [
210+
css`
211+
:host {
212+
display: flex;
213+
width: 100%;
214+
box-sizing: border-box;
215+
gap: var(--uui-size-space-3);
216+
height: 400px;
217+
}
220218
221-
#actions {
222-
display: flex;
223-
justify-content: space-between;
224-
margin-top: 0.5rem;
225-
}
219+
#main {
220+
max-width: 500px;
221+
min-width: 300px;
222+
width: 100%;
223+
height: 100%;
224+
display: flex;
225+
gap: var(--uui-size-space-1);
226+
flex-direction: column;
227+
}
226228
227-
umb-image-cropper-focus-setter {
228-
height: calc(100% - 33px - var(--uui-size-space-1)); /* Temp solution to make room for actions */
229-
}
229+
#actions {
230+
display: flex;
231+
justify-content: space-between;
232+
margin-top: 0.5rem;
230233
231-
#side {
232-
display: grid;
233-
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
234-
gap: var(--uui-size-space-3);
235-
flex-grow: 1;
236-
overflow-y: auto;
237-
height: fit-content;
238-
max-height: 100%;
239-
}
240-
`;
234+
uui-icon {
235+
padding-right: var(--uui-size-1);
236+
}
237+
}
238+
239+
slot[name='actions'] {
240+
display: block;
241+
flex: 1;
242+
}
243+
244+
umb-image-cropper-focus-setter {
245+
height: calc(100% - 33px - var(--uui-size-space-1)); /* Temp solution to make room for actions */
246+
}
247+
248+
#side {
249+
display: grid;
250+
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
251+
gap: var(--uui-size-space-3);
252+
flex-grow: 1;
253+
overflow-y: auto;
254+
height: fit-content;
255+
max-height: 100%;
256+
257+
umb-image-cropper-preview[active] {
258+
background-color: var(--uui-color-current);
259+
}
260+
}
261+
`,
262+
];
241263
}
242264

243265
declare global {

src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper-focus-setter.element.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -107,19 +107,10 @@ export class UmbImageCropperFocusSetterElement extends UmbLitElement {
107107
}
108108
}
109109

110-
#coordsToFactor(x: number, y: number) {
111-
const top = (y / 100 / y) * 50;
112-
const left = (x / 100 / x) * 50;
113-
114-
return { top, left };
115-
}
116-
117110
#setFocalPoint(x: number, y: number, width: number, height: number) {
118111
const left = clamp(x / width, 0, 1);
119112
const top = clamp(y / height, 0, 1);
120113

121-
this.#coordsToFactor(x, y);
122-
123114
const focalPoint = { left, top } as UmbFocalPointModel;
124115

125116
this.dispatchEvent(new UmbFocalPointChangeEvent(focalPoint));
@@ -252,12 +243,9 @@ export class UmbImageCropperFocusSetterElement extends UmbLitElement {
252243
<img id="image" @keydown=${() => nothing} src=${this.src} alt="" />
253244
<span
254245
id="focal-point"
255-
class=${classMap({
256-
'focal-point--dragging': this._isDraggingGridHandle,
257-
hidden: this.hideFocalPoint,
258-
})}
246+
class=${classMap({ 'focal-point--dragging': this._isDraggingGridHandle, hidden: this.hideFocalPoint })}
259247
tabindex=${ifDefined(this.disabled ? undefined : '0')}
260-
aria-label="${this.localize.term('general_focalPoint')}"
248+
aria-label=${this.localize.term('general_focalPoint')}
261249
@keydown=${this.#handleGridKeyDown}>
262250
</span>
263251
</div>

src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/input-image-cropper.element.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -173,14 +173,14 @@ export class UmbInputImageCropperElement extends UmbFormControlMixin<
173173
}
174174

175175
#renderImageCropper() {
176-
return html`<umb-image-cropper-field
177-
.value=${this.value}
178-
.file=${this._file?.temporaryFile?.file}
179-
@change=${this.#onChange}>
180-
<uui-button slot="actions" @click=${this.#onRemove} label=${this.localize.term('content_uploadClear')}>
181-
<uui-icon name="icon-trash"></uui-icon>${this.localize.term('content_uploadClear')}
182-
</uui-button>
183-
</umb-image-cropper-field> `;
176+
return html`
177+
<umb-image-cropper-field .value=${this.value} .file=${this._file?.temporaryFile?.file} @change=${this.#onChange}>
178+
<uui-button slot="actions" compact label=${this.localize.term('content_uploadClear')} @click=${this.#onRemove}>
179+
<uui-icon name="icon-trash"></uui-icon>
180+
<umb-localize key="content_uploadClear">Remove file(s)</umb-localize>
181+
</uui-button>
182+
</umb-image-cropper-field>
183+
`;
184184
}
185185

186186
static override readonly styles = [
@@ -190,10 +190,17 @@ export class UmbInputImageCropperElement extends UmbFormControlMixin<
190190
max-width: 500px;
191191
min-width: 300px;
192192
}
193+
193194
#loader {
194195
display: flex;
195196
justify-content: center;
196197
}
198+
199+
[slot='actions'] {
200+
uui-icon {
201+
padding-right: var(--uui-size-1);
202+
}
203+
}
197204
`,
198205
];
199206
}

0 commit comments

Comments
 (0)