Private
Public Access
1
0

feat: Fluent UI Outlook Lite + connections mockup

This commit is contained in:
2026-04-14 18:52:25 +00:00
parent 1199eff6c3
commit dfa4010406
34820 changed files with 1003813 additions and 205 deletions

View File

@@ -0,0 +1,15 @@
'use client';
import * as React from 'react';
import { useMenuPopover_unstable } from './useMenuPopover';
import { useMenuPopoverStyles_unstable } from './useMenuPopoverStyles.styles';
import { renderMenuPopover_unstable } from './renderMenuPopover';
import { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';
/**
* Popover intended to wrap `MenuList` and adds styling and interaction support specific to menus
*/ export const MenuPopover = /*#__PURE__*/ React.forwardRef((props, ref)=>{
const state = useMenuPopover_unstable(props, ref);
useMenuPopoverStyles_unstable(state);
useCustomStyleHook_unstable('useMenuPopoverStyles_unstable')(state);
return renderMenuPopover_unstable(state);
});
MenuPopover.displayName = 'MenuPopover';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/MenuPopover/MenuPopover.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useMenuPopover_unstable } from './useMenuPopover';\nimport { useMenuPopoverStyles_unstable } from './useMenuPopoverStyles.styles';\nimport { renderMenuPopover_unstable } from './renderMenuPopover';\nimport type { MenuPopoverProps } from './MenuPopover.types';\nimport type { ForwardRefComponent } from '@fluentui/react-utilities';\nimport { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';\n\n/**\n * Popover intended to wrap `MenuList` and adds styling and interaction support specific to menus\n */\nexport const MenuPopover: ForwardRefComponent<MenuPopoverProps> = React.forwardRef((props, ref) => {\n const state = useMenuPopover_unstable(props, ref);\n\n useMenuPopoverStyles_unstable(state);\n\n useCustomStyleHook_unstable('useMenuPopoverStyles_unstable')(state);\n\n return renderMenuPopover_unstable(state);\n});\n\nMenuPopover.displayName = 'MenuPopover';\n"],"names":["React","useMenuPopover_unstable","useMenuPopoverStyles_unstable","renderMenuPopover_unstable","useCustomStyleHook_unstable","MenuPopover","forwardRef","props","ref","state","displayName"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,uBAAuB,QAAQ,mBAAmB;AAC3D,SAASC,6BAA6B,QAAQ,gCAAgC;AAC9E,SAASC,0BAA0B,QAAQ,sBAAsB;AAGjE,SAASC,2BAA2B,QAAQ,kCAAkC;AAE9E;;CAEC,GACD,OAAO,MAAMC,4BAAqDL,MAAMM,UAAU,CAAC,CAACC,OAAOC;IACzF,MAAMC,QAAQR,wBAAwBM,OAAOC;IAE7CN,8BAA8BO;IAE9BL,4BAA4B,iCAAiCK;IAE7D,OAAON,2BAA2BM;AACpC,GAAG;AAEHJ,YAAYK,WAAW,GAAG"}

View File

@@ -0,0 +1 @@
import * as React from 'react';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/MenuPopover/MenuPopover.types.ts"],"sourcesContent":["import type { PortalProps } from '@fluentui/react-portal';\nimport type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nexport type MenuPopoverSlots = {\n root: Slot<'div'>;\n};\n\n/**\n * MenuPopover Props\n */\nexport type MenuPopoverProps = ComponentProps<MenuPopoverSlots>;\n\n/**\n * State used in rendering MenuPopover\n */\nexport type MenuPopoverState = ComponentState<MenuPopoverSlots> &\n Pick<PortalProps, 'mountNode'> & {\n /**\n * Root menus are rendered out of DOM order on `document.body`, use this to render the menu in DOM order\n * This option is disregarded for submenus\n */\n inline: boolean;\n\n safeZone?: React.ReactElement | null;\n };\n"],"names":["React"],"mappings":"AAEA,YAAYA,WAAW,QAAQ"}

View File

@@ -0,0 +1,4 @@
export { MenuPopover } from './MenuPopover';
export { renderMenuPopover_unstable } from './renderMenuPopover';
export { useMenuPopover_unstable } from './useMenuPopover';
export { menuPopoverClassNames, useMenuPopoverStyles_unstable } from './useMenuPopoverStyles.styles';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/MenuPopover/index.ts"],"sourcesContent":["export { MenuPopover } from './MenuPopover';\nexport type { MenuPopoverProps, MenuPopoverSlots, MenuPopoverState } from './MenuPopover.types';\nexport { renderMenuPopover_unstable } from './renderMenuPopover';\nexport { useMenuPopover_unstable } from './useMenuPopover';\nexport { menuPopoverClassNames, useMenuPopoverStyles_unstable } from './useMenuPopoverStyles.styles';\n"],"names":["MenuPopover","renderMenuPopover_unstable","useMenuPopover_unstable","menuPopoverClassNames","useMenuPopoverStyles_unstable"],"mappings":"AAAA,SAASA,WAAW,QAAQ,gBAAgB;AAE5C,SAASC,0BAA0B,QAAQ,sBAAsB;AACjE,SAASC,uBAAuB,QAAQ,mBAAmB;AAC3D,SAASC,qBAAqB,EAAEC,6BAA6B,QAAQ,gCAAgC"}

View File

@@ -0,0 +1,23 @@
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "@fluentui/react-jsx-runtime/jsx-runtime";
import { assertSlots } from '@fluentui/react-utilities';
import { Portal } from '@fluentui/react-portal';
/**
* Render the final JSX of MenuPopover
*/ export const renderMenuPopover_unstable = (state)=>{
assertSlots(state);
if (state.inline) {
return /*#__PURE__*/ _jsxs(_Fragment, {
children: [
/*#__PURE__*/ _jsx(state.root, {}),
state.safeZone
]
});
}
return /*#__PURE__*/ _jsxs(Portal, {
mountNode: state.mountNode,
children: [
/*#__PURE__*/ _jsx(state.root, {}),
state.safeZone
]
});
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/MenuPopover/renderMenuPopover.tsx"],"sourcesContent":["/** @jsxRuntime automatic */\n/** @jsxImportSource @fluentui/react-jsx-runtime */\nimport { assertSlots } from '@fluentui/react-utilities';\nimport type { JSXElement } from '@fluentui/react-utilities';\nimport { MenuPopoverSlots, MenuPopoverState } from './MenuPopover.types';\nimport { Portal } from '@fluentui/react-portal';\n\n/**\n * Render the final JSX of MenuPopover\n */\nexport const renderMenuPopover_unstable = (state: MenuPopoverState): JSXElement => {\n assertSlots<MenuPopoverSlots>(state);\n\n if (state.inline) {\n return (\n <>\n <state.root />\n {state.safeZone}\n </>\n );\n }\n\n return (\n <Portal mountNode={state.mountNode}>\n <state.root />\n {state.safeZone}\n </Portal>\n );\n};\n"],"names":["assertSlots","Portal","renderMenuPopover_unstable","state","inline","root","safeZone","mountNode"],"mappings":"AAAA,0BAA0B,GAC1B,iDAAiD;AACjD,SAASA,WAAW,QAAQ,4BAA4B;AAGxD,SAASC,MAAM,QAAQ,yBAAyB;AAEhD;;CAEC,GACD,OAAO,MAAMC,6BAA6B,CAACC;IACzCH,YAA8BG;IAE9B,IAAIA,MAAMC,MAAM,EAAE;QAChB,qBACE;;8BACE,KAACD,MAAME,IAAI;gBACVF,MAAMG,QAAQ;;;IAGrB;IAEA,qBACE,MAACL;QAAOM,WAAWJ,MAAMI,SAAS;;0BAChC,KAACJ,MAAME,IAAI;YACVF,MAAMG,QAAQ;;;AAGrB,EAAE"}

View File

@@ -0,0 +1,128 @@
'use client';
import { ArrowLeft, Tab, ArrowRight, Escape } from '@fluentui/keyboard-keys';
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';
import { useMotionForwardedRef } from '@fluentui/react-motion';
import { useRestoreFocusSource } from '@fluentui/react-tabster';
import { getIntrinsicElementProps, useEventCallback, useMergedRefs, slot, useTimeout } from '@fluentui/react-utilities';
import * as React from 'react';
import { useMenuContext_unstable } from '../../contexts/menuContext';
import { useMenuListContext_unstable } from '../../contexts/menuListContext';
import { dispatchMenuEnterEvent, useIsSubmenu } from '../../utils/index';
/**
* Create the state required to render MenuPopover.
*
* The returned state can be modified with hooks such as useMenuPopoverStyles_unstable,
* before being passed to renderMenuPopover_unstable.
*
* @param props - props from this instance of MenuPopover
* @param ref - reference to root HTMLElement of MenuPopover
*/ export const useMenuPopover_unstable = (props, ref)=>{
'use no memo';
const safeZone = useMenuContext_unstable((context)=>context.safeZone);
const popoverRef = useMenuContext_unstable((context)=>context.menuPopoverRef);
const setOpen = useMenuContext_unstable((context)=>context.setOpen);
const open = useMenuContext_unstable((context)=>context.open);
const openOnHover = useMenuContext_unstable((context)=>context.openOnHover);
const triggerRef = useMenuContext_unstable((context)=>context.triggerRef);
const isSubmenu = useIsSubmenu();
const shouldCloseOnArrowLeft = useMenuListContext_unstable((ctx)=>{
var _ctx_shouldCloseOnArrowLeft;
return (_ctx_shouldCloseOnArrowLeft = ctx.shouldCloseOnArrowLeft) !== null && _ctx_shouldCloseOnArrowLeft !== void 0 ? _ctx_shouldCloseOnArrowLeft : true;
});
const canDispatchCustomEventRef = React.useRef(true);
const restoreFocusSourceAttributes = useRestoreFocusSource();
const [setThrottleTimeout, clearThrottleTimeout] = useTimeout();
const { dir } = useFluent();
const CloseArrowKey = dir === 'ltr' ? ArrowLeft : ArrowRight;
// use DOM listener since react events propagate up the react tree
// no need to do `contains` logic as menus are all positioned in different portals
const mouseOverListenerCallbackRef = React.useCallback((node)=>{
if (node) {
// Dispatches the custom menu mouse enter event with throttling
// Needs to trigger on mouseover to support keyboard + mouse together
// i.e. keyboard opens submenus while cursor is still on the parent
node.addEventListener('mouseover', (e)=>{
if (canDispatchCustomEventRef.current) {
canDispatchCustomEventRef.current = false;
dispatchMenuEnterEvent(popoverRef.current, e);
setThrottleTimeout(()=>{
canDispatchCustomEventRef.current = true;
}, 250);
}
});
}
}, [
popoverRef,
setThrottleTimeout
]);
React.useEffect(()=>{
return ()=>clearThrottleTimeout();
}, [
clearThrottleTimeout
]);
var _useMenuContext_unstable;
const inline = (_useMenuContext_unstable = useMenuContext_unstable((context)=>context.inline)) !== null && _useMenuContext_unstable !== void 0 ? _useMenuContext_unstable : false;
const mountNode = useMenuContext_unstable((context)=>context.mountNode);
const rootProps = slot.always(getIntrinsicElementProps('div', {
role: 'presentation',
...restoreFocusSourceAttributes,
...props,
// FIXME:
// `ref` is wrongly assigned to be `HTMLElement` instead of `HTMLDivElement`
// but since it would be a breaking change to fix it, we are casting ref to it's proper type
ref: useMergedRefs(ref, popoverRef, mouseOverListenerCallbackRef, useMotionForwardedRef())
}), {
elementType: 'div'
});
const { onMouseEnter: onMouseEnterOriginal, onKeyDown: onKeyDownOriginal } = rootProps;
rootProps.onMouseEnter = useEventCallback((event)=>{
if (openOnHover || isSubmenu) {
setOpen(event, {
open: true,
keyboard: false,
type: 'menuPopoverMouseEnter',
event
});
}
onMouseEnterOriginal === null || onMouseEnterOriginal === void 0 ? void 0 : onMouseEnterOriginal(event);
});
rootProps.onKeyDown = useEventCallback((event)=>{
const key = event.key;
if (key === Escape || isSubmenu && shouldCloseOnArrowLeft && key === CloseArrowKey) {
var _popoverRef_current;
if (open && ((_popoverRef_current = popoverRef.current) === null || _popoverRef_current === void 0 ? void 0 : _popoverRef_current.contains(event.target)) && !event.isDefaultPrevented()) {
setOpen(event, {
open: false,
keyboard: true,
type: 'menuPopoverKeyDown',
event
});
// stop propagation to avoid conflicting with other elements that listen for `Escape`
// e,g: Dialog, Popover, Menu and Tooltip
event.preventDefault();
}
}
if (key === Tab) {
setOpen(event, {
open: false,
keyboard: true,
type: 'menuPopoverKeyDown',
event
});
if (!isSubmenu) {
var _triggerRef_current;
(_triggerRef_current = triggerRef.current) === null || _triggerRef_current === void 0 ? void 0 : _triggerRef_current.focus();
}
}
onKeyDownOriginal === null || onKeyDownOriginal === void 0 ? void 0 : onKeyDownOriginal(event);
});
return {
inline,
mountNode,
safeZone,
components: {
root: 'div'
},
root: rootProps
};
};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,68 @@
'use client';
import { mergeClasses, __styles } from '@griffel/react';
import { tokens, typographyStyles } from '@fluentui/react-theme';
export const menuPopoverClassNames = {
root: 'fui-MenuPopover'
};
const useStyles = /*#__PURE__*/__styles({
root: {
Beyfa6y: 0,
Bbmb7ep: 0,
Btl43ni: 0,
B7oj6ja: 0,
Dimara: "ft85np5",
De3pzq: "fxugw4r",
sj55zd: "f19n0e5",
B7ck84d: "f1ewtqcl",
Bf4jedk: "fl8fusi",
B2u0y6b: "f1kaai3v",
B68tc82: "f1p9o1ba",
a9b677: "f1ahpp82",
E5pizo: "f1hg901r",
Byoj8tv: 0,
uwmqm3: 0,
z189sj: 0,
z8tnut: 0,
B0ocmuz: "fd3pd8h",
Bgfg5da: 0,
B9xav0g: 0,
oivjwe: 0,
Bn0qgzm: 0,
B4g9neb: 0,
zhjwy3: 0,
wvpqe5: 0,
ibv6hh: 0,
u1mtju: 0,
h3c5rm: 0,
vrafjx: 0,
Bekrc4i: 0,
i8vvqc: 0,
g2u3we: 0,
icvyot: 0,
B4j52fo: 0,
irswps: "f9ggezi",
Bahqtrf: "fk6fouc",
Be2twd7: "fkhj508",
Bhrd7zp: "figsok6",
Bg96gwp: "f1i3iumi"
}
}, {
d: [[".ft85np5{border-radius:var(--borderRadiusMedium);}", {
p: -1
}], ".fxugw4r{background-color:var(--colorNeutralBackground1);}", ".f19n0e5{color:var(--colorNeutralForeground1);}", ".f1ewtqcl{box-sizing:border-box;}", ".fl8fusi{min-width:138px;}", ".f1kaai3v{max-width:300px;}", ".f1p9o1ba{overflow-x:hidden;}", ".f1ahpp82{width:max-content;}", ".f1hg901r{box-shadow:var(--shadow16);}", [".fd3pd8h{padding:4px;}", {
p: -1
}], [".f9ggezi{border:1px solid var(--colorTransparentStroke);}", {
p: -2
}], ".fk6fouc{font-family:var(--fontFamilyBase);}", ".fkhj508{font-size:var(--fontSizeBase300);}", ".figsok6{font-weight:var(--fontWeightRegular);}", ".f1i3iumi{line-height:var(--lineHeightBase300);}"]
});
/**
* Apply styling to the Menu slots based on the state
*/
export const useMenuPopoverStyles_unstable = state => {
'use no memo';
const styles = useStyles();
state.root.className = mergeClasses(menuPopoverClassNames.root, styles.root, state.root.className);
return state;
};

View File

@@ -0,0 +1 @@
{"version":3,"names":["mergeClasses","__styles","tokens","typographyStyles","menuPopoverClassNames","root","useStyles","Beyfa6y","Bbmb7ep","Btl43ni","B7oj6ja","Dimara","De3pzq","sj55zd","B7ck84d","Bf4jedk","B2u0y6b","B68tc82","a9b677","E5pizo","Byoj8tv","uwmqm3","z189sj","z8tnut","B0ocmuz","Bgfg5da","B9xav0g","oivjwe","Bn0qgzm","B4g9neb","zhjwy3","wvpqe5","ibv6hh","u1mtju","h3c5rm","vrafjx","Bekrc4i","i8vvqc","g2u3we","icvyot","B4j52fo","irswps","Bahqtrf","Be2twd7","Bhrd7zp","Bg96gwp","d","p","useMenuPopoverStyles_unstable","state","styles","className"],"sources":["useMenuPopoverStyles.styles.js"],"sourcesContent":["'use client';\nimport { mergeClasses, makeStyles } from '@griffel/react';\nimport { tokens, typographyStyles } from '@fluentui/react-theme';\nexport const menuPopoverClassNames = {\n root: 'fui-MenuPopover'\n};\nconst useStyles = makeStyles({\n root: {\n borderRadius: tokens.borderRadiusMedium,\n backgroundColor: tokens.colorNeutralBackground1,\n color: tokens.colorNeutralForeground1,\n boxSizing: 'border-box',\n minWidth: '138px',\n maxWidth: '300px',\n overflowX: 'hidden',\n width: 'max-content',\n boxShadow: `${tokens.shadow16}`,\n padding: '4px',\n border: `1px solid ${tokens.colorTransparentStroke}`,\n ...typographyStyles.body1\n }\n});\n/**\n * Apply styling to the Menu slots based on the state\n */ export const useMenuPopoverStyles_unstable = (state)=>{\n 'use no memo';\n const styles = useStyles();\n state.root.className = mergeClasses(menuPopoverClassNames.root, styles.root, state.root.className);\n return state;\n};\n"],"mappings":"AAAA,YAAY;;AACZ,SAASA,YAAY,EAAAC,QAAA,QAAoB,gBAAgB;AACzD,SAASC,MAAM,EAAEC,gBAAgB,QAAQ,uBAAuB;AAChE,OAAO,MAAMC,qBAAqB,GAAG;EACjCC,IAAI,EAAE;AACV,CAAC;AACD,MAAMC,SAAS,gBAAGL,QAAA;EAAAI,IAAA;IAAAE,OAAA;IAAAC,OAAA;IAAAC,OAAA;IAAAC,OAAA;IAAAC,MAAA;IAAAC,MAAA;IAAAC,MAAA;IAAAC,OAAA;IAAAC,OAAA;IAAAC,OAAA;IAAAC,OAAA;IAAAC,MAAA;IAAAC,MAAA;IAAAC,OAAA;IAAAC,MAAA;IAAAC,MAAA;IAAAC,MAAA;IAAAC,OAAA;IAAAC,OAAA;IAAAC,OAAA;IAAAC,MAAA;IAAAC,OAAA;IAAAC,OAAA;IAAAC,MAAA;IAAAC,MAAA;IAAAC,MAAA;IAAAC,MAAA;IAAAC,MAAA;IAAAC,MAAA;IAAAC,OAAA;IAAAC,MAAA;IAAAC,MAAA;IAAAC,MAAA;IAAAC,OAAA;IAAAC,MAAA;IAAAC,OAAA;IAAAC,OAAA;IAAAC,OAAA;IAAAC,OAAA;EAAA;AAAA;EAAAC,CAAA;IAAAC,CAAA;EAAA;IAAAA,CAAA;EAAA;IAAAA,CAAA;EAAA;AAAA,CAejB,CAAC;AACF;AACA;AACA;AAAI,OAAO,MAAMC,6BAA6B,GAAIC,KAAK,IAAG;EACtD,aAAa;;EACb,MAAMC,MAAM,GAAG5C,SAAS,CAAC,CAAC;EAC1B2C,KAAK,CAAC5C,IAAI,CAAC8C,SAAS,GAAGnD,YAAY,CAACI,qBAAqB,CAACC,IAAI,EAAE6C,MAAM,CAAC7C,IAAI,EAAE4C,KAAK,CAAC5C,IAAI,CAAC8C,SAAS,CAAC;EAClG,OAAOF,KAAK;AAChB,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,30 @@
'use client';
import { mergeClasses, makeStyles } from '@griffel/react';
import { tokens, typographyStyles } from '@fluentui/react-theme';
export const menuPopoverClassNames = {
root: 'fui-MenuPopover'
};
const useStyles = makeStyles({
root: {
borderRadius: tokens.borderRadiusMedium,
backgroundColor: tokens.colorNeutralBackground1,
color: tokens.colorNeutralForeground1,
boxSizing: 'border-box',
minWidth: '138px',
maxWidth: '300px',
overflowX: 'hidden',
width: 'max-content',
boxShadow: `${tokens.shadow16}`,
padding: '4px',
border: `1px solid ${tokens.colorTransparentStroke}`,
...typographyStyles.body1
}
});
/**
* Apply styling to the Menu slots based on the state
*/ export const useMenuPopoverStyles_unstable = (state)=>{
'use no memo';
const styles = useStyles();
state.root.className = mergeClasses(menuPopoverClassNames.root, styles.root, state.root.className);
return state;
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/MenuPopover/useMenuPopoverStyles.styles.ts"],"sourcesContent":["'use client';\n\nimport { mergeClasses, makeStyles } from '@griffel/react';\nimport { tokens, typographyStyles } from '@fluentui/react-theme';\nimport type { MenuPopoverSlots, MenuPopoverState } from './MenuPopover.types';\nimport type { SlotClassNames } from '@fluentui/react-utilities';\n\nexport const menuPopoverClassNames: SlotClassNames<MenuPopoverSlots> = {\n root: 'fui-MenuPopover',\n};\n\nconst useStyles = makeStyles({\n root: {\n borderRadius: tokens.borderRadiusMedium,\n backgroundColor: tokens.colorNeutralBackground1,\n color: tokens.colorNeutralForeground1,\n boxSizing: 'border-box',\n minWidth: '138px',\n maxWidth: '300px',\n overflowX: 'hidden',\n width: 'max-content',\n boxShadow: `${tokens.shadow16}`,\n padding: '4px',\n border: `1px solid ${tokens.colorTransparentStroke}`,\n ...typographyStyles.body1,\n },\n});\n\n/**\n * Apply styling to the Menu slots based on the state\n */\nexport const useMenuPopoverStyles_unstable = (state: MenuPopoverState): MenuPopoverState => {\n 'use no memo';\n\n const styles = useStyles();\n state.root.className = mergeClasses(menuPopoverClassNames.root, styles.root, state.root.className);\n return state;\n};\n"],"names":["mergeClasses","makeStyles","tokens","typographyStyles","menuPopoverClassNames","root","useStyles","borderRadius","borderRadiusMedium","backgroundColor","colorNeutralBackground1","color","colorNeutralForeground1","boxSizing","minWidth","maxWidth","overflowX","width","boxShadow","shadow16","padding","border","colorTransparentStroke","body1","useMenuPopoverStyles_unstable","state","styles","className"],"mappings":"AAAA;AAEA,SAASA,YAAY,EAAEC,UAAU,QAAQ,iBAAiB;AAC1D,SAASC,MAAM,EAAEC,gBAAgB,QAAQ,wBAAwB;AAIjE,OAAO,MAAMC,wBAA0D;IACrEC,MAAM;AACR,EAAE;AAEF,MAAMC,YAAYL,WAAW;IAC3BI,MAAM;QACJE,cAAcL,OAAOM,kBAAkB;QACvCC,iBAAiBP,OAAOQ,uBAAuB;QAC/CC,OAAOT,OAAOU,uBAAuB;QACrCC,WAAW;QACXC,UAAU;QACVC,UAAU;QACVC,WAAW;QACXC,OAAO;QACPC,WAAW,GAAGhB,OAAOiB,QAAQ,EAAE;QAC/BC,SAAS;QACTC,QAAQ,CAAC,UAAU,EAAEnB,OAAOoB,sBAAsB,EAAE;QACpD,GAAGnB,iBAAiBoB,KAAK;IAC3B;AACF;AAEA;;CAEC,GACD,OAAO,MAAMC,gCAAgC,CAACC;IAC5C;IAEA,MAAMC,SAASpB;IACfmB,MAAMpB,IAAI,CAACsB,SAAS,GAAG3B,aAAaI,sBAAsBC,IAAI,EAAEqB,OAAOrB,IAAI,EAAEoB,MAAMpB,IAAI,CAACsB,SAAS;IACjG,OAAOF;AACT,EAAE"}