[NodeJS] Add `grid` `ImageSet` style (#8845)

This commit is contained in:
Paul Campbell 2024-03-07 14:09:20 -08:00 коммит произвёл GitHub
Родитель ad8eee4385
Коммит 0152d5c726
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
10 изменённых файлов: 116 добавлений и 46 удалений

Просмотреть файл

@ -12,6 +12,11 @@
"type": "ImageSize",
"default":"medium",
"description": "Controls the approximate size of each image. The physical dimensions will vary per host. Auto and stretch are not supported for ImageSet. The size will default to medium if those values are set."
}
},
"style": {
"type": "ImageSetStyle",
"version": "1.6",
"description": "Controls how the images in the `ImageSet` are displayed."
}
}
}

Просмотреть файл

@ -0,0 +1,20 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/AdaptiveCards/6f39aedce45864ae1067ed44a5551dc973790bb5/source/nodejs/typed-schema/schema/lib/Type.json",
"classType": "Enum",
"description": "Controls how an `ImageSet` is displayed.",
"version": "1.6",
"values": [
{
"value": "default",
"description": "This is the default style for `ImageSet`. Images are displayed in their original aspect ratio."
},
{
"value": "stacked",
"description": "Display images in this `ImageSet` stack on top of each other (similar to a stack of photos)."
},
{
"value": "grid",
"description": "Display images in a grid. They are all shown at the same size. Images are clipped as needed to fit in the available space."
}
]
}

Просмотреть файл

@ -6,11 +6,11 @@
"values": [
{
"value": "default",
"description": "This is the default style which provide no special styling or behavior."
"description": "This is the default style which provides no special styling or behavior."
},
{
"value": "heading",
"description": "The TextBlock is a heading. This will apply the heading styling defaults and mark the text block as a heading for accessiblity."
"description": "The `TextBlock` is a heading. This will apply the heading styling defaults and mark the `TextBlock` as a heading for accessiblity."
}
]
}

Просмотреть файл

@ -257,5 +257,11 @@
"The number of choices to be skipped in the list of choices returned by the query. It can be ignored if the card-author does not want pagination.": "The number of choices to be skipped in the list of choices returned by the query. It can be ignored if the card-author does not want pagination.",
"[SUPPORTED ONLY IN JAVASCRIPT SDK] Determines the position of the label. It can take 'inline' and 'above' values. By default, the label is placed 'above' when label position is not specified.": "[SUPPORTED ONLY IN JAVASCRIPT SDK] Determines the position of the label. It can take 'inline' and 'above' values. By default, the label is placed 'above' when label position is not specified.",
"[SUPPORTED ONLY IN JAVASCRIPT SDK] Determines the width of the label in percent like 40 or a specific pixel width like '40px' when label is placed inline with the input. labelWidth would be ignored when the label is displayed above the input.": "[SUPPORTED ONLY IN JAVASCRIPT SDK] Determines the width of the label in percent like 40 or a specific pixel width like '40px' when label is placed inline with the input. labelWidth would be ignored when the label is displayed above the input.",
"[SUPPORTED ONLY IN JAVASCRIPT SDK] Style hint for input fields. Allows input fields to appear as read-only but when user clicks/focuses on the field, it allows them to update those fields.": "[SUPPORTED ONLY IN JAVASCRIPT SDK] Style hint for input fields. Allows input fields to appear as read-only but when user clicks/focuses on the field, it allows them to update those fields."
"[SUPPORTED ONLY IN JAVASCRIPT SDK] Style hint for input fields. Allows input fields to appear as read-only but when user clicks/focuses on the field, it allows them to update those fields.": "[SUPPORTED ONLY IN JAVASCRIPT SDK] Style hint for input fields. Allows input fields to appear as read-only but when user clicks/focuses on the field, it allows them to update those fields.",
"This is the default style which provides no special styling or behavior.": "This is the default style which provides no special styling or behavior.",
"The `TextBlock` is a heading. This will apply the heading styling defaults and mark the `TextBlock` as a heading for accessiblity.": "The `TextBlock` is a heading. This will apply the heading styling defaults and mark the `TextBlock` as a heading for accessiblity.",
"This is the default style for `ImageSet`. Images are displayed in their original aspect ratio.": "This is the default style for `ImageSet`. Images are displayed in their original aspect ratio.",
"Display images in this `ImageSet` stack on top of each other (similar to a stack of photos).": "Display images in this `ImageSet` stack on top of each other (similar to a stack of photos).",
"Display images in a grid. They are all shown at the same size. Images are clipped as needed to fit in the available space.": "Display images in a grid. They are all shown at the same size. Images are clipped as needed to fit in the available space.",
"Controls how the images in the `ImageSet` are displayed.": "Controls how the images in the `ImageSet` are displayed."
}

