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,18 @@
'use client';
import * as React from 'react';
import { useTree_unstable } from './useTree';
import { useTreeContextValues_unstable } from './useTreeContextValues';
import { useTreeStyles_unstable } from './useTreeStyles.styles';
import { renderTree_unstable } from './renderTree';
import { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';
/**
* The `Tree` component renders nested items in a hierarchical structure.
* Use it with `TreeItem` component and layouts components `TreeItemLayout` or `TreeItemPersonaLayout`.
*/ export const Tree = /*#__PURE__*/ React.forwardRef((props, ref)=>{
const state = useTree_unstable(props, ref);
const contextValues = useTreeContextValues_unstable(state);
useTreeStyles_unstable(state);
useCustomStyleHook_unstable('useTreeStyles_unstable')(state);
return renderTree_unstable(state, contextValues);
});
Tree.displayName = 'Tree';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/Tree/Tree.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport type { ForwardRefComponent } from '@fluentui/react-utilities';\nimport { useTree_unstable } from './useTree';\nimport type { TreeProps } from './Tree.types';\nimport { useTreeContextValues_unstable } from './useTreeContextValues';\nimport { useTreeStyles_unstable } from './useTreeStyles.styles';\nimport { renderTree_unstable } from './renderTree';\nimport { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';\n\n/**\n * The `Tree` component renders nested items in a hierarchical structure.\n * Use it with `TreeItem` component and layouts components `TreeItemLayout` or `TreeItemPersonaLayout`.\n */\nexport const Tree: ForwardRefComponent<TreeProps> = React.forwardRef((props, ref) => {\n const state = useTree_unstable(props, ref);\n const contextValues = useTreeContextValues_unstable(state);\n useTreeStyles_unstable(state);\n useCustomStyleHook_unstable('useTreeStyles_unstable')(state);\n\n return renderTree_unstable(state, contextValues);\n});\n\nTree.displayName = 'Tree';\n"],"names":["React","useTree_unstable","useTreeContextValues_unstable","useTreeStyles_unstable","renderTree_unstable","useCustomStyleHook_unstable","Tree","forwardRef","props","ref","state","contextValues","displayName"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAE/B,SAASC,gBAAgB,QAAQ,YAAY;AAE7C,SAASC,6BAA6B,QAAQ,yBAAyB;AACvE,SAASC,sBAAsB,QAAQ,yBAAyB;AAChE,SAASC,mBAAmB,QAAQ,eAAe;AACnD,SAASC,2BAA2B,QAAQ,kCAAkC;AAE9E;;;CAGC,GACD,OAAO,MAAMC,qBAAuCN,MAAMO,UAAU,CAAC,CAACC,OAAOC;IAC3E,MAAMC,QAAQT,iBAAiBO,OAAOC;IACtC,MAAME,gBAAgBT,8BAA8BQ;IACpDP,uBAAuBO;IACvBL,4BAA4B,0BAA0BK;IAEtD,OAAON,oBAAoBM,OAAOC;AACpC,GAAG;AAEHL,KAAKM,WAAW,GAAG"}

View File

@@ -0,0 +1,3 @@
/**
* State used in rendering Tree
*/ export { };

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
export { Tree } from './Tree';
export { useTree_unstable } from './useTree';
export { useTreeContextValues_unstable } from './useTreeContextValues';
export { treeClassNames, useTreeStyles_unstable } from './useTreeStyles.styles';
export { renderTree_unstable } from './renderTree';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/Tree/index.ts"],"sourcesContent":["export { Tree } from './Tree';\nexport type {\n TreeCheckedChangeData,\n TreeCheckedChangeEvent,\n TreeContextValues,\n TreeNavigationData_unstable,\n TreeNavigationEvent_unstable,\n TreeOpenChangeData,\n TreeOpenChangeEvent,\n TreeProps,\n TreeSelectionValue,\n TreeSlots,\n TreeState,\n TreeNavigationMode,\n TreeNavigationDataParam,\n} from './Tree.types';\nexport { useTree_unstable } from './useTree';\nexport { useTreeContextValues_unstable } from './useTreeContextValues';\nexport { treeClassNames, useTreeStyles_unstable } from './useTreeStyles.styles';\nexport { renderTree_unstable } from './renderTree';\n"],"names":["Tree","useTree_unstable","useTreeContextValues_unstable","treeClassNames","useTreeStyles_unstable","renderTree_unstable"],"mappings":"AAAA,SAASA,IAAI,QAAQ,SAAS;AAgB9B,SAASC,gBAAgB,QAAQ,YAAY;AAC7C,SAASC,6BAA6B,QAAQ,yBAAyB;AACvE,SAASC,cAAc,EAAEC,sBAAsB,QAAQ,yBAAyB;AAChF,SAASC,mBAAmB,QAAQ,eAAe"}

View File

@@ -0,0 +1,12 @@
import { jsx as _jsx } from "@fluentui/react-jsx-runtime/jsx-runtime";
import { assertSlots } from '@fluentui/react-utilities';
import { TreeProvider } from '../TreeProvider';
export const renderTree_unstable = (state, contextValues)=>{
assertSlots(state);
return /*#__PURE__*/ _jsx(TreeProvider, {
value: contextValues.tree,
children: state.collapseMotion ? /*#__PURE__*/ _jsx(state.collapseMotion, {
children: /*#__PURE__*/ _jsx(state.root, {})
}) : /*#__PURE__*/ _jsx(state.root, {})
});
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/Tree/renderTree.tsx"],"sourcesContent":["/** @jsxRuntime automatic */\n/** @jsxImportSource @fluentui/react-jsx-runtime */\nimport { assertSlots } from '@fluentui/react-utilities';\nimport type { JSXElement } from '@fluentui/react-utilities';\nimport type { TreeContextValues, TreeSlots, TreeState } from '../Tree/Tree.types';\nimport { TreeProvider } from '../TreeProvider';\n\nexport const renderTree_unstable = (state: TreeState, contextValues: TreeContextValues): JSXElement => {\n assertSlots<TreeSlots>(state);\n return (\n <TreeProvider value={contextValues.tree}>\n {state.collapseMotion ? (\n <state.collapseMotion>\n <state.root />\n </state.collapseMotion>\n ) : (\n <state.root />\n )}\n </TreeProvider>\n );\n};\n"],"names":["assertSlots","TreeProvider","renderTree_unstable","state","contextValues","value","tree","collapseMotion","root"],"mappings":"AAAA,0BAA0B,GAC1B,iDAAiD;AACjD,SAASA,WAAW,QAAQ,4BAA4B;AAGxD,SAASC,YAAY,QAAQ,kBAAkB;AAE/C,OAAO,MAAMC,sBAAsB,CAACC,OAAkBC;IACpDJ,YAAuBG;IACvB,qBACE,KAACF;QAAaI,OAAOD,cAAcE,IAAI;kBACpCH,MAAMI,cAAc,iBACnB,KAACJ,MAAMI,cAAc;sBACnB,cAAA,KAACJ,MAAMK,IAAI;2BAGb,KAACL,MAAMK,IAAI;;AAInB,EAAE"}

View File

@@ -0,0 +1,23 @@
'use client';
import * as React from 'react';
import { ImmutableMap } from '../../utils/ImmutableMap';
import { createCheckedItems } from '../../utils/createCheckedItems';
export function useNestedCheckedItems(props) {
return React.useMemo(()=>createCheckedItems(props.checkedItems), [
props.checkedItems
]);
}
export function createNextNestedCheckedItems(data, previousCheckedItems) {
if (data.selectionMode === 'single') {
return ImmutableMap.from([
[
data.value,
data.checked
]
]);
}
if (data.selectionMode === 'multiselect') {
return previousCheckedItems.set(data.value, data.checked);
}
return previousCheckedItems;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/Tree/useNestedControllableCheckedItems.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport type { TreeCheckedChangeData, TreeProps } from './Tree.types';\nimport { ImmutableMap } from '../../utils/ImmutableMap';\nimport { createCheckedItems } from '../../utils/createCheckedItems';\nimport { TreeItemValue } from '../TreeItem/TreeItem.types';\n\nexport function useNestedCheckedItems(\n props: Pick<TreeProps, 'checkedItems'>,\n): ImmutableMap<TreeItemValue, 'mixed' | boolean> {\n return React.useMemo(() => createCheckedItems(props.checkedItems), [props.checkedItems]);\n}\n\nexport function createNextNestedCheckedItems(\n data: Pick<TreeCheckedChangeData, 'selectionMode' | 'value' | 'checked'>,\n previousCheckedItems: ImmutableMap<TreeItemValue, 'mixed' | boolean>,\n): ImmutableMap<TreeItemValue, 'mixed' | boolean> {\n if (data.selectionMode === 'single') {\n return ImmutableMap.from([[data.value, data.checked]]);\n }\n if (data.selectionMode === 'multiselect') {\n return previousCheckedItems.set(data.value, data.checked);\n }\n return previousCheckedItems;\n}\n"],"names":["React","ImmutableMap","createCheckedItems","useNestedCheckedItems","props","useMemo","checkedItems","createNextNestedCheckedItems","data","previousCheckedItems","selectionMode","from","value","checked","set"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAE/B,SAASC,YAAY,QAAQ,2BAA2B;AACxD,SAASC,kBAAkB,QAAQ,iCAAiC;AAGpE,OAAO,SAASC,sBACdC,KAAsC;IAEtC,OAAOJ,MAAMK,OAAO,CAAC,IAAMH,mBAAmBE,MAAME,YAAY,GAAG;QAACF,MAAME,YAAY;KAAC;AACzF;AAEA,OAAO,SAASC,6BACdC,IAAwE,EACxEC,oBAAoE;IAEpE,IAAID,KAAKE,aAAa,KAAK,UAAU;QACnC,OAAOT,aAAaU,IAAI,CAAC;YAAC;gBAACH,KAAKI,KAAK;gBAAEJ,KAAKK,OAAO;aAAC;SAAC;IACvD;IACA,IAAIL,KAAKE,aAAa,KAAK,eAAe;QACxC,OAAOD,qBAAqBK,GAAG,CAACN,KAAKI,KAAK,EAAEJ,KAAKK,OAAO;IAC1D;IACA,OAAOJ;AACT"}

View File

@@ -0,0 +1,74 @@
'use client';
import * as React from 'react';
import { useEventCallback, useMergedRefs } from '@fluentui/react-utilities';
import { createNextOpenItems, useControllableOpenItems } from '../../hooks/useControllableOpenItems';
import { createNextNestedCheckedItems, useNestedCheckedItems } from './useNestedControllableCheckedItems';
import { SubtreeContext } from '../../contexts/subtreeContext';
import { useRootTree } from '../../hooks/useRootTree';
import { useSubtree } from '../../hooks/useSubtree';
import { useTreeNavigation } from '../../hooks/useTreeNavigation';
import { useTreeContext_unstable } from '../../contexts/treeContext';
import { ImmutableSet } from '../../utils/ImmutableSet';
import { ImmutableMap } from '../../utils/ImmutableMap';
export const useTree_unstable = (props, ref)=>{
'use no memo';
const isRoot = React.useContext(SubtreeContext) === undefined;
// as level is static, this doesn't break rule of hooks
// and if this becomes an issue later on, this can be easily converted
// eslint-disable-next-line react-hooks/rules-of-hooks
return isRoot ? useNestedRootTree(props, ref) : useNestedSubtree(props, ref);
};
function useNestedRootTree(props, ref) {
'use no memo';
const [openItems, setOpenItems] = useControllableOpenItems(props);
const checkedItems = useNestedCheckedItems(props);
const navigation = useTreeNavigation(props.navigationMode);
return Object.assign(useRootTree({
...props,
openItems,
checkedItems,
onOpenChange: useEventCallback((event, data)=>{
var _props_onOpenChange;
const nextOpenItems = createNextOpenItems(data, openItems);
(_props_onOpenChange = props.onOpenChange) === null || _props_onOpenChange === void 0 ? void 0 : _props_onOpenChange.call(props, event, {
...data,
openItems: ImmutableSet.dangerouslyGetInternalSet(nextOpenItems)
});
setOpenItems(nextOpenItems);
}),
onNavigation: useEventCallback((event, data)=>{
var _props_onNavigation;
(_props_onNavigation = props.onNavigation) === null || _props_onNavigation === void 0 ? void 0 : _props_onNavigation.call(props, event, data);
if (!event.isDefaultPrevented()) {
navigation.navigate(data, {
preventScroll: data.isScrollPrevented()
});
}
}),
onCheckedChange: useEventCallback((event, data)=>{
var _props_onCheckedChange;
const nextCheckedItems = createNextNestedCheckedItems(data, checkedItems);
(_props_onCheckedChange = props.onCheckedChange) === null || _props_onCheckedChange === void 0 ? void 0 : _props_onCheckedChange.call(props, event, {
...data,
checkedItems: ImmutableMap.dangerouslyGetInternalMap(nextCheckedItems)
});
})
}, useMergedRefs(ref, navigation.treeRef)), {
treeType: 'nested',
forceUpdateRovingTabIndex: navigation.forceUpdateRovingTabIndex
});
}
function useNestedSubtree(props, ref) {
'use no memo';
if (process.env.NODE_ENV === 'development') {
// this doesn't break rule of hooks, as environment is a static value
// eslint-disable-next-line react-hooks/rules-of-hooks
const treeType = useTreeContext_unstable((ctx)=>ctx.treeType);
if (treeType === 'flat') {
throw new Error(`@fluentui/react-tree [useTree]:
Subtrees are not allowed in a FlatTree!
You cannot use a <Tree> component inside of a <FlatTree> component!`);
}
}
return useSubtree(props, ref);
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,37 @@
'use client';
import * as React from 'react';
export function useTreeContextValues_unstable(state) {
'use no memo';
if (state.contextType === 'root') {
const { openItems, level, contextType, treeType, checkedItems, selectionMode, navigationMode, appearance, size, requestTreeResponse, forceUpdateRovingTabIndex } = state;
/**
* This context is created with "@fluentui/react-context-selector",
* there is no sense to memoize it
*/ const tree = {
treeType,
size,
openItems,
appearance,
checkedItems,
selectionMode,
navigationMode,
contextType,
level,
requestTreeResponse,
forceUpdateRovingTabIndex
};
return {
tree
};
}
return {
// contextType is statically determined by the context
// eslint-disable-next-line react-hooks/rules-of-hooks
tree: React.useMemo(()=>({
level: state.level,
contextType: 'subtree'
}), [
state.level
])
};
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/Tree/useTreeContextValues.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { TreeContextValue } from '../../contexts';\nimport { TreeContextValues, TreeState } from './Tree.types';\n\nexport function useTreeContextValues_unstable(state: TreeState): TreeContextValues {\n 'use no memo';\n\n if (state.contextType === 'root') {\n const {\n openItems,\n level,\n contextType,\n treeType,\n checkedItems,\n selectionMode,\n navigationMode,\n appearance,\n size,\n requestTreeResponse,\n forceUpdateRovingTabIndex,\n } = state;\n /**\n * This context is created with \"@fluentui/react-context-selector\",\n * there is no sense to memoize it\n */\n const tree: TreeContextValue = {\n treeType,\n size,\n openItems,\n appearance,\n checkedItems,\n selectionMode,\n navigationMode,\n contextType,\n level,\n requestTreeResponse,\n forceUpdateRovingTabIndex,\n };\n\n return { tree };\n }\n return {\n // contextType is statically determined by the context\n // eslint-disable-next-line react-hooks/rules-of-hooks\n tree: React.useMemo(() => ({ level: state.level, contextType: 'subtree' }), [state.level]),\n };\n}\n"],"names":["React","useTreeContextValues_unstable","state","contextType","openItems","level","treeType","checkedItems","selectionMode","navigationMode","appearance","size","requestTreeResponse","forceUpdateRovingTabIndex","tree","useMemo"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAI/B,OAAO,SAASC,8BAA8BC,KAAgB;IAC5D;IAEA,IAAIA,MAAMC,WAAW,KAAK,QAAQ;QAChC,MAAM,EACJC,SAAS,EACTC,KAAK,EACLF,WAAW,EACXG,QAAQ,EACRC,YAAY,EACZC,aAAa,EACbC,cAAc,EACdC,UAAU,EACVC,IAAI,EACJC,mBAAmB,EACnBC,yBAAyB,EAC1B,GAAGX;QACJ;;;KAGC,GACD,MAAMY,OAAyB;YAC7BR;YACAK;YACAP;YACAM;YACAH;YACAC;YACAC;YACAN;YACAE;YACAO;YACAC;QACF;QAEA,OAAO;YAAEC;QAAK;IAChB;IACA,OAAO;QACL,sDAAsD;QACtD,sDAAsD;QACtDA,MAAMd,MAAMe,OAAO,CAAC,IAAO,CAAA;gBAAEV,OAAOH,MAAMG,KAAK;gBAAEF,aAAa;YAAU,CAAA,GAAI;YAACD,MAAMG,KAAK;SAAC;IAC3F;AACF"}

View File

@@ -0,0 +1,24 @@
'use client';
import { __resetStyles, __styles, mergeClasses } from '@griffel/react';
import { tokens } from '@fluentui/react-theme';
export const treeClassNames = {
root: 'fui-Tree'
};
const useBaseStyles = /*#__PURE__*/__resetStyles("rnv2ez3", null, [".rnv2ez3{display:flex;flex-direction:column;row-gap:var(--spacingVerticalXXS);}"]);
const useStyles = /*#__PURE__*/__styles({
subtree: {
z8tnut: "fclwglc"
}
}, {
d: [".fclwglc{padding-top:var(--spacingVerticalXXS);}"]
});
export const useTreeStyles_unstable = state => {
'use no memo';
const baseStyles = useBaseStyles();
const styles = useStyles();
const isSubTree = state.level > 1;
state.root.className = mergeClasses(treeClassNames.root, baseStyles, isSubTree && styles.subtree, state.root.className);
return state;
};

View File

@@ -0,0 +1 @@
{"version":3,"names":["__resetStyles","__styles","mergeClasses","tokens","treeClassNames","root","useBaseStyles","useStyles","subtree","z8tnut","d","useTreeStyles_unstable","state","baseStyles","styles","isSubTree","level","className"],"sources":["useTreeStyles.styles.js"],"sourcesContent":["'use client';\nimport { makeResetStyles, makeStyles, mergeClasses } from '@griffel/react';\nimport { tokens } from '@fluentui/react-theme';\nexport const treeClassNames = {\n root: 'fui-Tree'\n};\nconst useBaseStyles = makeResetStyles({\n display: 'flex',\n flexDirection: 'column',\n rowGap: tokens.spacingVerticalXXS\n});\nconst useStyles = makeStyles({\n subtree: {\n paddingTop: tokens.spacingVerticalXXS\n }\n});\nexport const useTreeStyles_unstable = (state)=>{\n 'use no memo';\n const baseStyles = useBaseStyles();\n const styles = useStyles();\n const isSubTree = state.level > 1;\n state.root.className = mergeClasses(treeClassNames.root, baseStyles, isSubTree && styles.subtree, state.root.className);\n return state;\n};\n"],"mappings":"AAAA,YAAY;;AACZ,SAAAA,aAAA,EAAAC,QAAA,EAAsCC,YAAY,QAAQ,gBAAgB;AAC1E,SAASC,MAAM,QAAQ,uBAAuB;AAC9C,OAAO,MAAMC,cAAc,GAAG;EAC1BC,IAAI,EAAE;AACV,CAAC;AACD,MAAMC,aAAa,gBAAGN,aAAA,qGAIrB,CAAC;AACF,MAAMO,SAAS,gBAAGN,QAAA;EAAAO,OAAA;IAAAC,MAAA;EAAA;AAAA;EAAAC,CAAA;AAAA,CAIjB,CAAC;AACF,OAAO,MAAMC,sBAAsB,GAAIC,KAAK,IAAG;EAC3C,aAAa;;EACb,MAAMC,UAAU,GAAGP,aAAa,CAAC,CAAC;EAClC,MAAMQ,MAAM,GAAGP,SAAS,CAAC,CAAC;EAC1B,MAAMQ,SAAS,GAAGH,KAAK,CAACI,KAAK,GAAG,CAAC;EACjCJ,KAAK,CAACP,IAAI,CAACY,SAAS,GAAGf,YAAY,CAACE,cAAc,CAACC,IAAI,EAAEQ,UAAU,EAAEE,SAAS,IAAID,MAAM,CAACN,OAAO,EAAEI,KAAK,CAACP,IAAI,CAACY,SAAS,CAAC;EACvH,OAAOL,KAAK;AAChB,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,24 @@
'use client';
import { makeResetStyles, makeStyles, mergeClasses } from '@griffel/react';
import { tokens } from '@fluentui/react-theme';
export const treeClassNames = {
root: 'fui-Tree'
};
const useBaseStyles = makeResetStyles({
display: 'flex',
flexDirection: 'column',
rowGap: tokens.spacingVerticalXXS
});
const useStyles = makeStyles({
subtree: {
paddingTop: tokens.spacingVerticalXXS
}
});
export const useTreeStyles_unstable = (state)=>{
'use no memo';
const baseStyles = useBaseStyles();
const styles = useStyles();
const isSubTree = state.level > 1;
state.root.className = mergeClasses(treeClassNames.root, baseStyles, isSubTree && styles.subtree, state.root.className);
return state;
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/Tree/useTreeStyles.styles.ts"],"sourcesContent":["'use client';\n\nimport { makeResetStyles, makeStyles, mergeClasses } from '@griffel/react';\nimport type { TreeSlots, TreeState } from './Tree.types';\nimport type { SlotClassNames } from '@fluentui/react-utilities';\nimport { tokens } from '@fluentui/react-theme';\n\nexport const treeClassNames: SlotClassNames<Omit<TreeSlots, 'collapseMotion'>> = {\n root: 'fui-Tree',\n};\n\nconst useBaseStyles = makeResetStyles({\n display: 'flex',\n flexDirection: 'column',\n rowGap: tokens.spacingVerticalXXS,\n});\n\nconst useStyles = makeStyles({\n subtree: {\n paddingTop: tokens.spacingVerticalXXS,\n },\n});\n\nexport const useTreeStyles_unstable = (state: TreeState): TreeState => {\n 'use no memo';\n\n const baseStyles = useBaseStyles();\n const styles = useStyles();\n const isSubTree = state.level > 1;\n\n state.root.className = mergeClasses(\n treeClassNames.root,\n baseStyles,\n isSubTree && styles.subtree,\n state.root.className,\n );\n return state;\n};\n"],"names":["makeResetStyles","makeStyles","mergeClasses","tokens","treeClassNames","root","useBaseStyles","display","flexDirection","rowGap","spacingVerticalXXS","useStyles","subtree","paddingTop","useTreeStyles_unstable","state","baseStyles","styles","isSubTree","level","className"],"mappings":"AAAA;AAEA,SAASA,eAAe,EAAEC,UAAU,EAAEC,YAAY,QAAQ,iBAAiB;AAG3E,SAASC,MAAM,QAAQ,wBAAwB;AAE/C,OAAO,MAAMC,iBAAoE;IAC/EC,MAAM;AACR,EAAE;AAEF,MAAMC,gBAAgBN,gBAAgB;IACpCO,SAAS;IACTC,eAAe;IACfC,QAAQN,OAAOO,kBAAkB;AACnC;AAEA,MAAMC,YAAYV,WAAW;IAC3BW,SAAS;QACPC,YAAYV,OAAOO,kBAAkB;IACvC;AACF;AAEA,OAAO,MAAMI,yBAAyB,CAACC;IACrC;IAEA,MAAMC,aAAaV;IACnB,MAAMW,SAASN;IACf,MAAMO,YAAYH,MAAMI,KAAK,GAAG;IAEhCJ,MAAMV,IAAI,CAACe,SAAS,GAAGlB,aACrBE,eAAeC,IAAI,EACnBW,YACAE,aAAaD,OAAOL,OAAO,EAC3BG,MAAMV,IAAI,CAACe,SAAS;IAEtB,OAAOL;AACT,EAAE"}