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,13 @@
'use client';
import * as React from 'react';
import { renderFluentProvider_unstable } from './renderFluentProvider';
import { useFluentProvider_unstable } from './useFluentProvider';
import { useFluentProviderStyles_unstable } from './useFluentProviderStyles.styles';
import { useFluentProviderContextValues_unstable } from './useFluentProviderContextValues';
export const FluentProvider = /*#__PURE__*/ React.forwardRef((props, ref)=>{
const state = useFluentProvider_unstable(props, ref);
useFluentProviderStyles_unstable(state);
const contextValues = useFluentProviderContextValues_unstable(state);
return renderFluentProvider_unstable(state, contextValues);
});
FluentProvider.displayName = 'FluentProvider';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/FluentProvider/FluentProvider.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\n\nimport type { ForwardRefComponent } from '@fluentui/react-utilities';\n\nimport { renderFluentProvider_unstable } from './renderFluentProvider';\nimport { useFluentProvider_unstable } from './useFluentProvider';\nimport { useFluentProviderStyles_unstable } from './useFluentProviderStyles.styles';\nimport { useFluentProviderContextValues_unstable } from './useFluentProviderContextValues';\nimport type { FluentProviderProps } from './FluentProvider.types';\n\nexport const FluentProvider: ForwardRefComponent<FluentProviderProps> = React.forwardRef((props, ref) => {\n const state = useFluentProvider_unstable(props, ref);\n useFluentProviderStyles_unstable(state);\n\n const contextValues = useFluentProviderContextValues_unstable(state);\n\n return renderFluentProvider_unstable(state, contextValues);\n});\n\nFluentProvider.displayName = 'FluentProvider';\n"],"names":["React","renderFluentProvider_unstable","useFluentProvider_unstable","useFluentProviderStyles_unstable","useFluentProviderContextValues_unstable","FluentProvider","forwardRef","props","ref","state","contextValues","displayName"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAI/B,SAASC,6BAA6B,QAAQ,yBAAyB;AACvE,SAASC,0BAA0B,QAAQ,sBAAsB;AACjE,SAASC,gCAAgC,QAAQ,mCAAmC;AACpF,SAASC,uCAAuC,QAAQ,mCAAmC;AAG3F,OAAO,MAAMC,+BAA2DL,MAAMM,UAAU,CAAC,CAACC,OAAOC;IAC/F,MAAMC,QAAQP,2BAA2BK,OAAOC;IAChDL,iCAAiCM;IAEjC,MAAMC,gBAAgBN,wCAAwCK;IAE9D,OAAOR,8BAA8BQ,OAAOC;AAC9C,GAAG;AAEHL,eAAeM,WAAW,GAAG"}

View File

@@ -0,0 +1,5 @@
/*
IconDirectionContextValue is being imported as a leaf node import in order to prevent extra icons froms being
downloaded when trying to use the FluentProvider.
This issue has more context: https://github.com/microsoft/fluentui/issues/30909
*/ export { };

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/FluentProvider/FluentProvider.types.ts"],"sourcesContent":["/*\n IconDirectionContextValue is being imported as a leaf node import in order to prevent extra icons froms being\n downloaded when trying to use the FluentProvider.\n This issue has more context: https://github.com/microsoft/fluentui/issues/30909\n*/\nimport type { IconDirectionContextValue } from '@fluentui/react-icons/lib/providers';\nimport type {\n OverridesContextValue_unstable as OverridesContextValue,\n ProviderContextValue_unstable as ProviderContextValue,\n TooltipVisibilityContextValue_unstable as TooltipVisibilityContextValue,\n ThemeClassNameContextValue_unstable as ThemeClassNameContextValue,\n ThemeContextValue_unstable as ThemeContextValue,\n CustomStyleHooksContextValue_unstable as CustomStyleHooksContextValue,\n} from '@fluentui/react-shared-contexts';\nimport type { PartialTheme } from '@fluentui/react-theme';\nimport type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities';\n\nexport type FluentProviderSlots = {\n root: Slot<'div'>;\n};\n\n// exported for callers to avoid referencing react-shared-context\n// and applying Partial<> when passing custom style hooks.\nexport type FluentProviderCustomStyleHooks = CustomStyleHooksContextValue;\n\nexport type FluentProviderProps = Omit<ComponentProps<FluentProviderSlots>, 'dir'> & {\n /**\n * Passes styles applied to a component down to portals if enabled.\n * @default true\n */\n applyStylesToPortals?: boolean;\n\n /** Sets the hooks for custom styling components. */\n // eslint-disable-next-line @typescript-eslint/naming-convention\n customStyleHooks_unstable?: FluentProviderCustomStyleHooks;\n\n /** Sets the direction of text & generated styles. */\n dir?: 'ltr' | 'rtl';\n\n /** Provides the document, can be undefined during SSR render. */\n targetDocument?: Document;\n\n /** Sets the theme used in a scope. */\n theme?: PartialTheme;\n\n // eslint-disable-next-line @typescript-eslint/naming-convention\n overrides_unstable?: OverridesContextValue;\n};\n\nexport type FluentProviderState = ComponentState<FluentProviderSlots> &\n Pick<FluentProviderProps, 'targetDocument'> &\n Required<\n Pick<FluentProviderProps, 'applyStylesToPortals' | 'customStyleHooks_unstable' | 'dir' | 'overrides_unstable'>\n > & {\n theme: ThemeContextValue;\n themeClassName: string;\n /**\n * Props used to render SSR theme variables style element\n */\n serverStyleProps: {\n /**\n * CSS rule containing CSS variables\n */\n cssRule: string;\n /**\n * Additional attributes applied to the style element\n */\n attributes: Record<string, string>;\n };\n };\n\nexport type FluentProviderContextValues = Pick<\n FluentProviderState,\n 'customStyleHooks_unstable' | 'theme' | 'overrides_unstable'\n> & {\n provider: ProviderContextValue;\n themeClassName: ThemeClassNameContextValue;\n textDirection: 'ltr' | 'rtl';\n iconDirection: IconDirectionContextValue;\n tooltip: TooltipVisibilityContextValue;\n};\n"],"names":[],"mappings":"AAAA;;;;AAIA,GAmEA,WASE"}