Просмотреть файл

@ -257,5 +257,11 @@
"The number of choices to be skipped in the list of choices returned by the query. It can be ignored if the card-author does not want pagination.": "The number of choices to be skipped in the list of choices returned by the query. It can be ignored if the card-author does not want pagination.",
"[SUPPORTED ONLY IN JAVASCRIPT SDK] Determines the position of the label. It can take 'inline' and 'above' values. By default, the label is placed 'above' when label position is not specified.": "[SUPPORTED ONLY IN JAVASCRIPT SDK] Determines the position of the label. It can take 'inline' and 'above' values. By default, the label is placed 'above' when label position is not specified.",
"[SUPPORTED ONLY IN JAVASCRIPT SDK] Determines the width of the label in percent like 40 or a specific pixel width like '40px' when label is placed inline with the input. labelWidth would be ignored when the label is displayed above the input.": "[SUPPORTED ONLY IN JAVASCRIPT SDK] Determines the width of the label in percent like 40 or a specific pixel width like '40px' when label is placed inline with the input. labelWidth would be ignored when the label is displayed above the input.",
"[SUPPORTED ONLY IN JAVASCRIPT SDK] Style hint for input fields. Allows input fields to appear as read-only but when user clicks/focuses on the field, it allows them to update those fields.": "[SUPPORTED ONLY IN JAVASCRIPT SDK] Style hint for input fields. Allows input fields to appear as read-only but when user clicks/focuses on the field, it allows them to update those fields."
"[SUPPORTED ONLY IN JAVASCRIPT SDK] Style hint for input fields. Allows input fields to appear as read-only but when user clicks/focuses on the field, it allows them to update those fields.": "[SUPPORTED ONLY IN JAVASCRIPT SDK] Style hint for input fields. Allows input fields to appear as read-only but when user clicks/focuses on the field, it allows them to update those fields.",
"This is the default style which provides no special styling or behavior.": "This is the default style which provides no special styling or behavior.",
"The `TextBlock` is a heading. This will apply the heading styling defaults and mark the `TextBlock` as a heading for accessiblity.": "The `TextBlock` is a heading. This will apply the heading styling defaults and mark the `TextBlock` as a heading for accessiblity.",
"This is the default style for `ImageSet`. Images are displayed in their original aspect ratio.": "This is the default style for `ImageSet`. Images are displayed in their original aspect ratio.",
"Display images in this `ImageSet` stack on top of each other (similar to a stack of photos).": "Display images in this `ImageSet` stack on top of each other (similar to a stack of photos).",
"Display images in a grid. They are all shown at the same size. Images are clipped as needed to fit in the available space.": "Display images in a grid. They are all shown at the same size. Images are clipped as needed to fit in the available space.",
"Controls how the images in the `ImageSet` are displayed.": "Controls how the images in the `ImageSet` are displayed."
}

Просмотреть файл

