Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.

Commit 0521e5a

Browse files
committed
feat: add compose
1 parent a4d68f5 commit 0521e5a

File tree

81 files changed

+1907
-832
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+1907
-832
lines changed

build/gulp/tasks/docs.ts

+11
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,17 @@ const componentsSrc = [
6060
`${paths.posix.packageSrc('react')}/components/*/[A-Z]*.tsx`,
6161
`${paths.posix.packageSrc('react-bindings')}/FocusZone/[A-Z]!(*.types).tsx`,
6262
`${paths.posix.packageSrc('react-component-ref')}/[A-Z]*.tsx`,
63+
'!**/ButtonIcon.tsx',
64+
'!**/StatusIcon.tsx',
65+
'!**/ButtonContent.tsx',
66+
'!**/ButtonContent.tsx',
67+
'!**/AvatarLabel.tsx',
68+
'!**/AvatarImage.tsx',
69+
'!**/AvatarStatus.tsx',
70+
'!**/SliderInput.tsx',
71+
'!**/CheckboxLabel.tsx',
72+
'!**/CheckboxIcon.tsx',
73+
'!**/CheckboxToggleIcon.tsx',
6374
]
6475
const behaviorSrc = [`${paths.posix.packageSrc('accessibility')}/behaviors/*/[a-z]*Behavior.ts`]
6576
const examplesIndexSrc = `${paths.posix.docsSrc()}/examples/*/*/*/index.tsx`

docs/src/components/ComponentPlayground/componentGenerators.ts

+22
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ import { useSelectKnob, useStringKnob } from '@fluentui/docs-components'
22
import {
33
AvatarProps,
44
BoxProps,
5+
ButtonProps,
56
DialogProps,
67
DividerProps,
78
EmbedProps,
89
IconProps,
910
ImageProps,
11+
SliderProps,
12+
StatusProps,
1013
VideoProps,
1114
} from '@fluentui/react'
1215
import * as _ from 'lodash'
@@ -21,13 +24,22 @@ export const Avatar: KnobComponentGenerators<AvatarProps> = {
2124
name: propName,
2225
initialValue: _.capitalize(`${faker.name.firstName()} ${faker.name.lastName()}`),
2326
}),
27+
// TODO: fix support for composed components
28+
image: () => null,
29+
label: () => null,
30+
status: () => null,
2431
}
2532

2633
export const Box: KnobComponentGenerators<BoxProps> = {
2734
// TODO: fix support for boxes
2835
children: () => null,
2936
}
3037

38+
export const Button: KnobComponentGenerators<ButtonProps> = {
39+
// TODO: fix support for composed components
40+
icon: () => null,
41+
}
42+
3143
export const Dialog: KnobComponentGenerators<DialogProps> = {
3244
footer: () => null,
3345
}
@@ -79,6 +91,16 @@ export const Image: KnobComponentGenerators<ImageProps> = {
7991
}),
8092
}
8193

