@ably/ui 15.1.4-dev.0746ac8 → 15.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/core/Accordion.js CHANGED
@@ -1 +1 @@
1
- import React,{useMemo,useState}from"react";import{AccordionContent,AccordionItem,AccordionTrigger,Accordion as RadixAccordion}from"@radix-ui/react-accordion";import Icon from"./Icon";import{themeClasses,isNonTransparentTheme,isStaticTheme}from"./Accordion/utils";import cn from"./utils/cn";const AccordionRow=({name,children,rowIcon,options,toggleIcons,theme,index,onClick,openRowValues})=>{const{selectable,sticky}=options||{};const rowKey=`accordion-item-${index}`;const isOpen=openRowValues.includes(rowKey);const{text,bg,hoverBg,selectableBg,selectableText,border,toggleIconColor}=themeClasses[theme];const textClass=selectable&&isOpen&&selectableText||text;return /*#__PURE__*/React.createElement(AccordionItem,{value:rowKey,className:cn({[`${border}`]:border&&!options?.hideBorders})},/*#__PURE__*/React.createElement(AccordionTrigger,{onClick:onClick,className:cn({"flex w-full group/accordion-trigger py-16 ui-text-p1 font-bold text-left items-center gap-12 transition-colors focus:outline-none":true,"px-16 mb-16 rounded-lg":isNonTransparentTheme(theme),"rounded-none":!isNonTransparentTheme(theme),"pointer-events-none focus-visible:outline-none":isStaticTheme(theme),"focus-visible:outline-4 focus-visible:outline-offset-0 focus-visible:outline-gui-blue-focus":!isStaticTheme(theme),"sticky top-0":sticky,[`${bg} ${hoverBg} ${text}`]:!(selectable&&isOpen),[`${selectableBg} ${selectableText}`]:selectable&&isOpen,[options?.headerCSS??""]:options?.headerCSS,[options?.selectedHeaderCSS??""]:options?.selectedHeaderCSS&&isOpen})},rowIcon?/*#__PURE__*/React.createElement(Icon,{name:rowIcon,color:textClass,size:options?.rowIconSize??"32px"}):null,/*#__PURE__*/React.createElement("span",null,name),!selectable&&!isStaticTheme(theme)?/*#__PURE__*/React.createElement("span",{className:"flex-1 justify-end flex items-center"},/*#__PURE__*/React.createElement(Icon,{name:isOpen?toggleIcons.open.name:toggleIcons.closed.name,color:toggleIconColor,size:options?.iconSize??"16px"})):null),/*#__PURE__*/React.createElement(AccordionContent,{className:cn({"ui-text-p2 overflow-hidden transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down":true,[options?.contentCSS??""]:options?.contentCSS})},/*#__PURE__*/React.createElement("div",{className:"pb-16"},children)))};const Accordion=({data,theme="transparent",icons={closed:{name:"icon-gui-plus"},open:{name:"icon-gui-minus"}},options,...props})=>{const openIndexes=useMemo(()=>{const indexValues=data.map((_,i)=>`accordion-item-${i}`);return options?.fullyOpen?indexValues:indexValues.filter((_,index)=>options?.defaultOpenIndexes?.includes(index))},[options?.defaultOpenIndexes,options?.fullyOpen,data.length]);const[openRowValues,setOpenRowValues]=useState(openIndexes);const innerAccordion=data.map((item,index)=>/*#__PURE__*/React.createElement(AccordionRow,{key:item.name,name:item.name,rowIcon:item.icon,toggleIcons:icons,theme:theme,options:options,index:index,onClick:()=>{item.onClick?.(index)},openRowValues:openRowValues},item.content));return /*#__PURE__*/React.createElement("div",props,options?.autoClose?/*#__PURE__*/React.createElement(RadixAccordion,{type:"single",collapsible:true,defaultValue:openIndexes[0],onValueChange:values=>setOpenRowValues(values)},innerAccordion):/*#__PURE__*/React.createElement(RadixAccordion,{type:"multiple",defaultValue:openIndexes,onValueChange:values=>setOpenRowValues(values)},innerAccordion))};export default Accordion;
1
+ import React,{useMemo,useState}from"react";import{AccordionContent,AccordionItem,AccordionTrigger,Accordion as RadixAccordion}from"@radix-ui/react-accordion";import Icon from"./Icon";import{themeClasses,isNonTransparentTheme,isStaticTheme}from"./Accordion/utils";import cn from"./utils/cn";const AccordionRow=({name,children,rowIcon,options,toggleIcons,theme,index,onClick,openRowValues})=>{const{selectable,sticky}=options||{};const rowKey=`accordion-item-${index}`;const isOpen=openRowValues.includes(rowKey);const{text,bg,hoverBg,selectableBg,selectableText,border,toggleIconColor}=themeClasses[theme];const textClass=selectable&&isOpen&&selectableText||text;return /*#__PURE__*/React.createElement(AccordionItem,{value:rowKey,className:cn({[`${border}`]:border&&!options?.hideBorders})},/*#__PURE__*/React.createElement(AccordionTrigger,{onClick:onClick,className:cn({"flex w-full group/accordion-trigger py-16 ui-text-p1 font-bold text-left items-center gap-12 transition-colors focus:outline-none":true,"px-16 mb-16 rounded-lg":isNonTransparentTheme(theme),"rounded-none":!isNonTransparentTheme(theme),"pointer-events-none focus-visible:outline-none":isStaticTheme(theme),"focus-base":!isStaticTheme(theme),"sticky top-0":sticky,[`${bg} ${hoverBg} ${text}`]:!(selectable&&isOpen),[`${selectableBg} ${selectableText}`]:selectable&&isOpen,[options?.headerCSS??""]:options?.headerCSS,[options?.selectedHeaderCSS??""]:options?.selectedHeaderCSS&&isOpen})},rowIcon?/*#__PURE__*/React.createElement(Icon,{name:rowIcon,color:textClass,size:options?.rowIconSize??"32px"}):null,/*#__PURE__*/React.createElement("span",null,name),!selectable&&!isStaticTheme(theme)?/*#__PURE__*/React.createElement("span",{className:"flex-1 justify-end flex items-center"},/*#__PURE__*/React.createElement(Icon,{name:isOpen?toggleIcons.open.name:toggleIcons.closed.name,color:toggleIconColor,size:options?.iconSize??"16px"})):null),/*#__PURE__*/React.createElement(AccordionContent,{className:cn({"ui-text-p2 overflow-hidden transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down":true,[options?.contentCSS??""]:options?.contentCSS})},/*#__PURE__*/React.createElement("div",{className:"pb-16"},children)))};const Accordion=({data,theme="transparent",icons={closed:{name:"icon-gui-plus"},open:{name:"icon-gui-minus"}},options,...props})=>{const openIndexes=useMemo(()=>{const indexValues=data.map((_,i)=>`accordion-item-${i}`);return options?.fullyOpen?indexValues:indexValues.filter((_,index)=>options?.defaultOpenIndexes?.includes(index))},[options?.defaultOpenIndexes,options?.fullyOpen,data.length]);const[openRowValues,setOpenRowValues]=useState(openIndexes);const innerAccordion=data.map((item,index)=>/*#__PURE__*/React.createElement(AccordionRow,{key:item.name,name:item.name,rowIcon:item.icon,toggleIcons:icons,theme:theme,options:options,index:index,onClick:()=>{item.onClick?.(index)},openRowValues:openRowValues},item.content));return /*#__PURE__*/React.createElement("div",props,options?.autoClose?/*#__PURE__*/React.createElement(RadixAccordion,{type:"single",collapsible:true,defaultValue:openIndexes[0],onValueChange:values=>setOpenRowValues(values)},innerAccordion):/*#__PURE__*/React.createElement(RadixAccordion,{type:"multiple",defaultValue:openIndexes,onValueChange:values=>setOpenRowValues(values)},innerAccordion))};export default Accordion;
package/core/Badge.js ADDED
@@ -0,0 +1 @@
1
+ import React,{useMemo}from"react";import Icon from"./Icon";import cn from"./utils/cn";const Badge=({size="md",color="neutral",iconBefore,iconAfter,className,children,disabled=false,focusable=false,hoverable=false,iconSize="12px",ariaLabel})=>{const sizeClass=useMemo(()=>{switch(size){case"xs":return"px-8 py-0 text-[10px] leading-tight";case"sm":return"px-8 py-2 text-[10px] leading-tight";case"md":return"px-[10px] py-2 text-[11px] leading-normal";case"lg":return"px-12 py-[3px] text-[12px] leading-normal"}},[size]);const childClass=useMemo(()=>{switch(size){case"xs":case"sm":return"leading-[18px]";case"md":case"lg":return"leading-[20px]"}},[size]);const colorClass=useMemo(()=>{switch(color){case"neutral":return"text-neutral-900 dark:text-neutral-400";case"violet":return"text-violet-400";case"orange":return"text-orange-600";case"yellow":return"text-yellow-600";case"green":return"text-green-600";case"blue":return"text-blue-600";case"pink":return"text-pink-600";case"red":return"text-orange-700"}},[color]);return /*#__PURE__*/React.createElement("div",{className:cn("inline-flex bg-neutral-100 dark:bg-neutral-1200 rounded-2xl gap-4 items-center focus-base transition-colors select-none font-semibold",sizeClass,colorClass,{"focus-base":focusable},{"hover:bg-neutral-300 hover:dark:bg-neutral-1000 active:bg-neutral-300 dark:active:bg-neutral-1000":hoverable},{"cursor-not-allowed disabled:text-gui-unavailable dark:disabled:text-gui-unavailable-dark":disabled},className),tabIndex:focusable?0:undefined,"aria-label":focusable||hoverable?ariaLabel:undefined},iconBefore?/*#__PURE__*/React.createElement(Icon,{name:iconBefore,size:iconSize,color:colorClass}):null,/*#__PURE__*/React.createElement("span",{className:cn("whitespace-nowrap tracking-widen-0.04",childClass)},children),iconAfter?/*#__PURE__*/React.createElement(Icon,{name:iconAfter,size:iconSize,color:colorClass}):null)};export default Badge;
package/core/Toggle.js CHANGED
@@ -1 +1 @@
1
- import*as Switch from"@radix-ui/react-switch";import React from"react";import cn from"./utils/cn";const Toggle=({id,size,label,className,...props})=>{const rootSize=size==="small"?"w-[42px] h-[24px]":"w-[56px] h-32";const thumbSize=size==="small"?"w-[21px] h-[21px] translate-x-1 data-[state=checked]:translate-x-[20px]":"h-[28px] w-[28px] translate-x-2 data-[state=checked]:translate-x-[26px]";return /*#__PURE__*/React.createElement("div",{className:"flex items-center"},/*#__PURE__*/React.createElement(Switch.Root,{className:cn("p-0 bg-neutral-600 rounded-full relative inline-block transition-colors data-[disabled]:bg-gui-unavailable data-[disabled]:cursor-not-allowed data-[state=checked]:bg-orange-600 focus:outline-none focus-visible:outline-offset-0 focus-visible:outline-4 focus-visible:outline-gui-focus",className,rootSize),id:id,...props},/*#__PURE__*/React.createElement(Switch.Thumb,{className:`block bg-white data-[disabled]:bg-neutral-500 rounded-full drop-shadow-toggle transition-transform ${thumbSize}`})),label?/*#__PURE__*/React.createElement("label",{className:"ml-16",htmlFor:id},label):null)};export default Toggle;
1
+ import*as Switch from"@radix-ui/react-switch";import React from"react";import cn from"./utils/cn";const Toggle=({id,size="lg",label,className,...props})=>{const rootSize=size==="sm"?"w-[42px] h-24":"w-[56px] h-32";const thumbSize=size==="sm"?"w-[21px] h-[21px] translate-x-1 data-[state=checked]:translate-x-[20px]":"h-[28px] w-[28px] translate-x-2 data-[state=checked]:translate-x-[26px]";return /*#__PURE__*/React.createElement("div",{className:"flex items-center"},/*#__PURE__*/React.createElement(Switch.Root,{className:cn("p-0 bg-neutral-600 rounded-full relative inline-block transition-colors data-[disabled]:bg-gui-unavailable data-[disabled]:cursor-not-allowed data-[state=checked]:bg-orange-600 focus-base",className,rootSize),id:id,...props},/*#__PURE__*/React.createElement(Switch.Thumb,{className:cn(`block bg-white data-[disabled]:bg-neutral-500 rounded-full drop-shadow-toggle transition-transform`,thumbSize)})),label?/*#__PURE__*/React.createElement("label",{className:"ml-16",htmlFor:id},label):null)};export default Toggle;
@@ -1,6 +1,6 @@
1
1
  @layer components {
2
2
  .ui-button-base {
3
- @apply inline-flex rounded justify-center items-center gap-12 text-neutral-000 transition-colors focus:outline-none focus-visible:outline-offset-0 focus-visible:outline-4 focus-visible:outline-gui-blue-focus disabled:cursor-not-allowed;
3
+ @apply inline-flex rounded justify-center items-center gap-12 text-neutral-000 transition-colors focus-base disabled:cursor-not-allowed;
4
4
  }
5
5
 
6
6
  .ui-button-lg-base {
@@ -1,6 +1,6 @@
1
1
  @layer components {
2
2
  .ui-dropdown-base {
3
- @apply rounded-lg border border-neutral-400 hover:border-neutral-600 active:border-neutral-500 pl-16 pr-[56px] appearance-none select-none focus:outline-none focus-visible:outline-gui-focus focus-visible:outline-4 focus-visible:outline-offset-0;
3
+ @apply rounded-lg border border-neutral-400 hover:border-neutral-600 active:border-neutral-500 pl-16 pr-[56px] appearance-none select-none focus-base;
4
4
  @apply bg-no-repeat text-p2 flex font-medium bg-neutral-100 transition-colors;
5
5
  background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsPSIjNjY3MDg1IiBkPSJNMTIuOTA0NiAxMkw5LjAwNjcxIDE2LjMzMUwxMC40OTMzIDE3LjY2OUwxNC45OTMzIDEyLjY2OUwxNC45OTMzIDExLjMzMUwxMC40OTMzIDYuMzMxMDVMOS4wMDY3MSA3LjY2ODk4TDEyLjkwNDYgMTJaIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAxMiAxMikiLz4KPC9zdmc+Cg==");
6
6
  background-position: center right 16px;
@@ -123,7 +123,7 @@
123
123
 
124
124
  .ui-input {
125
125
  @apply ui-text-p2 font-medium bg-neutral-100 rounded p-input w-full leading-none appearance-none border border-neutral-400 transition-colors placeholder-neutral-600;
126
- @apply hover:border-neutral-700 focus:bg-white focus:outline-none focus-visible:outline-gui-focus focus-visible:outline-offset-0 focus-visible:outline-4;
126
+ @apply hover:border-neutral-700 focus:bg-white focus-base;
127
127
  @apply max-w-screen-sm invalid:border-gui-error-red;
128
128
  }
129
129
 
@@ -140,7 +140,7 @@
140
140
  }
141
141
 
142
142
  .ui-radio {
143
- @apply border border-neutral-600 w-20 h-20 appearance-none cursor-pointer rounded-full focus-visible:outline-4 focus-visible:outline-gui-blue-focus;
143
+ @apply border border-neutral-600 w-20 h-20 appearance-none cursor-pointer rounded-full focus-base;
144
144
  }
145
145
 
146
146
  .ui-radio:checked {
@@ -3,7 +3,7 @@
3
3
  @apply text-white bg-cool-black text-btn2 font-sans font-bold inline-block rounded p-btn;
4
4
  @apply hover:text-white hover:bg-neutral-1100;
5
5
  @apply active:text-white active:bg-neutral-1200;
6
- @apply focus:text-white focus:bg-cool-black focus:outline-offset-0 focus:outline-none focus-visible:outline-4 focus-visible:outline-gui-focus;
6
+ @apply focus:text-white focus:bg-cool-black focus-base;
7
7
  @apply disabled:text-mid-grey disabled:bg-gui-unavailable disabled:cursor-not-allowed;
8
8
  @apply transition-colors;
9
9
  @apply inline-flex items-center justify-center;
@@ -25,7 +25,7 @@
25
25
  background-position: 0% 0%;
26
26
 
27
27
  @apply text-white text-btn2 font-sans font-bold inline-block rounded p-btn;
28
- @apply focus:outline-offset-0 focus:outline-none focus-visible:outline-4 focus-visible:outline-gui-focus;
28
+ @apply focus-base;
29
29
  @apply inline-flex items-center justify-center;
30
30
  }
31
31
 
@@ -43,7 +43,7 @@
43
43
  @apply text-cool-black bg-white text-btn2 font-sans font-bold inline-block rounded p-btn;
44
44
  @apply hover:text-white hover:bg-active-orange;
45
45
  @apply active:text-white active:bg-red-orange;
46
- @apply focus:text-white focus:bg-cool-black focus:outline-offset-0 focus:outline-none focus-visible:outline-4 focus-visible:outline-gui-focus;
46
+ @apply focus:text-white focus:bg-cool-black focus-base;
47
47
  @apply disabled:text-mid-grey disabled:bg-gui-unavailable disabled:cursor-not-allowed;
48
48
  @apply transition-colors;
49
49
  @apply inline-flex items-center justify-center;
@@ -53,7 +53,7 @@
53
53
  @apply text-cool-black bg-white text-btn2 font-sans font-bold inline-block border-btn border-cool-black rounded p-btn;
54
54
  @apply hover:text-cool-black hover:border-active-orange hover:bg-white;
55
55
  @apply active:border-red-orange active:bg-white;
56
- @apply focus:border-cool-black focus:bg-white focus:outline-offset-0 focus:outline-none focus-visible:outline-4 focus-visible:outline-gui-focus;
56
+ @apply focus:border-cool-black focus:bg-white focus-base;
57
57
  @apply disabled:text-gui-unavailable disabled:border-gui-unavailable disabled:bg-white disabled:cursor-not-allowed;
58
58
  @apply transition-colors;
59
59
  @apply inline-flex items-center justify-center;
@@ -63,7 +63,7 @@
63
63
  @apply text-white bg-cool-black text-btn2 font-sans font-bold inline-block border-btn border-mid-grey rounded p-btn;
64
64
  @apply hover:text-white hover:border-active-orange;
65
65
  @apply active:border-red-orange;
66
- @apply focus:outline-offset-0 focus:outline-none focus-visible:outline-4 focus-visible:outline-gui-focus;
66
+ @apply focus-base;
67
67
  @apply disabled:text-gui-unavailable disabled:border-gui-unavailable disabled:cursor-not-allowed;
68
68
  @apply transition-colors;
69
69
  @apply inline-flex items-center justify-center;
@@ -223,6 +223,7 @@
223
223
  --ls-widen-0_1: 0.1em;
224
224
  --ls-widen-0_16: 0.16em;
225
225
  --ls-widen-0_15: 0.15em;
226
+ --ls-widen-0_04: 0.04em;
226
227
 
227
228
  --spacing-0: 0px;
228
229
  --spacing-1: 1px;
@@ -176,13 +176,13 @@
176
176
  .ui-link {
177
177
  @apply text-gui-default;
178
178
  @apply hover:text-gui-hover active:text-gui-active disabled:text-gui-unavailable;
179
- @apply focus:text-gui-default focus:outline-none focus-visible:outline-4 focus-visible:outline-offset-0 focus-visible:outline-gui-focus;
179
+ @apply focus:text-gui-default focus-base;
180
180
  @apply no-underline;
181
181
  }
182
182
 
183
183
  .ui-link-neutral {
184
184
  @apply hover:text-dark-grey active:text-cool-black disabled:text-gui-unavailable;
185
- @apply focus:text-charcoal-grey focus:outline-none focus-visible:outline-4 focus-visible:outline-offset-0 focus-visible:outline-gui-focus;
185
+ @apply focus:text-charcoal-grey focus-base;
186
186
  @apply underline;
187
187
  }
188
188
 
@@ -0,0 +1,3 @@
1
+ .focus-base {
2
+ @apply focus:outline-none focus-visible:outline-4 focus-visible:outline-offset-0 focus-visible:outline-gui-focus;
3
+ }
@@ -1,3 +1,4 @@
1
+ @import "./styles/utils.css";
1
2
  @import "./styles/buttons.css";
2
3
  @import "./styles/legacy-buttons.css";
3
4
  @import "./styles/dropdowns.css";
package/index.d.ts CHANGED
@@ -168,6 +168,60 @@ export default Accordion;
168
168
  //# sourceMappingURL=Accordion.d.ts.map
169
169
  }
170
170
 
171
+ declare module '@ably/ui/core/Badge' {
172
+ import React, { PropsWithChildren } from "react";
173
+ import { IconName, IconSize } from "@ably/ui/core/Icon/types";
174
+ import { ColorClassColorGroups } from "@ably/ui/core/styles/colors/types";
175
+ /**
176
+ * Props for the Badge component.
177
+ */
178
+ interface BadgeProps {
179
+ /**
180
+ * The size of the badge. Can be one of "xs", "sm", "md", or "lg".
181
+ */
182
+ size?: "xs" | "sm" | "md" | "lg";
183
+ /**
184
+ * The color of the badge. Can be a value from ColorClassColorGroups or "red".
185
+ */
186
+ color?: ColorClassColorGroups | "red";
187
+ /**
188
+ * The name of the icon to be displayed before the children in the badge.
189
+ */
190
+ iconBefore?: IconName;
191
+ /**
192
+ * The name of the icon to be displayed after the children in the badge.
193
+ */
194
+ iconAfter?: IconName;
195
+ /**
196
+ * Additional CSS class names to apply to the badge.
197
+ */
198
+ className?: string;
199
+ /**
200
+ * Whether the badge is disabled. Defaults to false.
201
+ */
202
+ disabled?: boolean;
203
+ /**
204
+ * Whether the badge is focusable. Defaults to false.
205
+ */
206
+ focusable?: boolean;
207
+ /**
208
+ * Whether the badge is hoverable. Defaults to false.
209
+ */
210
+ hoverable?: boolean;
211
+ /**
212
+ * The size of the icons in the badge. Defaults to 12px.
213
+ */
214
+ iconSize?: IconSize;
215
+ /**
216
+ * Accessible label for the badge when interactive
217
+ */
218
+ ariaLabel?: string;
219
+ }
220
+ const Badge: React.FC<PropsWithChildren<BadgeProps>>;
221
+ export default Badge;
222
+ //# sourceMappingURL=Badge.d.ts.map
223
+ }
224
+
171
225
  declare module '@ably/ui/core/Button' {
172
226
  import React, { PropsWithChildren } from "react";
173
227
  import { IconName } from "@ably/ui/core/Icon/types";
@@ -1094,9 +1148,10 @@ declare module '@ably/ui/core/Toggle' {
1094
1148
  import React from "react";
1095
1149
  type ToggleProps = {
1096
1150
  id: string;
1097
- size?: string;
1151
+ size?: "sm" | "lg";
1098
1152
  label?: string;
1099
1153
  className?: string;
1154
+ onCheckedChange?: (checked: boolean) => void;
1100
1155
  } & React.ButtonHTMLAttributes<HTMLButtonElement>;
1101
1156
  const Toggle: React.FC<ToggleProps>;
1102
1157
  export default Toggle;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ably/ui",
3
- "version": "15.1.4-dev.0746ac8",
3
+ "version": "15.1.4",
4
4
  "description": "Home of the Ably design system library ([design.ably.com](https://design.ably.com)). It provides a showcase, development/test environment and a publishing pipeline for different distributables.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -279,6 +279,7 @@ module.exports = {
279
279
  "widen-0.1": "var(--ls-widen-0_1)",
280
280
  "widen-0.15": "var(--ls-widen-0_15)",
281
281
  "widen-0.16": "var(--ls-widen-0_16)",
282
+ "widen-0.04": "var(--ls-widen-0_04)",
282
283
  },
283
284
  extend: {
284
285
  backgroundImage: {