@ -257,5 +257,11 @@
"The number of choices to be skipped in the list of choices returned by the query. It can be ignored if the card-author does not want pagination.": "The number of choices to be skipped in the list of choices returned by the query. It can be ignored if the card-author does not want pagination.",
"[SUPPORTED ONLY IN JAVASCRIPT SDK] Determines the position of the label. It can take 'inline' and 'above' values. By default, the label is placed 'above' when label position is not specified.": "[SUPPORTED ONLY IN JAVASCRIPT SDK] Determines the position of the label. It can take 'inline' and 'above' values. By default, the label is placed 'above' when label position is not specified.",
"[SUPPORTED ONLY IN JAVASCRIPT SDK] Determines the width of the label in percent like 40 or a specific pixel width like '40px' when label is placed inline with the input. labelWidth would be ignored when the label is displayed above the input.": "[SUPPORTED ONLY IN JAVASCRIPT SDK] Determines the width of the label in percent like 40 or a specific pixel width like '40px' when label is placed inline with the input. labelWidth would be ignored when the label is displayed above the input.",
"[SUPPORTED ONLY IN JAVASCRIPT SDK] Style hint for input fields. Allows input fields to appear as read-only but when user clicks/focuses on the field, it allows them to update those fields.": "[SUPPORTED ONLY IN JAVASCRIPT SDK] Style hint for input fields. Allows input fields to appear as read-only but when user clicks/focuses on the field, it allows them to update those fields."
"[SUPPORTED ONLY IN JAVASCRIPT SDK] Style hint for input fields. Allows input fields to appear as read-only but when user clicks/focuses on the field, it allows them to update those fields.": "[SUPPORTED ONLY IN JAVASCRIPT SDK] Style hint for input fields. Allows input fields to appear as read-only but when user clicks/focuses on the field, it allows them to update those fields.",
"This is the default style which provides no special styling or behavior.": "This is the default style which provides no special styling or behavior.",
"The `TextBlock` is a heading. This will apply the heading styling defaults and mark the `TextBlock` as a heading for accessiblity.": "The `TextBlock` is a heading. This will apply the heading styling defaults and mark the `TextBlock` as a heading for accessiblity.",
"This is the default style for `ImageSet`. Images are displayed in their original aspect ratio.": "This is the default style for `ImageSet`. Images are displayed in their original aspect ratio.",
"Display images in this `ImageSet` stack on top of each other (similar to a stack of photos).": "Display images in this `ImageSet` stack on top of each other (similar to a stack of photos).",
"Display images in a grid. They are all shown at the same size. Images are clipped as needed to fit in the available space.": "Display images in a grid. They are all shown at the same size. Images are clipped as needed to fit in the available space.",
"Controls how the images in the `ImageSet` are displayed.": "Controls how the images in the `ImageSet` are displayed."
}

Просмотреть файл

