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,22 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "MenuTrigger", {
enumerable: true,
get: function() {
return MenuTrigger;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _useMenuTrigger = require("./useMenuTrigger");
const _renderMenuTrigger = require("./renderMenuTrigger");
const MenuTrigger = (props)=>{
const state = (0, _useMenuTrigger.useMenuTrigger_unstable)(props);
return (0, _renderMenuTrigger.renderMenuTrigger_unstable)(state);
};
MenuTrigger.displayName = 'MenuTrigger';
// type casting here is required to ensure internal type FluentTriggerComponent is not leaked
MenuTrigger.isFluentTriggerComponent = true;

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/MenuTrigger/MenuTrigger.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useMenuTrigger_unstable } from './useMenuTrigger';\nimport { renderMenuTrigger_unstable } from './renderMenuTrigger';\nimport type { MenuTriggerProps } from './MenuTrigger.types';\nimport type { FluentTriggerComponent } from '@fluentui/react-utilities';\n\n/**\n * Wraps a trigger element as an only child\n * and adds the necessary event handling to open a popup menu\n */\nexport const MenuTrigger: React.FC<MenuTriggerProps> = props => {\n const state = useMenuTrigger_unstable(props);\n\n return renderMenuTrigger_unstable(state);\n};\n\nMenuTrigger.displayName = 'MenuTrigger';\n// type casting here is required to ensure internal type FluentTriggerComponent is not leaked\n(MenuTrigger as FluentTriggerComponent).isFluentTriggerComponent = true;\n"],"names":["React","useMenuTrigger_unstable","renderMenuTrigger_unstable","MenuTrigger","props","state","displayName","isFluentTriggerComponent"],"mappings":"AAAA;;;;;;;;;;;;iEAEuB,QAAQ;gCACS,mBAAmB;mCAChB,sBAAsB;AAQ1D,MAAMG,cAA0CC,CAAAA;IACrD,MAAMC,YAAQJ,uCAAAA,EAAwBG;IAEtC,WAAOF,6CAAAA,EAA2BG;AACpC,EAAE;AAEFF,YAAYG,WAAW,GAAG;AAC1B,6FAA6F;AAC5FH,YAAuCI,wBAAwB,GAAG"}

View File

@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/MenuTrigger/MenuTrigger.types.ts"],"sourcesContent":["import { ARIAButtonResultProps, ARIAButtonType } from '@fluentui/react-aria';\nimport type { TriggerProps } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nexport type MenuTriggerProps = TriggerProps<MenuTriggerChildProps> & {\n /**\n * Disables internal trigger mechanism that ensures a child provided will be a compliant ARIA button.\n * @default false\n */\n disableButtonEnhancement?: boolean;\n};\n\n/**\n * Props that are passed to the child of the MenuTrigger when cloned to ensure correct behaviour for the Menu\n */\nexport type MenuTriggerChildProps<Type extends ARIAButtonType = ARIAButtonType, Props = {}> = ARIAButtonResultProps<\n Type,\n Props & {\n 'aria-haspopup'?: 'menu';\n 'aria-expanded'?: boolean;\n id: string;\n ref: React.Ref<never>;\n /* eslint-disable @nx/workspace-consistent-callback-type -- can't change type of existing callback */\n onMouseEnter: React.MouseEventHandler<HTMLButtonElement & HTMLAnchorElement & HTMLDivElement>;\n onMouseLeave: React.MouseEventHandler<HTMLButtonElement & HTMLAnchorElement & HTMLDivElement>;\n onMouseMove: React.MouseEventHandler<HTMLButtonElement & HTMLAnchorElement & HTMLDivElement>;\n onMouseOver?: React.MouseEventHandler<HTMLButtonElement & HTMLAnchorElement & HTMLDivElement>;\n onContextMenu: React.MouseEventHandler<HTMLButtonElement & HTMLAnchorElement & HTMLDivElement>;\n /* eslint-enable @nx/workspace-consistent-callback-type */\n }\n>;\n\nexport type MenuTriggerState = {\n children: React.ReactElement | null;\n isSubmenu: boolean;\n};\n"],"names":["React"],"mappings":";;;;;iEAEuB,QAAQ"}

View File

@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
MenuTrigger: function() {
return _MenuTrigger.MenuTrigger;
},
renderMenuTrigger_unstable: function() {
return _renderMenuTrigger.renderMenuTrigger_unstable;
},
useMenuTrigger_unstable: function() {
return _useMenuTrigger.useMenuTrigger_unstable;
}
});
const _MenuTrigger = require("./MenuTrigger");
const _renderMenuTrigger = require("./renderMenuTrigger");
const _useMenuTrigger = require("./useMenuTrigger");

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/MenuTrigger/index.ts"],"sourcesContent":["export { MenuTrigger } from './MenuTrigger';\nexport type { MenuTriggerChildProps, MenuTriggerProps, MenuTriggerState } from './MenuTrigger.types';\nexport { renderMenuTrigger_unstable } from './renderMenuTrigger';\nexport { useMenuTrigger_unstable } from './useMenuTrigger';\n"],"names":["MenuTrigger","renderMenuTrigger_unstable","useMenuTrigger_unstable"],"mappings":";;;;;;;;;;;;eAASA,wBAAW;;;eAEXC,6CAA0B;;;eAC1BC,uCAAuB;;;6BAHJ,gBAAgB;mCAED,sBAAsB;gCACzB,mBAAmB"}