View File

@@ -0,0 +1,27 @@
const CSS_ESCAPE_MAP = {
'<': '\\3C ',
'>': '\\3E '
};
/**
* Escapes characters that could break out of a <style> tag during SSR.
*
* IMPORTANT: Do not strip quotes. Theme values legitimately include quoted font families and other CSS.
* We only need to ensure the generated text cannot terminate the style tag and inject HTML.
*/ function escapeForStyleTag(value) {
// Escape as CSS code points so the resulting CSS still represents the same characters.
// Using CSS escapes prevents the HTML parser from seeing a literal '<' / '>' and closing <style>.
return value.replace(/[<>]/g, (match)=>CSS_ESCAPE_MAP[match]);
}
/**
* Creates a CSS rule from a theme object.
*
* Useful for scenarios when you want to apply theming statically to a top level elements like `body`.
*/ export function createCSSRuleFromTheme(selector, theme) {
if (theme) {
const cssVarsAsString = Object.keys(theme).reduce((cssVarRule, cssVar)=>{
return `${cssVarRule}--${cssVar}: ${theme[cssVar]}; `;
}, '');
return `${selector} { ${escapeForStyleTag(cssVarsAsString)} }`;
}
return `${selector} {}`;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/FluentProvider/createCSSRuleFromTheme.ts"],"sourcesContent":["import type { PartialTheme } from '@fluentui/react-theme';\n\nconst CSS_ESCAPE_MAP = {\n '<': '\\\\3C ',\n '>': '\\\\3E ',\n};\n/**\n * Escapes characters that could break out of a <style> tag during SSR.\n *\n * IMPORTANT: Do not strip quotes. Theme values legitimately include quoted font families and other CSS.\n * We only need to ensure the generated text cannot terminate the style tag and inject HTML.\n */\nfunction escapeForStyleTag(value: string): string {\n // Escape as CSS code points so the resulting CSS still represents the same characters.\n // Using CSS escapes prevents the HTML parser from seeing a literal '<' / '>' and closing <style>.\n return value.replace(/[<>]/g, match => CSS_ESCAPE_MAP[match as keyof typeof CSS_ESCAPE_MAP]);\n}\n\n/**\n * Creates a CSS rule from a theme object.\n *\n * Useful for scenarios when you want to apply theming statically to a top level elements like `body`.\n */\nexport function createCSSRuleFromTheme(selector: string, theme: PartialTheme | undefined): string {\n if (theme) {\n const cssVarsAsString = (Object.keys(theme) as (keyof typeof theme)[]).reduce((cssVarRule, cssVar) => {\n return `${cssVarRule}--${cssVar}: ${theme[cssVar]}; `;\n }, '');\n\n return `${selector} { ${escapeForStyleTag(cssVarsAsString)} }`;\n }\n\n return `${selector} {}`;\n}\n"],"names":["CSS_ESCAPE_MAP","escapeForStyleTag","value","replace","match","createCSSRuleFromTheme","selector","theme","cssVarsAsString","Object","keys","reduce","cssVarRule","cssVar"],"mappings":"AAEA,MAAMA,iBAAiB;IACrB,KAAK;IACL,KAAK;AACP;AACA;;;;;CAKC,GACD,SAASC,kBAAkBC,KAAa;IACtC,uFAAuF;IACvF,kGAAkG;IAClG,OAAOA,MAAMC,OAAO,CAAC,SAASC,CAAAA,QAASJ,cAAc,CAACI,MAAqC;AAC7F;AAEA;;;;CAIC,GACD,OAAO,SAASC,uBAAuBC,QAAgB,EAAEC,KAA+B;IACtF,IAAIA,OAAO;QACT,MAAMC,kBAAkB,AAACC,OAAOC,IAAI,CAACH,OAAkCI,MAAM,CAAC,CAACC,YAAYC;YACzF,OAAO,GAAGD,WAAW,EAAE,EAAEC,OAAO,EAAE,EAAEN,KAAK,CAACM,OAAO,CAAC,EAAE,CAAC;QACvD,GAAG;QAEH,OAAO,GAAGP,SAAS,GAAG,EAAEL,kBAAkBO,iBAAiB,EAAE,CAAC;IAChE;IAEA,OAAO,GAAGF,SAAS,GAAG,CAAC;AACzB"}

View File

@@ -0,0 +1,7 @@
export { createCSSRuleFromTheme } from './createCSSRuleFromTheme';
export { FluentProvider } from './FluentProvider';
export { renderFluentProvider_unstable } from './renderFluentProvider';
export { useFluentProvider_unstable } from './useFluentProvider';
export { fluentProviderClassNames, useFluentProviderStyles_unstable } from './useFluentProviderStyles.styles';
export { useFluentProviderContextValues_unstable } from './useFluentProviderContextValues';
export { useFluentProviderThemeStyleTag } from './useFluentProviderThemeStyleTag';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/FluentProvider/index.ts"],"sourcesContent":["export { createCSSRuleFromTheme } from './createCSSRuleFromTheme';\nexport { FluentProvider } from './FluentProvider';\nexport type {\n FluentProviderContextValues,\n FluentProviderCustomStyleHooks,\n FluentProviderProps,\n FluentProviderSlots,\n FluentProviderState,\n} from './FluentProvider.types';\nexport { renderFluentProvider_unstable } from './renderFluentProvider';\nexport { useFluentProvider_unstable } from './useFluentProvider';\nexport { fluentProviderClassNames, useFluentProviderStyles_unstable } from './useFluentProviderStyles.styles';\nexport { useFluentProviderContextValues_unstable } from './useFluentProviderContextValues';\nexport { useFluentProviderThemeStyleTag } from './useFluentProviderThemeStyleTag';\n"],"names":["createCSSRuleFromTheme","FluentProvider","renderFluentProvider_unstable","useFluentProvider_unstable","fluentProviderClassNames","useFluentProviderStyles_unstable","useFluentProviderContextValues_unstable","useFluentProviderThemeStyleTag"],"mappings":"AAAA,SAASA,sBAAsB,QAAQ,2BAA2B;AAClE,SAASC,cAAc,QAAQ,mBAAmB;AAQlD,SAASC,6BAA6B,QAAQ,yBAAyB;AACvE,SAASC,0BAA0B,QAAQ,sBAAsB;AACjE,SAASC,wBAAwB,EAAEC,gCAAgC,QAAQ,mCAAmC;AAC9G,SAASC,uCAAuC,QAAQ,mCAAmC;AAC3F,SAASC,8BAA8B,QAAQ,mCAAmC"}

View File

@@ -0,0 +1,52 @@
'use client';
import { jsx as _jsx, jsxs as _jsxs } from "@fluentui/react-jsx-runtime/jsx-runtime";
import { canUseDOM, assertSlots } from '@fluentui/react-utilities';
import { TextDirectionProvider } from '@griffel/react';
import { OverridesProvider_unstable as OverridesProvider, Provider_unstable as Provider, TooltipVisibilityProvider_unstable as TooltipVisibilityProvider, ThemeProvider_unstable as ThemeProvider, ThemeClassNameProvider_unstable as ThemeClassNameProvider, CustomStyleHooksProvider_unstable as CustomStyleHooksProvider } from '@fluentui/react-shared-contexts';
import { IconDirectionContextProvider } from '@fluentui/react-icons/lib/providers';
/**
* Render the final JSX of FluentProvider
*/ export const renderFluentProvider_unstable = (state, contextValues)=>{
assertSlots(state);
// Typescript (vscode) incorrectly references the FluentProviderProps.customStyleHooks_unstable
// instead of FluentProviderContextValues.customStyleHooks_unstable and thinks it is
// Partial<CustomStyleHooksContextValue>, so it needs to be cast to Required<CustomStyleHooksContextValue>
return /*#__PURE__*/ _jsx(Provider, {
value: contextValues.provider,
children: /*#__PURE__*/ _jsx(ThemeProvider, {
value: contextValues.theme,
children: /*#__PURE__*/ _jsx(ThemeClassNameProvider, {
value: contextValues.themeClassName,
children: /*#__PURE__*/ _jsx(CustomStyleHooksProvider, {
value: contextValues.customStyleHooks_unstable,
children: /*#__PURE__*/ _jsx(TooltipVisibilityProvider, {
value: contextValues.tooltip,
children: /*#__PURE__*/ _jsx(TextDirectionProvider, {
dir: contextValues.textDirection,
children: /*#__PURE__*/ _jsx(IconDirectionContextProvider, {
value: contextValues.iconDirection,
children: /*#__PURE__*/ _jsx(OverridesProvider, {
value: contextValues.overrides_unstable,
children: /*#__PURE__*/ _jsxs(state.root, {
children: [
canUseDOM() ? null : /*#__PURE__*/ _jsx("style", {
// Using dangerous HTML because react can escape characters
// which can lead to invalid CSS.
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML: {
__html: state.serverStyleProps.cssRule
},
...state.serverStyleProps.attributes
}),
state.root.children
]
})
})
})
})
})
})
})
})
});
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/FluentProvider/renderFluentProvider.tsx"],"sourcesContent":["/** @jsxRuntime automatic */\n/** @jsxImportSource @fluentui/react-jsx-runtime */\n\n'use client';\n\nimport { canUseDOM, assertSlots } from '@fluentui/react-utilities';\nimport type { JSXElement } from '@fluentui/react-utilities';\nimport { TextDirectionProvider } from '@griffel/react';\nimport {\n OverridesProvider_unstable as OverridesProvider,\n Provider_unstable as Provider,\n TooltipVisibilityProvider_unstable as TooltipVisibilityProvider,\n ThemeProvider_unstable as ThemeProvider,\n ThemeClassNameProvider_unstable as ThemeClassNameProvider,\n CustomStyleHooksProvider_unstable as CustomStyleHooksProvider,\n CustomStyleHooksContextValue_unstable as CustomStyleHooksContextValue,\n} from '@fluentui/react-shared-contexts';\nimport type { FluentProviderContextValues, FluentProviderState, FluentProviderSlots } from './FluentProvider.types';\nimport { IconDirectionContextProvider } from '@fluentui/react-icons/lib/providers';\n\n/**\n * Render the final JSX of FluentProvider\n */\nexport const renderFluentProvider_unstable = (\n state: FluentProviderState,\n contextValues: FluentProviderContextValues,\n): JSXElement => {\n assertSlots<FluentProviderSlots>(state);\n\n // Typescript (vscode) incorrectly references the FluentProviderProps.customStyleHooks_unstable\n // instead of FluentProviderContextValues.customStyleHooks_unstable and thinks it is\n // Partial<CustomStyleHooksContextValue>, so it needs to be cast to Required<CustomStyleHooksContextValue>\n\n return (\n <Provider value={contextValues.provider}>\n <ThemeProvider value={contextValues.theme}>\n <ThemeClassNameProvider value={contextValues.themeClassName}>\n <CustomStyleHooksProvider\n value={contextValues.customStyleHooks_unstable as Required<CustomStyleHooksContextValue>}\n >\n <TooltipVisibilityProvider value={contextValues.tooltip}>\n <TextDirectionProvider dir={contextValues.textDirection}>\n <IconDirectionContextProvider value={contextValues.iconDirection}>\n <OverridesProvider value={contextValues.overrides_unstable}>\n <state.root>\n {canUseDOM() ? null : (\n <style\n // Using dangerous HTML because react can escape characters\n // which can lead to invalid CSS.\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{ __html: state.serverStyleProps.cssRule }}\n {...state.serverStyleProps.attributes}\n />\n )}\n\n {state.root.children}\n </state.root>\n </OverridesProvider>\n </IconDirectionContextProvider>\n </TextDirectionProvider>\n </TooltipVisibilityProvider>\n </CustomStyleHooksProvider>\n </ThemeClassNameProvider>\n </ThemeProvider>\n </Provider>\n );\n};\n"],"names":["canUseDOM","assertSlots","TextDirectionProvider","OverridesProvider_unstable","OverridesProvider","Provider_unstable","Provider","TooltipVisibilityProvider_unstable","TooltipVisibilityProvider","ThemeProvider_unstable","ThemeProvider","ThemeClassNameProvider_unstable","ThemeClassNameProvider","CustomStyleHooksProvider_unstable","CustomStyleHooksProvider","IconDirectionContextProvider","renderFluentProvider_unstable","state","contextValues","value","provider","theme","themeClassName","customStyleHooks_unstable","tooltip","dir","textDirection","iconDirection","overrides_unstable","root","style","dangerouslySetInnerHTML","__html","serverStyleProps","cssRule","attributes","children"],"mappings":"AAAA,0BAA0B,GAC1B,iDAAiD,GAEjD;;AAEA,SAASA,SAAS,EAAEC,WAAW,QAAQ,4BAA4B;AAEnE,SAASC,qBAAqB,QAAQ,iBAAiB;AACvD,SACEC,8BAA8BC,iBAAiB,EAC/CC,qBAAqBC,QAAQ,EAC7BC,sCAAsCC,yBAAyB,EAC/DC,0BAA0BC,aAAa,EACvCC,mCAAmCC,sBAAsB,EACzDC,qCAAqCC,wBAAwB,QAExD,kCAAkC;AAEzC,SAASC,4BAA4B,QAAQ,sCAAsC;AAEnF;;CAEC,GACD,OAAO,MAAMC,gCAAgC,CAC3CC,OACAC;IAEAjB,YAAiCgB;IAEjC,+FAA+F;IAC/F,oFAAoF;IACpF,0GAA0G;IAE1G,qBACE,KAACX;QAASa,OAAOD,cAAcE,QAAQ;kBACrC,cAAA,KAACV;YAAcS,OAAOD,cAAcG,KAAK;sBACvC,cAAA,KAACT;gBAAuBO,OAAOD,cAAcI,cAAc;0BACzD,cAAA,KAACR;oBACCK,OAAOD,cAAcK,yBAAyB;8BAE9C,cAAA,KAACf;wBAA0BW,OAAOD,cAAcM,OAAO;kCACrD,cAAA,KAACtB;4BAAsBuB,KAAKP,cAAcQ,aAAa;sCACrD,cAAA,KAACX;gCAA6BI,OAAOD,cAAcS,aAAa;0CAC9D,cAAA,KAACvB;oCAAkBe,OAAOD,cAAcU,kBAAkB;8CACxD,cAAA,MAACX,MAAMY,IAAI;;4CACR7B,cAAc,qBACb,KAAC8B;gDACC,2DAA2D;gDAC3D,iCAAiC;gDACjC,2CAA2C;gDAC3CC,yBAAyB;oDAAEC,QAAQf,MAAMgB,gBAAgB,CAACC,OAAO;gDAAC;gDACjE,GAAGjB,MAAMgB,gBAAgB,CAACE,UAAU;;4CAIxClB,MAAMY,IAAI,CAACO,QAAQ;;;;;;;;;;;AAW1C,EAAE"}

View File

@@ -0,0 +1,103 @@
'use client';
import { useRenderer_unstable } from '@griffel/react';
import { useFocusVisible } from '@fluentui/react-tabster';
import { ThemeContext_unstable as ThemeContext, useFluent_unstable as useFluent, useOverrides_unstable as useOverrides, CustomStyleHooksContext_unstable as CustomStyleHooksContext } from '@fluentui/react-shared-contexts';
import { getIntrinsicElementProps, useMergedRefs, slot } from '@fluentui/react-utilities';
import * as React from 'react';
import { useFluentProviderThemeStyleTag } from './useFluentProviderThemeStyleTag';
// Meomizing empty objects to avoid unnecessary rerenders.
const DEFAULT_STYLE_HOOKS = {};
const DEFAULT_RENDERER_ATTRIBUTES = {};
/**
* Create the state required to render FluentProvider.
*
* The returned state can be modified with hooks such as useFluentProviderStyles_unstable,
* before being passed to renderFluentProvider_unstable.
*
* @param props - props from this instance of FluentProvider
* @param ref - reference to root HTMLElement of FluentProvider
*/ export const useFluentProvider_unstable = (props, ref)=>{
'use no memo';
const parentContext = useFluent();
const parentTheme = useTheme();
const parentOverrides = useOverrides();
const parentCustomStyleHooks = React.useContext(CustomStyleHooksContext) || DEFAULT_STYLE_HOOKS;
/**
* TODO: add merge functions to "dir" merge,
* nesting providers with the same "dir" should not add additional attributes to DOM
* see https://github.com/microsoft/fluentui/blob/0dc74a19f3aa5a058224c20505016fbdb84db172/packages/fluentui/react-northstar/src/utils/mergeProviderContexts.ts#L89-L93
*/ const { applyStylesToPortals = true, // eslint-disable-next-line @typescript-eslint/naming-convention
customStyleHooks_unstable, dir = parentContext.dir, targetDocument = parentContext.targetDocument, theme, overrides_unstable: overrides = {} } = props;
const mergedTheme = shallowMerge(parentTheme, theme);
const mergedOverrides = shallowMerge(parentOverrides, overrides);
const mergedCustomStyleHooks = shallowMerge(parentCustomStyleHooks, customStyleHooks_unstable);
const renderer = useRenderer_unstable();
var _renderer_styleElementAttributes;
const { styleTagId, rule } = useFluentProviderThemeStyleTag({
theme: mergedTheme,
targetDocument,
rendererAttributes: (_renderer_styleElementAttributes = renderer.styleElementAttributes) !== null && _renderer_styleElementAttributes !== void 0 ? _renderer_styleElementAttributes : DEFAULT_RENDERER_ATTRIBUTES
});
if (process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line react-hooks/rules-of-hooks
React.useEffect(()=>{
if (mergedTheme === undefined) {
// eslint-disable-next-line no-console
console.warn([
'@fluentui/react-provider: FluentProvider does not have your "theme" defined.',
"Make sure that your top-level FluentProvider has set a `theme` prop or you're setting the theme in your child FluentProvider."
].join(' '));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}
return {
applyStylesToPortals,
// eslint-disable-next-line @typescript-eslint/naming-convention
customStyleHooks_unstable: mergedCustomStyleHooks,
dir,
targetDocument,
theme: mergedTheme,
// eslint-disable-next-line @typescript-eslint/naming-convention
overrides_unstable: mergedOverrides,
themeClassName: styleTagId,
components: {
root: 'div'
},
root: slot.always(getIntrinsicElementProps('div', {
...props,
dir,
// 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, useFocusVisible({
targetDocument
}))
}), {
elementType: 'div'
}),
serverStyleProps: {
cssRule: rule,
attributes: {
...renderer.styleElementAttributes,
id: styleTagId
}
}
};
};
function shallowMerge(a, b) {
// Merge impacts perf: we should like to avoid it if it's possible
if (a && b) {
return {
...a,
...b
};
}
if (a) {
return a;
}
return b;
}
function useTheme() {
return React.useContext(ThemeContext);
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
'use client';
import * as React from 'react';
export function useFluentProviderContextValues_unstable(state) {
const { applyStylesToPortals, // eslint-disable-next-line @typescript-eslint/naming-convention
customStyleHooks_unstable, dir, root, targetDocument, theme, themeClassName, // eslint-disable-next-line @typescript-eslint/naming-convention
overrides_unstable } = state;
const provider = React.useMemo(()=>({
dir,
targetDocument
}), [
dir,
targetDocument
]);
// "Tooltip" component mutates an object in this context, instance should be stable
const [tooltip] = React.useState(()=>({}));
const iconDirection = React.useMemo(()=>({
textDirection: dir
}), [
dir
]);
return {
// eslint-disable-next-line @typescript-eslint/naming-convention
customStyleHooks_unstable,
// eslint-disable-next-line @typescript-eslint/naming-convention
overrides_unstable,
provider,
textDirection: dir,
iconDirection,
tooltip,
theme,
themeClassName: applyStylesToPortals ? root.className : themeClassName
};
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/FluentProvider/useFluentProviderContextValues.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport type { FluentProviderContextValues, FluentProviderState } from './FluentProvider.types';\n\nexport function useFluentProviderContextValues_unstable(state: FluentProviderState): FluentProviderContextValues {\n const {\n applyStylesToPortals,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n customStyleHooks_unstable,\n dir,\n root,\n targetDocument,\n theme,\n themeClassName,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n overrides_unstable,\n } = state;\n\n const provider = React.useMemo(() => ({ dir, targetDocument }), [dir, targetDocument]);\n // \"Tooltip\" component mutates an object in this context, instance should be stable\n const [tooltip] = React.useState(() => ({}));\n const iconDirection = React.useMemo(() => ({ textDirection: dir }), [dir]);\n\n return {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n customStyleHooks_unstable,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n overrides_unstable,\n provider,\n textDirection: dir,\n iconDirection,\n tooltip,\n theme,\n themeClassName: applyStylesToPortals ? root.className! : themeClassName,\n };\n}\n"],"names":["React","useFluentProviderContextValues_unstable","state","applyStylesToPortals","customStyleHooks_unstable","dir","root","targetDocument","theme","themeClassName","overrides_unstable","provider","useMemo","tooltip","useState","iconDirection","textDirection","className"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAG/B,OAAO,SAASC,wCAAwCC,KAA0B;IAChF,MAAM,EACJC,oBAAoB,EACpB,gEAAgE;IAChEC,yBAAyB,EACzBC,GAAG,EACHC,IAAI,EACJC,cAAc,EACdC,KAAK,EACLC,cAAc,EACd,gEAAgE;IAChEC,kBAAkB,EACnB,GAAGR;IAEJ,MAAMS,WAAWX,MAAMY,OAAO,CAAC,IAAO,CAAA;YAAEP;YAAKE;QAAe,CAAA,GAAI;QAACF;QAAKE;KAAe;IACrF,mFAAmF;IACnF,MAAM,CAACM,QAAQ,GAAGb,MAAMc,QAAQ,CAAC,IAAO,CAAA,CAAC,CAAA;IACzC,MAAMC,gBAAgBf,MAAMY,OAAO,CAAC,IAAO,CAAA;YAAEI,eAAeX;QAAI,CAAA,GAAI;QAACA;KAAI;IAEzE,OAAO;QACL,gEAAgE;QAChED;QACA,gEAAgE;QAChEM;QACAC;QACAK,eAAeX;QACfU;QACAF;QACAL;QACAC,gBAAgBN,uBAAuBG,KAAKW,SAAS,GAAIR;IAC3D;AACF"}

View File

@@ -0,0 +1,33 @@
'use client';
import { __styles, mergeClasses } from '@griffel/core';
import { useRenderer_unstable } from '@griffel/react';
import { tokens, typographyStyles } from '@fluentui/react-theme';
export const fluentProviderClassNames = {
root: 'fui-FluentProvider'
};
const useStyles = /*#__PURE__*/__styles({
root: {
sj55zd: "f19n0e5",
De3pzq: "fxugw4r",
fsow6f: ["f1o700av", "fes3tcz"],
Bahqtrf: "fk6fouc",
Be2twd7: "fkhj508",
Bhrd7zp: "figsok6",
Bg96gwp: "f1i3iumi"
}
}, {
d: [".f19n0e5{color:var(--colorNeutralForeground1);}", ".fxugw4r{background-color:var(--colorNeutralBackground1);}", ".f1o700av{text-align:left;}", ".fes3tcz{text-align:right;}", ".fk6fouc{font-family:var(--fontFamilyBase);}", ".fkhj508{font-size:var(--fontSizeBase300);}", ".figsok6{font-weight:var(--fontWeightRegular);}", ".f1i3iumi{line-height:var(--lineHeightBase300);}"]
});
/** Applies style classnames to slots */
export const useFluentProviderStyles_unstable = state => {
'use no memo';
const renderer = useRenderer_unstable();
const styles = useStyles({
dir: state.dir,
renderer
});
state.root.className = mergeClasses(fluentProviderClassNames.root, state.themeClassName, styles.root, state.root.className);
return state;
};

View File

@@ -0,0 +1 @@
{"version":3,"names":["__styles","mergeClasses","useRenderer_unstable","tokens","typographyStyles","fluentProviderClassNames","root","useStyles","sj55zd","De3pzq","fsow6f","Bahqtrf","Be2twd7","Bhrd7zp","Bg96gwp","d","useFluentProviderStyles_unstable","state","renderer","styles","dir","className","themeClassName"],"sources":["useFluentProviderStyles.styles.js"],"sourcesContent":["'use client';\nimport { makeStyles, mergeClasses } from '@griffel/core';\nimport { useRenderer_unstable } from '@griffel/react';\nimport { tokens, typographyStyles } from '@fluentui/react-theme';\nexport const fluentProviderClassNames = {\n root: 'fui-FluentProvider'\n};\nconst useStyles = makeStyles({\n root: {\n color: tokens.colorNeutralForeground1,\n backgroundColor: tokens.colorNeutralBackground1,\n textAlign: 'left',\n ...typographyStyles.body1\n }\n});\n/** Applies style classnames to slots */ export const useFluentProviderStyles_unstable = (state)=>{\n 'use no memo';\n const renderer = useRenderer_unstable();\n const styles = useStyles({\n dir: state.dir,\n renderer\n });\n state.root.className = mergeClasses(fluentProviderClassNames.root, state.themeClassName, styles.root, state.root.className);\n return state;\n};\n"],"mappings":"AAAA,YAAY;;AACZ,SAAAA,QAAA,EAAqBC,YAAY,QAAQ,eAAe;AACxD,SAASC,oBAAoB,QAAQ,gBAAgB;AACrD,SAASC,MAAM,EAAEC,gBAAgB,QAAQ,uBAAuB;AAChE,OAAO,MAAMC,wBAAwB,GAAG;EACpCC,IAAI,EAAE;AACV,CAAC;AACD,MAAMC,SAAS,gBAAGP,QAAA;EAAAM,IAAA;IAAAE,MAAA;IAAAC,MAAA;IAAAC,MAAA;IAAAC,OAAA;IAAAC,OAAA;IAAAC,OAAA;IAAAC,OAAA;EAAA;AAAA;EAAAC,CAAA;AAAA,CAOjB,CAAC;AACF;AAAyC,OAAO,MAAMC,gCAAgC,GAAIC,KAAK,IAAG;EAC9F,aAAa;;EACb,MAAMC,QAAQ,GAAGhB,oBAAoB,CAAC,CAAC;EACvC,MAAMiB,MAAM,GAAGZ,SAAS,CAAC;IACrBa,GAAG,EAAEH,KAAK,CAACG,GAAG;IACdF;EACJ,CAAC,CAAC;EACFD,KAAK,CAACX,IAAI,CAACe,SAAS,GAAGpB,YAAY,CAACI,wBAAwB,CAACC,IAAI,EAAEW,KAAK,CAACK,cAAc,EAAEH,MAAM,CAACb,IAAI,EAAEW,KAAK,CAACX,IAAI,CAACe,SAAS,CAAC;EAC3H,OAAOJ,KAAK;AAChB,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,25 @@
'use client';
import { makeStyles, mergeClasses } from '@griffel/core';
import { useRenderer_unstable } from '@griffel/react';
import { tokens, typographyStyles } from '@fluentui/react-theme';
export const fluentProviderClassNames = {
root: 'fui-FluentProvider'
};
const useStyles = makeStyles({
root: {
color: tokens.colorNeutralForeground1,
backgroundColor: tokens.colorNeutralBackground1,
textAlign: 'left',
...typographyStyles.body1
}
});
/** Applies style classnames to slots */ export const useFluentProviderStyles_unstable = (state)=>{
'use no memo';
const renderer = useRenderer_unstable();
const styles = useStyles({
dir: state.dir,
renderer
});
state.root.className = mergeClasses(fluentProviderClassNames.root, state.themeClassName, styles.root, state.root.className);
return state;
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/FluentProvider/useFluentProviderStyles.styles.ts"],"sourcesContent":["'use client';\n\nimport { makeStyles, mergeClasses } from '@griffel/core';\nimport { useRenderer_unstable } from '@griffel/react';\nimport { tokens, typographyStyles } from '@fluentui/react-theme';\nimport type { FluentProviderSlots, FluentProviderState } from './FluentProvider.types';\nimport { SlotClassNames } from '@fluentui/react-utilities';\n\nexport const fluentProviderClassNames: SlotClassNames<FluentProviderSlots> = {\n root: 'fui-FluentProvider',\n};\n\nconst useStyles = makeStyles({\n root: {\n color: tokens.colorNeutralForeground1,\n backgroundColor: tokens.colorNeutralBackground1,\n textAlign: 'left',\n ...typographyStyles.body1,\n },\n});\n\n/** Applies style classnames to slots */\nexport const useFluentProviderStyles_unstable = (state: FluentProviderState): FluentProviderState => {\n 'use no memo';\n\n const renderer = useRenderer_unstable();\n const styles = useStyles({ dir: state.dir, renderer });\n\n state.root.className = mergeClasses(\n fluentProviderClassNames.root,\n state.themeClassName,\n styles.root,\n state.root.className,\n );\n\n return state;\n};\n"],"names":["makeStyles","mergeClasses","useRenderer_unstable","tokens","typographyStyles","fluentProviderClassNames","root","useStyles","color","colorNeutralForeground1","backgroundColor","colorNeutralBackground1","textAlign","body1","useFluentProviderStyles_unstable","state","renderer","styles","dir","className","themeClassName"],"mappings":"AAAA;AAEA,SAASA,UAAU,EAAEC,YAAY,QAAQ,gBAAgB;AACzD,SAASC,oBAAoB,QAAQ,iBAAiB;AACtD,SAASC,MAAM,EAAEC,gBAAgB,QAAQ,wBAAwB;AAIjE,OAAO,MAAMC,2BAAgE;IAC3EC,MAAM;AACR,EAAE;AAEF,MAAMC,YAAYP,WAAW;IAC3BM,MAAM;QACJE,OAAOL,OAAOM,uBAAuB;QACrCC,iBAAiBP,OAAOQ,uBAAuB;QAC/CC,WAAW;QACX,GAAGR,iBAAiBS,KAAK;IAC3B;AACF;AAEA,sCAAsC,GACtC,OAAO,MAAMC,mCAAmC,CAACC;IAC/C;IAEA,MAAMC,WAAWd;IACjB,MAAMe,SAASV,UAAU;QAAEW,KAAKH,MAAMG,GAAG;QAAEF;IAAS;IAEpDD,MAAMT,IAAI,CAACa,SAAS,GAAGlB,aACrBI,yBAAyBC,IAAI,EAC7BS,MAAMK,cAAc,EACpBH,OAAOX,IAAI,EACXS,MAAMT,IAAI,CAACa,SAAS;IAGtB,OAAOJ;AACT,EAAE"}

View File

@@ -0,0 +1,136 @@
'use client';
import { useId, useIsomorphicLayoutEffect } from '@fluentui/react-utilities';
import * as React from 'react';
import { createCSSRuleFromTheme } from './createCSSRuleFromTheme';
import { fluentProviderClassNames } from './useFluentProviderStyles.styles';
// String concatenation is used to prevent bundlers to complain with older versions of React
const useInsertionEffect = React['useInsertion' + 'Effect'] ? React['useInsertion' + 'Effect'] : useIsomorphicLayoutEffect;
const createStyleTag = (target, elementAttributes)=>{
// Document might exist but not be ready yet (e.g. during SSR)
// In that case, we should not create a style tag
if (!(target === null || target === void 0 ? void 0 : target.head)) {
return undefined;
}
const tag = target.createElement('style');
Object.keys(elementAttributes).forEach((attrName)=>{
tag.setAttribute(attrName, elementAttributes[attrName]);
});
target.head.appendChild(tag);
return tag;
};
const insertSheet = (tag, rule)=>{
const sheet = tag.sheet;
if (sheet) {
if (sheet.cssRules.length > 0) {
sheet.deleteRule(0);
}
sheet.insertRule(rule, 0);
} else if (process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line no-console
console.error('FluentProvider: No sheet available on styleTag, styles will not be inserted into DOM.');
}
};
/**
* Writes a theme as css variables in a style tag on the provided targetDocument as a rule applied to a CSS class
* @internal
* @returns CSS class to apply the rule
*/ export const useFluentProviderThemeStyleTag = (options)=>{
'use no memo';
const { targetDocument, theme, rendererAttributes } = options;
const styleTag = React.useRef(undefined);
const styleTagId = useId(fluentProviderClassNames.root);
const styleElementAttributes = rendererAttributes;
const rule = React.useMemo(()=>createCSSRuleFromTheme(`.${styleTagId}`, theme), [
theme,
styleTagId
]);
if (process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line react-hooks/rules-of-hooks
React.useMemo(()=>{
// Heads up!
// .useMemo() is used because it is called during render and DOM for _current_ component is not mounted yet. Also,
// this allows to do checks with strict mode enabled as .useEffect() will be called with incremented IDs because
// of double render.
if (targetDocument) {
var _styleElement_textContent;
const providerElementSelector = `.${fluentProviderClassNames.root}.${styleTagId}`;
const providerElements = targetDocument.querySelectorAll(providerElementSelector);
const styleElementSelector = `style[id="${styleTagId}"]`;
const styleElements = targetDocument.querySelectorAll(styleElementSelector);
if (styleElements.length > 1) {
// eslint-disable-next-line no-console
console.error([
'@fluentui/react-provider: We found multiple <style> elements with same IDs in your DOM.',
'Please make sure that you configured your application properly.',
'\n',
'\n',
'Configuration guide: https://aka.ms/fluentui-conflicting-ids'
].join(' '));
return;
}
const styleElement = styleElements.item(0);
var _styleElement_textContent_length;
// Heads up!
//
// In SSR, we will have DOM upfront & style tags will have CSS rules defined in `.textContent`
const isSSR = ((_styleElement_textContent_length = styleElement === null || styleElement === void 0 ? void 0 : (_styleElement_textContent = styleElement.textContent) === null || _styleElement_textContent === void 0 ? void 0 : _styleElement_textContent.length) !== null && _styleElement_textContent_length !== void 0 ? _styleElement_textContent_length : 0) > 0;
const elementsCount = isSSR ? 1 : 0;
if (providerElements.length > elementsCount) {
// eslint-disable-next-line no-console
console.error([
'@fluentui/react-provider: There are conflicting ids in your DOM.',
'Please make sure that you configured your application properly.',
'\n',
'\n',
'Configuration guide: https://aka.ms/fluentui-conflicting-ids'
].join(' '));
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}
useHandleSSRStyleElements(targetDocument, styleTagId);
useInsertionEffect(()=>{
// The style element could already have been created during SSR - no need to recreate it
const ssrStyleElement = targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.getElementById(styleTagId);
if (ssrStyleElement) {
styleTag.current = ssrStyleElement;
} else {
styleTag.current = createStyleTag(targetDocument, {
...styleElementAttributes,
id: styleTagId
});
if (styleTag.current) {
insertSheet(styleTag.current, rule);
}
}
return ()=>{
var _styleTag_current;
(_styleTag_current = styleTag.current) === null || _styleTag_current === void 0 ? void 0 : _styleTag_current.remove();
};
}, [
styleTagId,
targetDocument,
rule,
styleElementAttributes
]);
return {
styleTagId,
rule
};
};
function useHandleSSRStyleElements(targetDocument, styleTagId) {
// Using a state factory so that this logic only runs once per render
// Each FluentProvider can create its own style element during SSR as a slot
// Moves all theme style elements to document head during render to avoid hydration errors.
// Should be strict mode safe since the logic is idempotent.
React.useState(()=>{
if (!targetDocument) {
return;
}
const themeStyleElement = targetDocument.getElementById(styleTagId);
if (themeStyleElement) {
targetDocument.head.append(themeStyleElement);
}
});
}

File diff suppressed because one or more lines are too long