@ -2000,18 +2000,7 @@ export class Image extends CardElement {
// auto and stretch are ignored (default to medium). THis is necessary for
// ImageSet which uses a maximum image height as opposed to the cards width
// as a constraining dimension
switch (this.size) {
case Enums.Size.Small:
element.style.height = this.hostConfig.imageSizes.small + "px";
break;
case Enums.Size.Large:
element.style.height = this.hostConfig.imageSizes.large + "px";
break;
default:
element.style.height = this.hostConfig.imageSizes.medium + "px";
break;
}
element.style.height = this.hostConfig.getEffectiveImageSize(this.size) + "px";
element.style.maxHeight = this.maxHeight + "px";
} else {
switch (this.size) {
@ -2021,14 +2010,8 @@ export class Image extends CardElement {
case Enums.Size.Auto:
element.style.maxWidth = "100%";
break;
case Enums.Size.Small:
element.style.width = this.hostConfig.imageSizes.small + "px";
break;
case Enums.Size.Large:
element.style.width = this.hostConfig.imageSizes.large + "px";
break;
case Enums.Size.Medium:
element.style.width = this.hostConfig.imageSizes.medium + "px";
default:
element.style.width = this.hostConfig.getEffectiveImageSize(this.size) + "px";
break;
}
@ -2518,38 +2501,64 @@ export class ImageSet extends CardElementContainer {
let element: HTMLElement | undefined = undefined;
if (this._images.length > 0) {
const imageSetIsGrid = (this.presentationStyle === Enums.ImageSetPresentationStyle.Grid);
element = document.createElement("div");
element.style.display = "flex";
element.style.flexWrap = "wrap";
element.classList.add(this.hostConfig.makeCssClassName("ac-imageSet"));
element.classList.toggle(this.hostConfig.makeCssClassName("ac-imageSetStyle-grid"), imageSetIsGrid);
element.style.gap = "5px";
let renderImageSize : Enums.Size;
switch (this.imageSize) {
case Enums.ImageSize.Small:
renderImageSize = Enums.Size.Small;
break;
case Enums.ImageSize.Large:
renderImageSize = Enums.Size.Large;
break;
default:
renderImageSize = Enums.Size.Medium;
break;
}
const effectiveImageSize = this.hostConfig.getEffectiveImageSize(renderImageSize);
for (const image of this._images) {
switch (this.imageSize) {
case Enums.ImageSize.Small:
image.size = Enums.Size.Small;
break;
case Enums.ImageSize.Large:
image.size = Enums.Size.Large;
break;
default:
image.size = Enums.Size.Medium;
break;
}
image.maxHeight = this.hostConfig.imageSet.maxImageHeight;
const renderedImage = image.render();
if (imageSetIsGrid) {
image.pixelWidth = effectiveImageSize;
} else {
image.size = renderImageSize;
}
if (renderedImage) {
renderedImage.style.display = "inline-flex";
renderedImage.style.margin = "0px";
if (this.presentationStyle == Enums.ImageSetPresentationStyle.Default) {
renderedImage.style.marginRight = "10px";
const imageContainer = image.render();
if (imageContainer) {
imageContainer.style.display = "inline-flex";
imageContainer.style.margin = "0px";
if (imageSetIsGrid) {
imageContainer.style.flexBasis = effectiveImageSize + "px";
imageContainer.style.height = effectiveImageSize + "px";
imageContainer.style.flexGrow = "0";
imageContainer.style.flexShrink = "0";
const renderedImageStyle = image.renderedImageElement?.style;
if (renderedImageStyle) {
renderedImageStyle.width = "100%";
renderedImageStyle.height = "100%";
renderedImageStyle.objectFit = "cover";
renderedImageStyle.verticalAlign = "middle";
}
}
Utils.appendChild(element, renderedImage);
Utils.appendChild(element, imageContainer);
}
}
if (this.presentationStyle == Enums.ImageSetPresentationStyle.Stacked) {
this.applyStackedPresentationStyle();
}

Просмотреть файл

@ -56,7 +56,8 @@ export enum ImageSize {
export enum ImageSetPresentationStyle {
Default,
Stacked
Stacked,
Grid
}
export enum SizeUnit {

Просмотреть файл

@ -839,6 +839,20 @@ export class HostConfig {
}
}
getEffectiveImageSize(imageSize: Enums.ImageSize | Enums.Size): number {
switch (imageSize) {
case Enums.Size.Small:
return this.imageSizes.small;
case Enums.Size.Large:
return this.imageSizes.large;
case Enums.Size.Medium:
default:
return this.imageSizes.medium;
}
}
getEffectiveSpacing(spacing: Enums.Spacing): number {
switch (spacing) {
case Enums.Spacing.Small:

Просмотреть файл

@ -1,5 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import { ImageSetPresentationStyle } from "./enums";
export type Size = "auto" | "stretch" | "small" | "medium" | "large";
export type TextSize = "small" | "default" | "medium" | "large" | "extraLarge";
export type HorizontalAlignment = "left" | "center" | "right";
@ -110,6 +112,7 @@ export interface IImageSet extends ICardElement {
type: "ImageSet";
images: IImage[];
size?: Size;
style?: ImageSetPresentationStyle;
}
export interface IInput extends ICardElement {