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 { useSelect_unstable } from './useSelect';
import { renderSelect_unstable } from './renderSelect';
import { useSelectStyles_unstable } from './useSelectStyles.styles';
import { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';
/**
* Select component
*/ export const Select = /*#__PURE__*/ React.forwardRef((props, ref)=>{
const state = useSelect_unstable(props, ref);
useSelectStyles_unstable(state);
useCustomStyleHook_unstable('useSelectStyles_unstable')(state);
return renderSelect_unstable(state);
});
Select.displayName = 'Select';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/Select/Select.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useSelect_unstable } from './useSelect';\nimport { renderSelect_unstable } from './renderSelect';\nimport { useSelectStyles_unstable } from './useSelectStyles.styles';\nimport type { SelectProps } from './Select.types';\nimport type { ForwardRefComponent } from '@fluentui/react-utilities';\nimport { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';\n\n/**\n * Select component\n */\nexport const Select: ForwardRefComponent<SelectProps> = React.forwardRef((props, ref) => {\n const state = useSelect_unstable(props, ref);\n\n useSelectStyles_unstable(state);\n\n useCustomStyleHook_unstable('useSelectStyles_unstable')(state);\n\n return renderSelect_unstable(state);\n});\n\nSelect.displayName = 'Select';\n"],"names":["React","useSelect_unstable","renderSelect_unstable","useSelectStyles_unstable","useCustomStyleHook_unstable","Select","forwardRef","props","ref","state","displayName"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,kBAAkB,QAAQ,cAAc;AACjD,SAASC,qBAAqB,QAAQ,iBAAiB;AACvD,SAASC,wBAAwB,QAAQ,2BAA2B;AAGpE,SAASC,2BAA2B,QAAQ,kCAAkC;AAE9E;;CAEC,GACD,OAAO,MAAMC,uBAA2CL,MAAMM,UAAU,CAAC,CAACC,OAAOC;IAC/E,MAAMC,QAAQR,mBAAmBM,OAAOC;IAExCL,yBAAyBM;IAEzBL,4BAA4B,4BAA4BK;IAExD,OAAOP,sBAAsBO;AAC/B,GAAG;AAEHJ,OAAOK,WAAW,GAAG"}

View File

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

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/Select/Select.types.ts"],"sourcesContent":["import * as React from 'react';\nimport type { ComponentProps, ComponentState, DistributiveOmit, Slot } from '@fluentui/react-utilities';\n\nexport type SelectSlots = {\n /*\n * Wrapper for both the select and icon, renders as a `<span>`.\n * The `className` and `style` props on `<Select>` are applied to this slot;\n * All other top-level props are applied to the primary slot, `select`.\n */\n root: NonNullable<Slot<'span'>>;\n\n /** Primary slot: the actual `<select>` element */\n select: NonNullable<Slot<'select'>>;\n\n /** the icon, typically a down arrow */\n icon: Slot<'span'>;\n};\n\nexport type SelectProps = Omit<ComponentProps<Partial<SelectSlots>, 'select'>, 'size' | 'onChange'> & {\n /**\n * Controls the colors and borders of the Select.\n *\n * @default 'outline'\n */\n appearance?: 'outline' | 'underline' | 'filled-darker' | 'filled-lighter';\n\n /**\n * Called when the user changes the select element's value by selecting an option.\n */\n // eslint-disable-next-line @nx/workspace-consistent-callback-type -- can't change type of existing callback\n onChange?: (ev: React.ChangeEvent<HTMLSelectElement>, data: SelectOnChangeData) => void;\n\n /**\n * Matches the Input sizes\n *\n * @default 'medium'\n */\n size?: 'small' | 'medium' | 'large';\n};\n\nexport type SelectState = ComponentState<SelectSlots> & Required<Pick<SelectProps, 'appearance' | 'size'>>;\n\nexport type SelectBaseProps = DistributiveOmit<SelectProps, 'appearance' | 'size'>;\nexport type SelectBaseState = DistributiveOmit<SelectState, 'appearance' | 'size'>;\n\n/**\n * Data passed to the `onChange` callback when a new option is selected.\n */\nexport type SelectOnChangeData = {\n /**\n * Updated `<select>` value, taken from either the selected option's value prop or inner text.\n */\n value: string;\n};\n"],"names":["React"],"mappings":"AAAA,YAAYA,WAAW,QAAQ"}

View File

@@ -0,0 +1,4 @@
export { Select } from './Select';
export { renderSelect_unstable } from './renderSelect';
export { useSelectBase_unstable, useSelect_unstable } from './useSelect';
export { selectClassNames, useSelectStyles_unstable } from './useSelectStyles.styles';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/Select/index.ts"],"sourcesContent":["export { Select } from './Select';\nexport type {\n SelectBaseProps,\n SelectBaseState,\n SelectOnChangeData,\n SelectProps,\n SelectSlots,\n SelectState,\n} from './Select.types';\nexport { renderSelect_unstable } from './renderSelect';\nexport { useSelectBase_unstable, useSelect_unstable } from './useSelect';\nexport { selectClassNames, useSelectStyles_unstable } from './useSelectStyles.styles';\n"],"names":["Select","renderSelect_unstable","useSelectBase_unstable","useSelect_unstable","selectClassNames","useSelectStyles_unstable"],"mappings":"AAAA,SAASA,MAAM,QAAQ,WAAW;AASlC,SAASC,qBAAqB,QAAQ,iBAAiB;AACvD,SAASC,sBAAsB,EAAEC,kBAAkB,QAAQ,cAAc;AACzE,SAASC,gBAAgB,EAAEC,wBAAwB,QAAQ,2BAA2B"}

View File

@@ -0,0 +1,15 @@
import { jsx as _jsx, jsxs as _jsxs } from "@fluentui/react-jsx-runtime/jsx-runtime";
import { assertSlots } from '@fluentui/react-utilities';
/**
* Render the final JSX of Select
*/ export const renderSelect_unstable = (state)=>{
assertSlots(state);
return /*#__PURE__*/ _jsxs(state.root, {
children: [
/*#__PURE__*/ _jsx(state.select, {
children: state.select.children
}),
state.icon && /*#__PURE__*/ _jsx(state.icon, {})
]
});
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/Select/renderSelect.tsx"],"sourcesContent":["/** @jsxRuntime automatic */\n/** @jsxImportSource @fluentui/react-jsx-runtime */\n\nimport { assertSlots } from '@fluentui/react-utilities';\nimport type { JSXElement } from '@fluentui/react-utilities';\nimport type { SelectBaseState, SelectSlots } from './Select.types';\n\n/**\n * Render the final JSX of Select\n */\nexport const renderSelect_unstable = (state: SelectBaseState): JSXElement => {\n assertSlots<SelectSlots>(state);\n return (\n <state.root>\n <state.select>{state.select.children}</state.select>\n {state.icon && <state.icon />}\n </state.root>\n );\n};\n"],"names":["assertSlots","renderSelect_unstable","state","root","select","children","icon"],"mappings":"AAAA,0BAA0B,GAC1B,iDAAiD;AAEjD,SAASA,WAAW,QAAQ,4BAA4B;AAIxD;;CAEC,GACD,OAAO,MAAMC,wBAAwB,CAACC;IACpCF,YAAyBE;IACzB,qBACE,MAACA,MAAMC,IAAI;;0BACT,KAACD,MAAME,MAAM;0BAAEF,MAAME,MAAM,CAACC,QAAQ;;YACnCH,MAAMI,IAAI,kBAAI,KAACJ,MAAMI,IAAI;;;AAGhC,EAAE"}

View File

@@ -0,0 +1,83 @@
'use client';
import * as React from 'react';
import { useFieldControlProps_unstable } from '@fluentui/react-field';
import { getPartitionedNativeProps, useEventCallback, slot } from '@fluentui/react-utilities';
import { ChevronDownRegular } from '@fluentui/react-icons';
import { useOverrides_unstable as useOverrides } from '@fluentui/react-shared-contexts';
/**
* Create the state required to render Select.
*
* The returned state can be modified with hooks such as useSelectStyles,
* before being passed to renderSelect.
*
* @param props - props from this instance of Select
* @param ref - reference to the `<select>` element in Select
*/ export const useSelect_unstable = (props, ref)=>{
// Merge props from surrounding <Field>, if any
props = useFieldControlProps_unstable(props, {
supportsLabelFor: true,
supportsRequired: true,
supportsSize: true
});
const overrides = useOverrides();
var _overrides_inputDefaultAppearance;
const { appearance = (_overrides_inputDefaultAppearance = overrides.inputDefaultAppearance) !== null && _overrides_inputDefaultAppearance !== void 0 ? _overrides_inputDefaultAppearance : 'outline', size = 'medium', ...baseProps } = props;
const state = useSelectBase_unstable(baseProps, ref);
if (state.icon) {
var _state_icon;
var _children;
(_children = (_state_icon = state.icon).children) !== null && _children !== void 0 ? _children : _state_icon.children = /*#__PURE__*/ React.createElement(ChevronDownRegular, null);
}
return {
...state,
appearance,
size
};
};
/**
* Create the base state required to render Select without design-specific props.
*
* @param props - props from this instance of Select (without appearance/size)
* @param ref - reference to the `<select>` element in Select
*/ export const useSelectBase_unstable = (props, ref)=>{
const { defaultValue, value, select, icon, root, onChange } = props;
const nativeProps = getPartitionedNativeProps({
props,
primarySlotTagName: 'select',
excludedPropNames: [
'defaultValue',
'onChange',
'value'
]
});
const state = {
components: {
root: 'span',
select: 'select',
icon: 'span'
},
select: slot.always(select, {
defaultProps: {
defaultValue,
value,
ref,
...nativeProps.primary
},
elementType: 'select'
}),
icon: slot.optional(icon, {
renderByDefault: true,
elementType: 'span'
}),
root: slot.always(root, {
defaultProps: nativeProps.root,
elementType: 'span'
})
};
state.select.onChange = useEventCallback((event)=>{
onChange === null || onChange === void 0 ? void 0 : onChange(event, {
value: event.target.value
});
});
return state;
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/Select/useSelect.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useFieldControlProps_unstable } from '@fluentui/react-field';\nimport { getPartitionedNativeProps, useEventCallback, slot } from '@fluentui/react-utilities';\nimport { ChevronDownRegular } from '@fluentui/react-icons';\nimport type { SelectBaseProps, SelectBaseState, SelectProps, SelectState } from './Select.types';\nimport { useOverrides_unstable as useOverrides } from '@fluentui/react-shared-contexts';\n\n/**\n * Create the state required to render Select.\n *\n * The returned state can be modified with hooks such as useSelectStyles,\n * before being passed to renderSelect.\n *\n * @param props - props from this instance of Select\n * @param ref - reference to the `<select>` element in Select\n */\nexport const useSelect_unstable = (props: SelectProps, ref: React.Ref<HTMLSelectElement>): SelectState => {\n // Merge props from surrounding <Field>, if any\n props = useFieldControlProps_unstable(props, { supportsLabelFor: true, supportsRequired: true, supportsSize: true });\n\n const overrides = useOverrides();\n\n const { appearance = overrides.inputDefaultAppearance ?? 'outline', size = 'medium', ...baseProps } = props;\n\n const state = useSelectBase_unstable(baseProps, ref);\n\n if (state.icon) {\n state.icon.children ??= <ChevronDownRegular />;\n }\n\n return { ...state, appearance, size };\n};\n\n/**\n * Create the base state required to render Select without design-specific props.\n *\n * @param props - props from this instance of Select (without appearance/size)\n * @param ref - reference to the `<select>` element in Select\n */\nexport const useSelectBase_unstable = (props: SelectBaseProps, ref: React.Ref<HTMLSelectElement>): SelectBaseState => {\n const { defaultValue, value, select, icon, root, onChange } = props;\n\n const nativeProps = getPartitionedNativeProps({\n props,\n primarySlotTagName: 'select',\n excludedPropNames: ['defaultValue', 'onChange', 'value'],\n });\n\n const state: SelectBaseState = {\n components: {\n root: 'span',\n select: 'select',\n icon: 'span',\n },\n select: slot.always(select, {\n defaultProps: {\n defaultValue,\n value,\n ref,\n ...nativeProps.primary,\n },\n elementType: 'select',\n }),\n icon: slot.optional(icon, {\n renderByDefault: true,\n elementType: 'span',\n }),\n root: slot.always(root, {\n defaultProps: nativeProps.root,\n elementType: 'span',\n }),\n };\n\n state.select.onChange = useEventCallback(event => {\n onChange?.(event, { value: (event.target as HTMLSelectElement).value });\n });\n\n return state;\n};\n"],"names":["React","useFieldControlProps_unstable","getPartitionedNativeProps","useEventCallback","slot","ChevronDownRegular","useOverrides_unstable","useOverrides","useSelect_unstable","props","ref","supportsLabelFor","supportsRequired","supportsSize","overrides","appearance","inputDefaultAppearance","size","baseProps","state","useSelectBase_unstable","icon","children","defaultValue","value","select","root","onChange","nativeProps","primarySlotTagName","excludedPropNames","components","always","defaultProps","primary","elementType","optional","renderByDefault","event","target"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,6BAA6B,QAAQ,wBAAwB;AACtE,SAASC,yBAAyB,EAAEC,gBAAgB,EAAEC,IAAI,QAAQ,4BAA4B;AAC9F,SAASC,kBAAkB,QAAQ,wBAAwB;AAE3D,SAASC,yBAAyBC,YAAY,QAAQ,kCAAkC;AAExF;;;;;;;;CAQC,GACD,OAAO,MAAMC,qBAAqB,CAACC,OAAoBC;IACrD,+CAA+C;IAC/CD,QAAQR,8BAA8BQ,OAAO;QAAEE,kBAAkB;QAAMC,kBAAkB;QAAMC,cAAc;IAAK;IAElH,MAAMC,YAAYP;QAEGO;IAArB,MAAM,EAAEC,aAAaD,CAAAA,oCAAAA,UAAUE,sBAAsB,cAAhCF,+CAAAA,oCAAoC,SAAS,EAAEG,OAAO,QAAQ,EAAE,GAAGC,WAAW,GAAGT;IAEtG,MAAMU,QAAQC,uBAAuBF,WAAWR;IAEhD,IAAIS,MAAME,IAAI,EAAE;YACdF;;QAAAA,cAAAA,cAAAA,MAAME,IAAI,EAACC,yDAAXH,YAAWG,yBAAa,oBAACjB;IAC3B;IAEA,OAAO;QAAE,GAAGc,KAAK;QAAEJ;QAAYE;IAAK;AACtC,EAAE;AAEF;;;;;CAKC,GACD,OAAO,MAAMG,yBAAyB,CAACX,OAAwBC;IAC7D,MAAM,EAAEa,YAAY,EAAEC,KAAK,EAAEC,MAAM,EAAEJ,IAAI,EAAEK,IAAI,EAAEC,QAAQ,EAAE,GAAGlB;IAE9D,MAAMmB,cAAc1B,0BAA0B;QAC5CO;QACAoB,oBAAoB;QACpBC,mBAAmB;YAAC;YAAgB;YAAY;SAAQ;IAC1D;IAEA,MAAMX,QAAyB;QAC7BY,YAAY;YACVL,MAAM;YACND,QAAQ;YACRJ,MAAM;QACR;QACAI,QAAQrB,KAAK4B,MAAM,CAACP,QAAQ;YAC1BQ,cAAc;gBACZV;gBACAC;gBACAd;gBACA,GAAGkB,YAAYM,OAAO;YACxB;YACAC,aAAa;QACf;QACAd,MAAMjB,KAAKgC,QAAQ,CAACf,MAAM;YACxBgB,iBAAiB;YACjBF,aAAa;QACf;QACAT,MAAMtB,KAAK4B,MAAM,CAACN,MAAM;YACtBO,cAAcL,YAAYF,IAAI;YAC9BS,aAAa;QACf;IACF;IAEAhB,MAAMM,MAAM,CAACE,QAAQ,GAAGxB,iBAAiBmC,CAAAA;QACvCX,qBAAAA,+BAAAA,SAAWW,OAAO;YAAEd,OAAO,AAACc,MAAMC,MAAM,CAAuBf,KAAK;QAAC;IACvE;IAEA,OAAOL;AACT,EAAE"}

View File

@@ -0,0 +1,321 @@
'use client';
import { __styles, mergeClasses, shorthands } from '@griffel/react';
import { tokens, typographyStyles } from '@fluentui/react-theme';
export const selectClassNames = {
root: 'fui-Select',
select: 'fui-Select__select',
icon: 'fui-Select__icon'
};
const iconSizes = {
small: '16px',
medium: '20px',
large: '24px'
};
//TODO: Should fieldHeights be a set of global design tokens or constants?
const fieldHeights = {
small: '24px',
medium: '32px',
large: '40px'
};
/* Since the <select> element must span the full width and cannot have children,
* the right padding needs to be calculated from the sum of the following:
* 1. Field padding-right
* 2. Icon width
* 3. Content-icon spacing
* 4. Content inner padding
*/
const paddingRight = {
small: `calc(${tokens.spacingHorizontalSNudge}
+ ${iconSizes.small}
+ ${tokens.spacingHorizontalXXS}
+ ${tokens.spacingHorizontalXXS})`,
medium: `calc(${tokens.spacingHorizontalMNudge}
+ ${iconSizes.medium}
+ ${tokens.spacingHorizontalXXS}
+ ${tokens.spacingHorizontalXXS})`,
large: `calc(${tokens.spacingHorizontalM}
+ ${iconSizes.large}
+ ${tokens.spacingHorizontalSNudge}
+ ${tokens.spacingHorizontalSNudge})`
};
/* Left padding is calculated from the outer padding + inner content padding values
* since <select> can't have additional child content or custom inner layout */
const paddingLeft = {
small: `calc(${tokens.spacingHorizontalSNudge} + ${tokens.spacingHorizontalXXS})`,
medium: `calc(${tokens.spacingHorizontalMNudge} + ${tokens.spacingHorizontalXXS})`,
large: `calc(${tokens.spacingHorizontalM} + ${tokens.spacingHorizontalSNudge})`
};
/* end of shared values */
const useRootStyles = /*#__PURE__*/__styles({
base: {
Bt984gj: "f122n59",
B7ck84d: "f1ewtqcl",
mc9l5x: "f22iagw",
Eh141a: "flvyvdh",
Bahqtrf: "fk6fouc",
qhf8xq: "f10pi13n",
h62rwi: "f7ll8cq",
d9w3h3: 0,
B3778ie: 0,
B4j8arr: 0,
Bl18szs: 0,
Blrzh8d: "fe5s0lv",
li1rpt: "f1gw3sf2",
Bsft5z2: "f13zj6fq",
Dlnsje: "fhwjr99",
E3zdtr: "f1mdlcz9",
By385i5: "fo72kxq",
Eqx8gd: ["f1n6gb5g", "f15yvnhg"],
B1piin3: ["f15yvnhg", "f1n6gb5g"],
b1kco5: "f1yk9hq",
Ba2ppi3: "fhwpy7i",
F2fol1: "f14ee0xe",
lck23g: "f1xhbsuh",
wi16st: "fsrmcvb",
ywj3b2: "f1t3k7v9",
umuwi5: "fjw5xc1",
Blcqepd: "f1xdyd5c",
nplu4u: "fatpbeo",
Bioka5o: "fb7uyps",
Bnupc0a: "fx04xgm",
bing71: "f1c7in40"
}
}, {
d: [".f122n59{align-items:center;}", ".f1ewtqcl{box-sizing:border-box;}", ".f22iagw{display:flex;}", ".flvyvdh{flex-wrap:nowrap;}", ".fk6fouc{font-family:var(--fontFamilyBase);}", ".f10pi13n{position:relative;}", ".f7ll8cq::after{background-image:linear-gradient(\n 0deg,\n var(--colorCompoundBrandStroke) 0%,\n var(--colorCompoundBrandStroke) 50%,\n transparent 50%,\n transparent 100%\n );}", [".fe5s0lv::after{border-radius:0 0 var(--borderRadiusMedium) var(--borderRadiusMedium);}", {
p: -1
}], ".f1gw3sf2::after{box-sizing:border-box;}", ".f13zj6fq::after{content:\"\";}", ".fhwjr99::after{height:var(--borderRadiusMedium);}", ".f1mdlcz9::after{position:absolute;}", ".fo72kxq::after{bottom:0;}", ".f1n6gb5g::after{left:0;}", ".f15yvnhg::after{right:0;}", ".f1yk9hq::after{transform:scaleX(0);}", ".fhwpy7i::after{transition-property:transform;}", ".f14ee0xe::after{transition-duration:var(--durationUltraFast);}", ".f1xhbsuh::after{transition-delay:var(--curveAccelerateMid);}"],
m: [["@media screen and (prefers-reduced-motion: reduce){.fsrmcvb::after{transition-duration:0.01ms;}}", {
m: "screen and (prefers-reduced-motion: reduce)"
}], ["@media screen and (prefers-reduced-motion: reduce){.f1t3k7v9::after{transition-delay:0.01ms;}}", {
m: "screen and (prefers-reduced-motion: reduce)"
}], ["@media screen and (prefers-reduced-motion: reduce){.fx04xgm:focus-within::after{transition-duration:0.01ms;}}", {
m: "screen and (prefers-reduced-motion: reduce)"
}], ["@media screen and (prefers-reduced-motion: reduce){.f1c7in40:focus-within::after{transition-delay:0.01ms;}}", {
m: "screen and (prefers-reduced-motion: reduce)"
}]],
w: [".fjw5xc1:focus-within::after{transform:scaleX(1);}", ".f1xdyd5c:focus-within::after{transition-property:transform;}", ".fatpbeo:focus-within::after{transition-duration:var(--durationNormal);}", ".fb7uyps:focus-within::after{transition-delay:var(--curveDecelerateMid);}"]
});
const useSelectStyles = /*#__PURE__*/__styles({
base: {
Bowrso0: "fqrijq1",
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: "faev5xe",
Beyfa6y: 0,
Bbmb7ep: 0,
Btl43ni: 0,
B7oj6ja: 0,
Dimara: "ft85np5",
E5pizo: "f1couhl3",
B7ck84d: "f1ewtqcl",
sj55zd: "f19n0e5",
Bceei9c: "f1k6fduh",
Bh6795r: "fqerorx",
B2u0y6b: "f6dzj5z",
Byoj8tv: "f1qch9an",
z8tnut: "f1g0x7ka",
B3aqqti: "fatbyko",
Brovlpu: "f1grzc83",
Bxa1mx5: "f19shzzi"
},
disabled: {
De3pzq: "f1c21dwh",
g2u3we: "f1jj8ep1",
h3c5rm: ["f15xbau", "fy0fskl"],
B9xav0g: "f4ikngz",
zhjwy3: ["fy0fskl", "f15xbau"],
sj55zd: "f1s2aq7o",
Bceei9c: "fdrzuqr",
Bcq6wej: "f9dbb4x",
Jcjdmf: ["f3qs60o", "f5u9ap2"],
sc4o1m: "fwd1oij",
Bosien3: ["f5u9ap2", "f3qs60o"]
},
disabledUnderline: {
g2u3we: "fgig46g",
h3c5rm: ["f1mxt3zg", "fziff3p"],
B9xav0g: "f4ikngz",
zhjwy3: ["fziff3p", "f1mxt3zg"]
},
small: {
Bqenvij: "frvgh55",
uwmqm3: ["f1xile11", "fqznh8f"],
z189sj: ["fiqd4sw", "f11fkzut"],
Bahqtrf: "fk6fouc",
Be2twd7: "fy9rknc",
Bhrd7zp: "figsok6",
Bg96gwp: "fwrc4pm"
},
medium: {
Bqenvij: "f1d2rq10",
uwmqm3: ["f1e60jzv", "f135dnwl"],
z189sj: ["f154vowv", "flqamny"],
Bahqtrf: "fk6fouc",
Be2twd7: "fkhj508",
Bhrd7zp: "figsok6",
Bg96gwp: "f1i3iumi"
},
large: {
Bqenvij: "fbhnoac",
uwmqm3: ["fnphzt9", "flt1dlf"],
z189sj: ["f1xi5ia2", "f1xi1l47"],
Bahqtrf: "fk6fouc",
Be2twd7: "fod5ikn",
Bhrd7zp: "figsok6",
Bg96gwp: "faaz57k"
},
outline: {
De3pzq: "fxugw4r",
Bgfg5da: 0,
B9xav0g: "f1c1zstj",
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: "fm9niy"
},
outlineInteractive: {
Bgoe8wy: "fvcxoqz",
Bwzppfd: ["f1ub3y4t", "f1m52nbi"],
oetu4i: "flmw63s",
gg5e9n: ["f1m52nbi", "f1ub3y4t"],
B6oc9vd: "fvs00aa",
ak43y8: ["f1assf6x", "f4ruux4"],
wmxk5l: "fqhmt4z",
B50zh58: ["f4ruux4", "f1assf6x"]
},
underline: {
De3pzq: "f1c21dwh",
B9xav0g: 0,
oivjwe: 0,
Bn0qgzm: 0,
Bgfg5da: "fd91s9p",
Beyfa6y: 0,
Bbmb7ep: 0,
Btl43ni: 0,
B7oj6ja: 0,
Dimara: "fokr779",
C8i20h: "fb77jct"
},
"filled-lighter": {
De3pzq: "fxugw4r"
},
"filled-darker": {
De3pzq: "f16xq7d1"
},
invalid: {
tvckwq: "fs4k3qj",
gk2u95: ["fcee079", "fmyw78r"],
hhx65j: "f1fgmyf4",
Bxowmz0: ["fmyw78r", "fcee079"]
},
invalidUnderline: {
hhx65j: "f1fgmyf4"
}
}, {
d: [".fqrijq1{-webkit-appearance:none;-moz-appearance:none;appearance:none;}", [".faev5xe{border:1px solid transparent;}", {
p: -2
}], [".ft85np5{border-radius:var(--borderRadiusMedium);}", {
p: -1
}], ".f1couhl3{box-shadow:none;}", ".f1ewtqcl{box-sizing:border-box;}", ".f19n0e5{color:var(--colorNeutralForeground1);}", ".f1k6fduh{cursor:pointer;}", ".fqerorx{flex-grow:1;}", ".f6dzj5z{max-width:100%;}", ".f1qch9an{padding-bottom:0;}", ".f1g0x7ka{padding-top:0;}", ".f1c21dwh{background-color:var(--colorTransparentBackground);}", ".f1jj8ep1{border-top-color:var(--colorNeutralStrokeDisabled);}", ".f15xbau{border-right-color:var(--colorNeutralStrokeDisabled);}", ".fy0fskl{border-left-color:var(--colorNeutralStrokeDisabled);}", ".f4ikngz{border-bottom-color:var(--colorNeutralStrokeDisabled);}", ".f1s2aq7o{color:var(--colorNeutralForegroundDisabled);}", ".fdrzuqr{cursor:not-allowed;}", ".fgig46g{border-top-color:var(--colorTransparentStrokeDisabled);}", ".f1mxt3zg{border-right-color:var(--colorTransparentStrokeDisabled);}", ".fziff3p{border-left-color:var(--colorTransparentStrokeDisabled);}", ".frvgh55{height:24px;}", ".f1xile11{padding-left:calc(var(--spacingHorizontalSNudge) + var(--spacingHorizontalXXS));}", ".fqznh8f{padding-right:calc(var(--spacingHorizontalSNudge) + var(--spacingHorizontalXXS));}", ".fiqd4sw{padding-right:calc(var(--spacingHorizontalSNudge)\n + 16px\n + var(--spacingHorizontalXXS)\n + var(--spacingHorizontalXXS));}", ".f11fkzut{padding-left:calc(var(--spacingHorizontalSNudge)\n + 16px\n + var(--spacingHorizontalXXS)\n + var(--spacingHorizontalXXS));}", ".fk6fouc{font-family:var(--fontFamilyBase);}", ".fy9rknc{font-size:var(--fontSizeBase200);}", ".figsok6{font-weight:var(--fontWeightRegular);}", ".fwrc4pm{line-height:var(--lineHeightBase200);}", ".f1d2rq10{height:32px;}", ".f1e60jzv{padding-left:calc(var(--spacingHorizontalMNudge) + var(--spacingHorizontalXXS));}", ".f135dnwl{padding-right:calc(var(--spacingHorizontalMNudge) + var(--spacingHorizontalXXS));}", ".f154vowv{padding-right:calc(var(--spacingHorizontalMNudge)\n + 20px\n + var(--spacingHorizontalXXS)\n + var(--spacingHorizontalXXS));}", ".flqamny{padding-left:calc(var(--spacingHorizontalMNudge)\n + 20px\n + var(--spacingHorizontalXXS)\n + var(--spacingHorizontalXXS));}", ".fkhj508{font-size:var(--fontSizeBase300);}", ".f1i3iumi{line-height:var(--lineHeightBase300);}", ".fbhnoac{height:40px;}", ".fnphzt9{padding-left:calc(var(--spacingHorizontalM) + var(--spacingHorizontalSNudge));}", ".flt1dlf{padding-right:calc(var(--spacingHorizontalM) + var(--spacingHorizontalSNudge));}", ".f1xi5ia2{padding-right:calc(var(--spacingHorizontalM)\n + 24px\n + var(--spacingHorizontalSNudge)\n + var(--spacingHorizontalSNudge));}", ".f1xi1l47{padding-left:calc(var(--spacingHorizontalM)\n + 24px\n + var(--spacingHorizontalSNudge)\n + var(--spacingHorizontalSNudge));}", ".fod5ikn{font-size:var(--fontSizeBase400);}", ".faaz57k{line-height:var(--lineHeightBase400);}", ".fxugw4r{background-color:var(--colorNeutralBackground1);}", [".fm9niy{border:1px solid var(--colorNeutralStroke1);}", {
p: -2
}], ".f1c1zstj{border-bottom-color:var(--colorNeutralStrokeAccessible);}", [".fd91s9p{border-bottom:1px solid var(--colorNeutralStrokeAccessible);}", {
p: -1
}], [".fokr779{border-radius:0;}", {
p: -1
}], ".fb77jct option{background-color:var(--colorNeutralBackground1);}", ".f16xq7d1{background-color:var(--colorNeutralBackground3);}", ".fs4k3qj:not(:focus-within),.fs4k3qj:hover:not(:focus-within){border-top-color:var(--colorPaletteRedBorder2);}", ".fcee079:not(:focus-within),.fcee079:hover:not(:focus-within){border-right-color:var(--colorPaletteRedBorder2);}", ".fmyw78r:not(:focus-within),.fmyw78r:hover:not(:focus-within){border-left-color:var(--colorPaletteRedBorder2);}", ".f1fgmyf4:not(:focus-within),.f1fgmyf4:hover:not(:focus-within){border-bottom-color:var(--colorPaletteRedBorder2);}"],
f: [".fatbyko:focus{outline-width:2px;}", ".f1grzc83:focus{outline-style:solid;}", ".f19shzzi:focus{outline-color:transparent;}"],
m: [["@media (forced-colors: active){.f9dbb4x{border-top-color:GrayText;}}", {
m: "(forced-colors: active)"
}], ["@media (forced-colors: active){.f3qs60o{border-right-color:GrayText;}.f5u9ap2{border-left-color:GrayText;}}", {
m: "(forced-colors: active)"
}], ["@media (forced-colors: active){.fwd1oij{border-bottom-color:GrayText;}}", {
m: "(forced-colors: active)"
}]],
h: [".fvcxoqz:hover{border-top-color:var(--colorNeutralStroke1Hover);}", ".f1ub3y4t:hover{border-right-color:var(--colorNeutralStroke1Hover);}", ".f1m52nbi:hover{border-left-color:var(--colorNeutralStroke1Hover);}", ".flmw63s:hover{border-bottom-color:var(--colorNeutralStrokeAccessible);}"],
a: [".fvs00aa:active{border-top-color:var(--colorNeutralStroke1Pressed);}", ".f1assf6x:active{border-right-color:var(--colorNeutralStroke1Pressed);}", ".f4ruux4:active{border-left-color:var(--colorNeutralStroke1Pressed);}", ".fqhmt4z:active{border-bottom-color:var(--colorNeutralStrokeAccessible);}"]
});
const useIconStyles = /*#__PURE__*/__styles({
icon: {
B7ck84d: "f1ewtqcl",
sj55zd: "fxkbij4",
mc9l5x: "ftgm304",
qhf8xq: "f1euv43f",
Bkecrkj: "f1aehjj5",
Bo70h7d: "fvc9v3g"
},
disabled: {
sj55zd: "f1s2aq7o",
B7iucu3: "f1cyfu5x"
},
small: {
Be2twd7: "f4ybsrx",
Bqenvij: "fd461yt",
j35jbq: ["f13lnp83", "f1i5nn0v"],
a9b677: "fjw5fx7"
},
medium: {
Be2twd7: "fe5j1ua",
Bqenvij: "fjamq6b",
j35jbq: ["fnyteob", "f1enpzzf"],
a9b677: "f64fuq3"
},
large: {
Be2twd7: "f1rt2boy",
Bqenvij: "frvgh55",
j35jbq: ["f8b87gs", "fedtrts"],
a9b677: "fq4mcun"
}
}, {
d: [".f1ewtqcl{box-sizing:border-box;}", ".fxkbij4{color:var(--colorNeutralStrokeAccessible);}", ".ftgm304{display:block;}", ".f1euv43f{position:absolute;}", ".f1aehjj5{pointer-events:none;}", ".fvc9v3g svg{display:block;}", ".f1s2aq7o{color:var(--colorNeutralForegroundDisabled);}", ".f4ybsrx{font-size:16px;}", ".fd461yt{height:16px;}", ".f13lnp83{right:var(--spacingHorizontalSNudge);}", ".f1i5nn0v{left:var(--spacingHorizontalSNudge);}", ".fjw5fx7{width:16px;}", ".fe5j1ua{font-size:20px;}", ".fjamq6b{height:20px;}", ".fnyteob{right:var(--spacingHorizontalMNudge);}", ".f1enpzzf{left:var(--spacingHorizontalMNudge);}", ".f64fuq3{width:20px;}", ".f1rt2boy{font-size:24px;}", ".frvgh55{height:24px;}", ".f8b87gs{right:var(--spacingHorizontalM);}", ".fedtrts{left:var(--spacingHorizontalM);}", ".fq4mcun{width:24px;}"],
m: [["@media (forced-colors: active){.f1cyfu5x{color:GrayText;}}", {
m: "(forced-colors: active)"
}]]
});
/**
* Apply styling to the Select slots based on the state
*/
export const useSelectStyles_unstable = state => {
'use no memo';
const {
size,
appearance
} = state;
const disabled = state.select.disabled;
const invalid = `${state.select['aria-invalid']}` === 'true';
const iconStyles = useIconStyles();
const rootStyles = useRootStyles();
const selectStyles = useSelectStyles();
state.root.className = mergeClasses(selectClassNames.root, rootStyles.base, state.root.className);
state.select.className = mergeClasses(selectClassNames.select, selectStyles.base, selectStyles[size], selectStyles[appearance], !disabled && appearance === 'outline' && selectStyles.outlineInteractive, !disabled && invalid && appearance !== 'underline' && selectStyles.invalid, !disabled && invalid && appearance === 'underline' && selectStyles.invalidUnderline, disabled && selectStyles.disabled, disabled && appearance === 'underline' && selectStyles.disabledUnderline, state.select.className);
if (state.icon) {
state.icon.className = mergeClasses(selectClassNames.icon, iconStyles.icon, disabled && iconStyles.disabled, iconStyles[size], state.icon.className);
}
return state;
};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,235 @@
'use client';
import { makeStyles, mergeClasses, shorthands } from '@griffel/react';
import { tokens, typographyStyles } from '@fluentui/react-theme';
export const selectClassNames = {
root: 'fui-Select',
select: 'fui-Select__select',
icon: 'fui-Select__icon'
};
const iconSizes = {
small: '16px',
medium: '20px',
large: '24px'
};
//TODO: Should fieldHeights be a set of global design tokens or constants?
const fieldHeights = {
small: '24px',
medium: '32px',
large: '40px'
};
/* Since the <select> element must span the full width and cannot have children,
* the right padding needs to be calculated from the sum of the following:
* 1. Field padding-right
* 2. Icon width
* 3. Content-icon spacing
* 4. Content inner padding
*/ const paddingRight = {
small: `calc(${tokens.spacingHorizontalSNudge}
+ ${iconSizes.small}
+ ${tokens.spacingHorizontalXXS}
+ ${tokens.spacingHorizontalXXS})`,
medium: `calc(${tokens.spacingHorizontalMNudge}
+ ${iconSizes.medium}
+ ${tokens.spacingHorizontalXXS}
+ ${tokens.spacingHorizontalXXS})`,
large: `calc(${tokens.spacingHorizontalM}
+ ${iconSizes.large}
+ ${tokens.spacingHorizontalSNudge}
+ ${tokens.spacingHorizontalSNudge})`
};
/* Left padding is calculated from the outer padding + inner content padding values
* since <select> can't have additional child content or custom inner layout */ const paddingLeft = {
small: `calc(${tokens.spacingHorizontalSNudge} + ${tokens.spacingHorizontalXXS})`,
medium: `calc(${tokens.spacingHorizontalMNudge} + ${tokens.spacingHorizontalXXS})`,
large: `calc(${tokens.spacingHorizontalM} + ${tokens.spacingHorizontalSNudge})`
};
/* end of shared values */ const useRootStyles = makeStyles({
base: {
alignItems: 'center',
boxSizing: 'border-box',
display: 'flex',
flexWrap: 'nowrap',
fontFamily: tokens.fontFamilyBase,
position: 'relative',
'&::after': {
backgroundImage: `linear-gradient(
0deg,
${tokens.colorCompoundBrandStroke} 0%,
${tokens.colorCompoundBrandStroke} 50%,
transparent 50%,
transparent 100%
)`,
borderRadius: `0 0 ${tokens.borderRadiusMedium} ${tokens.borderRadiusMedium}`,
boxSizing: 'border-box',
content: '""',
height: tokens.borderRadiusMedium,
position: 'absolute',
bottom: '0',
left: '0',
right: '0',
transform: 'scaleX(0)',
transitionProperty: 'transform',
transitionDuration: tokens.durationUltraFast,
transitionDelay: tokens.curveAccelerateMid,
'@media screen and (prefers-reduced-motion: reduce)': {
transitionDuration: '0.01ms',
transitionDelay: '0.01ms'
}
},
'&:focus-within::after': {
transform: 'scaleX(1)',
transitionProperty: 'transform',
transitionDuration: tokens.durationNormal,
transitionDelay: tokens.curveDecelerateMid,
'@media screen and (prefers-reduced-motion: reduce)': {
transitionDuration: '0.01ms',
transitionDelay: '0.01ms'
}
}
}
});
const useSelectStyles = makeStyles({
base: {
appearance: 'none',
border: '1px solid transparent',
borderRadius: tokens.borderRadiusMedium,
boxShadow: 'none',
boxSizing: 'border-box',
color: tokens.colorNeutralForeground1,
cursor: 'pointer',
flexGrow: 1,
maxWidth: '100%',
paddingBottom: 0,
paddingTop: 0,
':focus': {
outlineWidth: '2px',
outlineStyle: 'solid',
outlineColor: 'transparent'
}
},
disabled: {
backgroundColor: tokens.colorTransparentBackground,
...shorthands.borderColor(tokens.colorNeutralStrokeDisabled),
color: tokens.colorNeutralForegroundDisabled,
cursor: 'not-allowed',
'@media (forced-colors: active)': {
...shorthands.borderColor('GrayText')
}
},
disabledUnderline: {
...shorthands.borderColor(tokens.colorTransparentStrokeDisabled, tokens.colorTransparentStrokeDisabled, tokens.colorNeutralStrokeDisabled)
},
small: {
height: fieldHeights.small,
paddingLeft: paddingLeft.small,
paddingRight: paddingRight.small,
...typographyStyles.caption1
},
medium: {
height: fieldHeights.medium,
paddingLeft: paddingLeft.medium,
paddingRight: paddingRight.medium,
...typographyStyles.body1
},
large: {
height: fieldHeights.large,
paddingLeft: paddingLeft.large,
paddingRight: paddingRight.large,
...typographyStyles.body2
},
outline: {
backgroundColor: tokens.colorNeutralBackground1,
border: `1px solid ${tokens.colorNeutralStroke1}`,
borderBottomColor: tokens.colorNeutralStrokeAccessible
},
outlineInteractive: {
'&:hover': {
...shorthands.borderColor(tokens.colorNeutralStroke1Hover),
borderBottomColor: tokens.colorNeutralStrokeAccessible
},
'&:active': {
...shorthands.borderColor(tokens.colorNeutralStroke1Pressed),
borderBottomColor: tokens.colorNeutralStrokeAccessible
}
},
underline: {
backgroundColor: tokens.colorTransparentBackground,
borderBottom: `1px solid ${tokens.colorNeutralStrokeAccessible}`,
borderRadius: '0',
'& option': {
// The transparent select bg means the option background must be set so the text is visible in dark themes
backgroundColor: tokens.colorNeutralBackground1
}
},
'filled-lighter': {
backgroundColor: tokens.colorNeutralBackground1
},
'filled-darker': {
backgroundColor: tokens.colorNeutralBackground3
},
invalid: {
':not(:focus-within),:hover:not(:focus-within)': {
...shorthands.borderColor(tokens.colorPaletteRedBorder2)
}
},
invalidUnderline: {
':not(:focus-within),:hover:not(:focus-within)': {
borderBottomColor: tokens.colorPaletteRedBorder2
}
}
});
const useIconStyles = makeStyles({
icon: {
boxSizing: 'border-box',
color: tokens.colorNeutralStrokeAccessible,
display: 'block',
position: 'absolute',
pointerEvents: 'none',
// the SVG must have display: block for accurate positioning
// otherwise an extra inline space is inserted after the svg element
'& svg': {
display: 'block'
}
},
disabled: {
color: tokens.colorNeutralForegroundDisabled,
'@media (forced-colors: active)': {
color: 'GrayText'
}
},
small: {
fontSize: iconSizes.small,
height: iconSizes.small,
right: tokens.spacingHorizontalSNudge,
width: iconSizes.small
},
medium: {
fontSize: iconSizes.medium,
height: iconSizes.medium,
right: tokens.spacingHorizontalMNudge,
width: iconSizes.medium
},
large: {
fontSize: iconSizes.large,
height: iconSizes.large,
right: tokens.spacingHorizontalM,
width: iconSizes.large
}
});
/**
* Apply styling to the Select slots based on the state
*/ export const useSelectStyles_unstable = (state)=>{
'use no memo';
const { size, appearance } = state;
const disabled = state.select.disabled;
const invalid = `${state.select['aria-invalid']}` === 'true';
const iconStyles = useIconStyles();
const rootStyles = useRootStyles();
const selectStyles = useSelectStyles();
state.root.className = mergeClasses(selectClassNames.root, rootStyles.base, state.root.className);
state.select.className = mergeClasses(selectClassNames.select, selectStyles.base, selectStyles[size], selectStyles[appearance], !disabled && appearance === 'outline' && selectStyles.outlineInteractive, !disabled && invalid && appearance !== 'underline' && selectStyles.invalid, !disabled && invalid && appearance === 'underline' && selectStyles.invalidUnderline, disabled && selectStyles.disabled, disabled && appearance === 'underline' && selectStyles.disabledUnderline, state.select.className);
if (state.icon) {
state.icon.className = mergeClasses(selectClassNames.icon, iconStyles.icon, disabled && iconStyles.disabled, iconStyles[size], state.icon.className);
}
return state;
};

File diff suppressed because one or more lines are too long