94+
export const Slider: KnobComponentGenerators<SliderProps> = {
95+
// TODO: fix support for composed components
96+
input: () => null,
97+
}
98+
99+
export const Status: KnobComponentGenerators<StatusProps> = {
100+
// TODO: fix support for composed components
101+
icon: () => null,
102+
}
103+
82104
export const Video: KnobComponentGenerators<VideoProps> = {
83105
poster: ({ componentInfo, propName }) => ({
84106
hook: useStringKnob,

docs/src/components/ComponentPlayground/propGenerators.tsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ export const color: KnobGenerator<string> = ({ propName, propDef, componentInfo,
2525

2626
export const size: KnobGenerator<string> = ({ propName, propDef, componentInfo }) => {
2727
if (propDef.types.length > 1 || propDef.types[0].name !== 'SizeValue') {
28-
throw new Error(
29-
`A "${componentInfo.displayName}" for "size" prop defines type different than "SizeValue" it is not supported`,
30-
)
28+
return null
29+
// throw new Error(
30+
// `A "${componentInfo.displayName}" for "size" prop defines type different than "SizeValue" it is not supported`,
31+
// )
3132
}
3233

3334
return {
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import * as React from 'react'
22
import { Slider } from '@fluentui/react'
33

4-
const SliderExampleShorthand = () => <Slider />
4+
const SliderExampleShorthand = () => (
5+
<>
6+
<Slider />
7+
<Slider />
8+
</>
9+
)
510

611
export default SliderExampleShorthand

packages/accessibility/src/behaviors/Checkbox/checkboxBehavior.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ const checkboxBehavior: Accessibility<CheckboxBehaviorProps> = props => ({
3131

3232
export default checkboxBehavior
3333

34-
type CheckboxBehaviorProps = {
34+
export type CheckboxBehaviorProps = {
3535
/** Whether or not item is checked. */
36-
checked: boolean
36+
checked?: boolean
3737
/** If the checkbox is in disabled state. */
3838
disabled?: boolean
3939
}

packages/accessibility/src/behaviors/Icon/iconBehavior.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ const iconBehavior: Accessibility<IconBehaviorProps> = props => ({
2020

2121
export default iconBehavior
2222

23-
type IconBehaviorProps = {
23+
export type IconBehaviorProps = {
2424
/** Alternative text. */
2525
alt?: string
26-
'aria-label'?: string
2726
} & Pick<AccessibilityAttributes, 'aria-label'>

packages/accessibility/src/behaviors/Slider/sliderBehavior.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ const sliderBehavior: Accessibility<SliderBehaviorProps> = props => ({
2626

2727
export default sliderBehavior
2828

29-
type SliderBehaviorProps = {
29+
export type SliderBehaviorProps = {
3030
disabled?: boolean
31+
// TODO: fix these SupportedIntrinsicInputProps['min']
3132
min?: number
3233
max?: number
3334
value?: number

packages/accessibility/src/behaviors/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export { default as selectableListItemBehavior } from './List/selectableListItem
2020
export { default as loaderBehavior } from './Loader/loaderBehavior'
2121
export { default as inputBehavior } from './Input/inputBehavior'
2222
export { default as iconBehavior } from './Icon/iconBehavior'
23+
export * from './Icon/iconBehavior'
2324
export { default as tabBehavior } from './Tab/tabBehavior'
2425
export { default as tabListBehavior } from './Tab/tabListBehavior'
2526
export { default as menuAsToolbarBehavior } from './Toolbar/menuAsToolbarBehavior'
@@ -51,9 +52,11 @@ export { default as accordionBehavior } from './Accordion/accordionBehavior'
5152
export { default as accordionTitleBehavior } from './Accordion/accordionTitleBehavior'
5253
export { default as accordionContentBehavior } from './Accordion/accordionContentBehavior'
5354
export { default as checkboxBehavior } from './Checkbox/checkboxBehavior'
55+
export * from './Checkbox/checkboxBehavior'
5456
export { default as tooltipAsDescriptionBehavior } from './Tooltip/tooltipAsDescriptionBehavior'
5557
export { default as tooltipAsLabelBehavior } from './Tooltip/tooltipAsLabelBehavior'
5658
export { default as sliderBehavior } from './Slider/sliderBehavior'
59+
export * from './Slider/sliderBehavior'
5760
export { default as menuButtonBehavior } from './MenuButton/menuButtonBehavior'
5861
export { default as splitButtonBehavior } from './SplitButton/splitButtonBehavior'
5962
export { default as treeBehavior } from './Tree/treeBehavior'
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import * as React from 'react'
2+
3+
type ComposeOptions = {
4+
// TODO: better typings PLZ
5+
className?: string
6+
displayName: string
7+
mapPropsToBehavior?: Function
8+
mapPropsToStyles?: Function
9+
handledProps?: string[]
10+
overrideStyles?: boolean
11+
}
12+
13+
const COMPOSE_CONFIG_PROP_NAME = '__unstable_config'
14+
15+
export type ComposableProps = { [COMPOSE_CONFIG_PROP_NAME]?: ComposeOptions }
16+
17+
export const compose = <UserProps, CProps = {}>(
18+
Component: React.ComponentType<CProps>,
19+
options: ComposeOptions,
20+
): React.ComponentType<CProps & UserProps> => {
21+
const ComposedComponent = Component.bind(null)
22+
23+
ComposedComponent.displayName = options.displayName
24+
25+
// We are passing config via props by setting default prop value
26+
ComposedComponent.defaultProps = { ...(Component.defaultProps || {}) }
27+
// @ts-ignore TODO PLS FIX ME
28+
ComposedComponent.defaultProps[COMPOSE_CONFIG_PROP_NAME] = options
29+
30+
return ComposedComponent as any
31+
}
32+
33+
export const useComposedConfig = <P extends ComposableProps>(props: P) => {
34+
const { [COMPOSE_CONFIG_PROP_NAME]: options } = props
35+
36+
const {
37+
className = '',
38+
displayName,
39+
handledProps = [],
40+
mapPropsToBehavior = () => ({}),
41+
mapPropsToStyles = () => ({}),
42+
overrideStyles = false,
43+
} = options || {}
44+
45+
return {
46+
behaviorProps: mapPropsToBehavior(props),
47+
styleProps: mapPropsToStyles(props),
48+
className,
49+
displayName,
50+
handledProps: handledProps.concat(['__unstable_config']),
51+
overrideStyles,
52+
}
53+
}

packages/react-bindings/src/hooks/useStyles.ts

+18-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {
22
ComponentSlotStyle,
3-
ComponentSlotStylesPrepared,
3+
ComponentSlotStylesResolved,
44
ComponentVariablesInput,
55
DebugData,
66
emptyTheme,
@@ -10,6 +10,7 @@ import * as React from 'react'
1010
import { ThemeContext } from 'react-fela'
1111

1212
import {
13+
ComponentAnimationProp,
1314
ComponentDesignProp,
1415
ComponentSlotClasses,
1516
RendererRenderRule,
@@ -23,14 +24,19 @@ type UseStylesOptions<StyleProps extends PrimitiveProps> = {
2324
mapPropsToStyles?: () => StyleProps
2425
mapPropsToInlineStyles?: () => InlineStyleProps<StyleProps>
2526
rtl?: boolean
27+
28+
__experimental_composeName?: string
29+
__experimental_overrideStyles?: boolean
2630
}
2731

2832
type UseStylesResult = {
2933
classes: ComponentSlotClasses
30-
styles: ComponentSlotStylesPrepared
34+
styles: ComponentSlotStylesResolved
3135
}
3236

3337
type InlineStyleProps<StyleProps> = {
38+
unstable_animation?: ComponentAnimationProp
39+
3440
/** Additional CSS class name(s) to apply. */
3541
className?: string
3642

@@ -62,17 +68,22 @@ const useStyles = <StyleProps extends PrimitiveProps>(
6268
mapPropsToStyles = () => ({} as StyleProps),
6369
mapPropsToInlineStyles = () => ({} as InlineStyleProps<StyleProps>),
6470
rtl = false,
71+
__experimental_composeName,
72+
__experimental_overrideStyles,
6573
} = options
6674

6775
// Stores debug information for component.
6876
const debug = React.useRef<{ fluentUIDebug: DebugData | null }>({ fluentUIDebug: null })
77+
const inlineProps = mapPropsToInlineStyles()
78+
6979
const { classes, styles: resolvedStyles } = getStyles({
7080
// Input values
7181
className,
7282
displayName,
7383
props: {
7484
...mapPropsToStyles(),
75-
...mapPropsToInlineStyles(),
85+
...inlineProps,
86+
animation: inlineProps.unstable_animation,
7687
},
7788

7889
// Context values
@@ -82,6 +93,10 @@ const useStyles = <StyleProps extends PrimitiveProps>(
8293
saveDebug: fluentUIDebug => (debug.current = { fluentUIDebug }),
8394
theme: context.theme,
8495
_internal_resolvedComponentVariables: context._internal_resolvedComponentVariables,
96+
97+
__experimental_cache: true,
98+
__experimental_composeName,
99+
__experimental_overrideStyles,
85100
})
86101

87102
return { classes, styles: resolvedStyles }

packages/react-bindings/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,5 @@ export * from './telemetry/types'
2323

2424
export { default as getElementType } from './utils/getElementType'
2525
export { default as getUnhandledProps } from './utils/getUnhandledProps'
26+
27+
export * from './compose'

0 commit comments

Comments
 (0)