View File

@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "renderMenuTrigger_unstable", {
enumerable: true,
get: function() {
return renderMenuTrigger_unstable;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _menuTriggerContext = require("../../contexts/menuTriggerContext");
const renderMenuTrigger_unstable = (state)=>{
return /*#__PURE__*/ _react.createElement(_menuTriggerContext.MenuTriggerContextProvider, {
value: state.isSubmenu
}, state.children);
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/MenuTrigger/renderMenuTrigger.tsx"],"sourcesContent":["import * as React from 'react';\nimport { MenuTriggerContextProvider } from '../../contexts/menuTriggerContext';\nimport type { MenuTriggerState } from './MenuTrigger.types';\nimport type { JSXElement } from '@fluentui/react-utilities';\n\n/**\n * Render the final JSX of MenuTrigger\n *\n * Only renders children\n */\nexport const renderMenuTrigger_unstable = (state: MenuTriggerState): JSXElement => {\n return <MenuTriggerContextProvider value={state.isSubmenu}>{state.children}</MenuTriggerContextProvider>;\n};\n"],"names":["React","MenuTriggerContextProvider","renderMenuTrigger_unstable","state","value","isSubmenu","children"],"mappings":";;;;;;;;;;;iEAAuB,QAAQ;oCACY,oCAAoC;AASxE,MAAME,6BAA6B,CAACC;IACzC,OAAA,WAAA,GAAO,OAAA,aAAA,CAACF,8CAAAA,EAAAA;QAA2BG,OAAOD,MAAME,SAAS;OAAGF,MAAMG,QAAQ;AAC5E,EAAE"}

View File

@@ -0,0 +1,200 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useMenuTrigger_unstable", {
enumerable: true,
get: function() {
return useMenuTrigger_unstable;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _reactaria = require("@fluentui/react-aria");
const _keyboardkeys = require("@fluentui/keyboard-keys");
const _reactsharedcontexts = require("@fluentui/react-shared-contexts");
const _reacttabster = require("@fluentui/react-tabster");
const _reactutilities = require("@fluentui/react-utilities");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _menuContext = require("../../contexts/menuContext");
const _menuListContext = require("../../contexts/menuListContext");
const _utils = require("../../utils");
function noop() {
// does nothing
}
const useMenuTrigger_unstable = (props)=>{
const { children, disableButtonEnhancement = false } = props;
const triggerRef = (0, _menuContext.useMenuContext_unstable)((context)=>context.triggerRef);
const menuPopoverRef = (0, _menuContext.useMenuContext_unstable)((context)=>context.menuPopoverRef);
const setOpen = (0, _menuContext.useMenuContext_unstable)((context)=>context.setOpen);
const open = (0, _menuContext.useMenuContext_unstable)((context)=>context.open);
const triggerId = (0, _menuContext.useMenuContext_unstable)((context)=>context.triggerId);
const openOnHover = (0, _menuContext.useMenuContext_unstable)((context)=>context.openOnHover);
const openOnContext = (0, _menuContext.useMenuContext_unstable)((context)=>context.openOnContext);
const isSubmenu = (0, _utils.useIsSubmenu)();
const shouldOpenOnArrowRight = (0, _menuListContext.useMenuListContext_unstable)((ctx)=>{
var _ctx_shouldOpenOnArrowRight;
return (_ctx_shouldOpenOnArrowRight = ctx.shouldOpenOnArrowRight) !== null && _ctx_shouldOpenOnArrowRight !== void 0 ? _ctx_shouldOpenOnArrowRight : true;
});
const { findFirstFocusable } = (0, _reacttabster.useFocusFinders)();
const focusFirst = _react.useCallback(()=>{
const firstFocusable = findFirstFocusable(menuPopoverRef.current);
firstFocusable === null || firstFocusable === void 0 ? void 0 : firstFocusable.focus();
}, [
findFirstFocusable,
menuPopoverRef
]);
const openedWithKeyboardRef = _react.useRef(false);
const openedViaSafeZoneRef = _react.useRef(false);
const hasMouseMovedRef = _react.useRef(false);
const { dir } = (0, _reactsharedcontexts.useFluent_unstable)();
const OpenArrowKey = dir === 'ltr' ? _keyboardkeys.ArrowRight : _keyboardkeys.ArrowLeft;
const child = (0, _reactutilities.getTriggerChild)(children);
// Heads up!
//
// Handles an edge case where mouse movement over the menu trigger didn't happen as safe zone blocked pointer events,
// but the cursor is already over the menu trigger.
const safeZoneHandlerRef = (0, _utils.useOnMenuSafeZoneTimeout)((0, _reactutilities.useEventCallback)(()=>{
if (isSubmenu) {
openedViaSafeZoneRef.current = true;
}
}));
const onContextMenu = (event)=>{
if (isTargetDisabled(event) || event.isDefaultPrevented()) {
return;
}
if (openOnContext) {
event.preventDefault();
setOpen(event, {
open: true,
keyboard: false,
type: 'menuTriggerContextMenu',
event
});
}
};
const onClick = (event)=>{
if (isTargetDisabled(event)) {
return;
}
if (!openOnContext) {
setOpen(event, {
open: !open,
keyboard: openedWithKeyboardRef.current,
type: 'menuTriggerClick',
event
});
openedWithKeyboardRef.current = false;
}
};
const onKeyDown = (event)=>{
if (isTargetDisabled(event) || event.isDefaultPrevented()) {
return;
}
const key = event.key;
if (!openOnContext && (isSubmenu && shouldOpenOnArrowRight && key === OpenArrowKey || !isSubmenu && key === _keyboardkeys.ArrowDown)) {
setOpen(event, {
open: true,
keyboard: true,
type: 'menuTriggerKeyDown',
event
});
}
if (key === _keyboardkeys.Escape && !isSubmenu) {
setOpen(event, {
open: false,
keyboard: true,
type: 'menuTriggerKeyDown',
event
});
}
// if menu is already open, can't rely on effects to focus
if (open && key === OpenArrowKey && isSubmenu && shouldOpenOnArrowRight) {
focusFirst();
}
};
const onMouseOver = (event)=>{
if (isTargetDisabled(event)) {
return;
}
if (openOnHover) {
if (hasMouseMovedRef.current) {
setOpen(event, {
open: true,
keyboard: false,
type: 'menuTriggerMouseEnter',
event
});
} else if (openedViaSafeZoneRef.current) {
setOpen(event, {
open: true,
keyboard: false,
ignoreHoverDelay: true,
type: 'menuTriggerMouseEnter',
event
});
openedViaSafeZoneRef.current = false;
}
}
};
// Opening a menu when a mouse hasn't moved and just entering the trigger is a bad a11y experience
// First time open the mouse using mousemove and then continue with mouseenter
// Only use once to determine that the user is using the mouse since it is an expensive event to handle
const onMouseMove = (event)=>{
if (isTargetDisabled(event)) {
return;
}
if (openOnHover && !hasMouseMovedRef.current) {
setOpen(event, {
open: true,
keyboard: false,
type: 'menuTriggerMouseMove',
event
});
hasMouseMovedRef.current = true;
}
};
const onMouseLeave = (event)=>{
if (isTargetDisabled(event)) {
return;
}
if (openOnHover) {
setOpen(event, {
open: false,
keyboard: false,
type: 'menuTriggerMouseLeave',
event
});
}
};
var _child_props_onMouseEnter;
const contextMenuProps = {
id: triggerId,
...child === null || child === void 0 ? void 0 : child.props,
ref: (0, _reactutilities.useMergedRefs)(triggerRef, (0, _reactutilities.getReactElementRef)(child), safeZoneHandlerRef),
onMouseEnter: (0, _reactutilities.useEventCallback)((_child_props_onMouseEnter = child === null || child === void 0 ? void 0 : child.props.onMouseEnter) !== null && _child_props_onMouseEnter !== void 0 ? _child_props_onMouseEnter : noop),
onMouseLeave: (0, _reactutilities.useEventCallback)((0, _reactutilities.mergeCallbacks)(child === null || child === void 0 ? void 0 : child.props.onMouseLeave, onMouseLeave)),
onContextMenu: (0, _reactutilities.useEventCallback)((0, _reactutilities.mergeCallbacks)(child === null || child === void 0 ? void 0 : child.props.onContextMenu, onContextMenu)),
onMouseMove: (0, _reactutilities.useEventCallback)((0, _reactutilities.mergeCallbacks)(child === null || child === void 0 ? void 0 : child.props.onMouseMove, onMouseMove)),
onMouseOver: (0, _reactutilities.useEventCallback)((0, _reactutilities.mergeCallbacks)(child === null || child === void 0 ? void 0 : child.props.onMouseOver, onMouseOver))
};
const triggerChildProps = {
'aria-haspopup': 'menu',
'aria-expanded': !open && !isSubmenu ? undefined : open,
...contextMenuProps,
onClick: (0, _reactutilities.useEventCallback)((0, _reactutilities.mergeCallbacks)(child === null || child === void 0 ? void 0 : child.props.onClick, onClick)),
onKeyDown: (0, _reactutilities.useEventCallback)((0, _reactutilities.mergeCallbacks)(child === null || child === void 0 ? void 0 : child.props.onKeyDown, onKeyDown))
};
const ariaButtonTriggerChildProps = (0, _reactaria.useARIAButtonProps)((child === null || child === void 0 ? void 0 : child.type) === 'button' || (child === null || child === void 0 ? void 0 : child.type) === 'a' ? child.type : 'div', triggerChildProps);
return {
isSubmenu,
children: (0, _reactutilities.applyTriggerPropsToChildren)(children, openOnContext ? contextMenuProps : disableButtonEnhancement ? triggerChildProps : ariaButtonTriggerChildProps)
};
};
const isTargetDisabled = (event)=>{
const isDisabled = (el)=>el.hasAttribute('disabled') || el.hasAttribute('aria-disabled') && el.getAttribute('aria-disabled') === 'true';
if ((0, _reactutilities.isHTMLElement)(event.target) && isDisabled(event.target)) {
return true;
}
return (0, _reactutilities.isHTMLElement)(event.currentTarget) && isDisabled(event.currentTarget);
};

File diff suppressed because one or more lines are too long