-
Notifications
You must be signed in to change notification settings - Fork 104
feat(Form): initial Implementation #242
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 35 commits
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
ea20fa1
feat(polyfills): Add Safari Polyfill
MarcusNotheis 3aa4f73
Merge branch 'master' into chore/safari-polyfill
MarcusNotheis 3ab5b79
analytical table columns drag'n'drop implementation
andybessm 3df54a5
merged
andybessm ee57618
Merge commit '3aa4f731cefd0c0e757fe8f2c325d5e81b062fec' into feat/ana…
andybessm d7af885
unit test added
andybessm 9f3e5d4
delete unneccessary files
andybessm da3a172
make dnd marker disappeared when drop occurs out of a target column; …
andybessm 7d03370
Merge branch 'master' of ssh://github.com/SAP/ui5-webcomponents-react…
andybessm f9b3726
Merge branch 'master' into feat/analytical-table-dnd
vbersch c8809fe
onColumnsReordered Event added; hook renamed to correct name
andybessm 73c3716
remove incorrectly named hook file
andybessm e57e690
Merge branch 'master' into feat/analytical-table-dnd
vbersch 253a963
refactor(AnalyticalTable): update react-table and replace grid layout…
MarcusNotheis e462376
WIP: Update tests
MarcusNotheis 2965c2d
WIP: Update react-table and add resize handler
MarcusNotheis 7fbf85e
Update tests
MarcusNotheis 17daa55
Update AnalyticalTable.test.tsx
MarcusNotheis 4fecbdc
initial create
andybessm 7205b0d
more tests and touch of style
andybessm 9e6ee24
restyling
andybessm 9f65904
Merge branch 'master' into refactor/AnalyticalTable
vbersch a5b2df8
Merge branch 'master' of ssh://github.com/SAP/ui5-webcomponents-react…
andybessm 789ef64
Merge commit '9f659048c527fdab126f8cb8681bd142ae4d4854' into feat/for…
andybessm d56dfc8
performance optimization; styling
andybessm a217398
test snapshot updated
andybessm 0134fc8
use hook for initialization; restyling
andybessm 6219f3e
recreate the component according to the review results
andybessm 2b9c794
recreate test snapshots
andybessm 39100f1
Merge commit '00239135eea104d4f4cf7695d0050041b6248bdd' into feat/for…
andybessm 028e298
Merge branch 'master' into feat/form-component
MarcusNotheis 726ce06
Merge branch 'master' into feat/form-component
vbersch 04079ed
WIP: Change import path of device
MarcusNotheis 99329a1
fixes according to the review
andybessm 7c0d8b6
fixes according to the code review
andybessm 5ca0b25
fixes according to the code review
andybessm 211ac8f
Merge branch 'master' into feat/form-component
andybessm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { useCallback, useEffect, useState } from 'react'; | ||
import { Device } from '@ui5/webcomponents-react-base/lib/Device'; | ||
|
||
export const useViewportRange = (rangeSet) => { | ||
const [currentRange, setCurrentRange] = useState(Device.media.getCurrentRange(rangeSet, window.innerWidth).name); | ||
|
||
const onWindowResize = useCallback( | ||
({ name: range }) => { | ||
setCurrentRange(range); | ||
}, | ||
[currentRange, setCurrentRange] | ||
); | ||
|
||
useEffect(() => { | ||
Device.media.attachHandler(onWindowResize, null, 'StdExt'); | ||
return () => Device.resize.detachHandler(onWindowResize, null); | ||
}, [onWindowResize]); | ||
|
||
return currentRange; | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { useViewportRange } from '../hooks/useViewportRange'; | ||
|
||
export { useViewportRange }; |
48 changes: 48 additions & 0 deletions
48
packages/main/src/components/AnalyticalTable/hooks/useCellStyling.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { TextAlign } from '@ui5/webcomponents-react/lib/TextAlign'; | ||
import { VerticalAlign } from '@ui5/webcomponents-react/lib/VerticalAlign'; | ||
import { CSSProperties } from 'react'; | ||
|
||
export const useCellStyling = ({ rowHeight }, classes) => ({ column }) => { | ||
const style: CSSProperties = {}; | ||
|
||
if (rowHeight) { | ||
style.height = `${rowHeight}px`; | ||
} | ||
switch (column.hAlign) { | ||
case TextAlign.Begin: | ||
style.textAlign = 'start'; | ||
break; | ||
case TextAlign.Center: | ||
style.textAlign = 'center'; | ||
break; | ||
case TextAlign.End: | ||
style.textAlign = 'end'; | ||
break; | ||
case TextAlign.Left: | ||
style.textAlign = 'left'; | ||
break; | ||
case TextAlign.Right: | ||
style.textAlign = 'right'; | ||
break; | ||
} | ||
switch (column.vAlign) { | ||
case VerticalAlign.Bottom: | ||
style.verticalAlign = 'bottom'; | ||
break; | ||
case VerticalAlign.Middle: | ||
style.verticalAlign = 'middle'; | ||
break; | ||
case VerticalAlign.Top: | ||
style.verticalAlign = 'top'; | ||
break; | ||
} | ||
|
||
let className = classes.tableCell; | ||
if (column.className) { | ||
className += ` ${column.className}`; | ||
} | ||
return { | ||
className, | ||
style | ||
}; | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { JSSTheme } from '../../interfaces/JSSTheme'; | ||
|
||
const styles = ({ parameters }: JSSTheme) => ({ | ||
formTitle: { | ||
borderBottom: `1px solid ${parameters.sapUiGroupTitleBorderColor}` | ||
}, | ||
formTitlePaddingBottom: { | ||
paddingBottom: '2em' | ||
}, | ||
formPaddingBottom: { | ||
paddingBottom: '1em' | ||
}, | ||
formGroupStyle: { | ||
width: '100%', | ||
paddingTop: '0.25em' | ||
}, | ||
formItemTopDiv: { | ||
alignItems: 'center' | ||
}, | ||
formLabel: { | ||
paddingRight: '0.5em' | ||
}, | ||
formElement: { | ||
display: 'block' | ||
} | ||
}); | ||
|
||
export { styles }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
```jsx | ||
import { Form } from '@ui5/webcomponents-react/lib/Form'; | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { Form } from './index'; | ||
import React from 'react'; | ||
import notes from './Form.md'; | ||
import { FormItem } from './FormItem'; | ||
import { FormGroup } from './FormGroup'; | ||
import { CheckBox, Input, InputType, Option, Select } from '../..'; | ||
|
||
export const defaultStory = () => { | ||
return ( | ||
<Form title={'Test Form'}> | ||
<FormGroup title={'Personal Data'}> | ||
<FormItem labelText={'Name'}> | ||
<Input type={InputType.Text} /> | ||
</FormItem> | ||
<FormItem labelText={'Address'}> | ||
<Input type={InputType.Text} /> | ||
</FormItem> | ||
<FormItem labelText={'Country'}> | ||
<Select> | ||
<Option>Germany</Option> | ||
<Option>France</Option> | ||
<Option>Italy</Option> | ||
</Select> | ||
</FormItem> | ||
<FormItem labelText={'Home address'}> | ||
<CheckBox checked /> | ||
</FormItem> | ||
</FormGroup> | ||
<FormGroup title={'Business Data'}> | ||
<FormItem labelText={'Organization'}> | ||
<Input type={InputType.Text} /> | ||
</FormItem> | ||
<FormItem labelText={'Position'}> | ||
<Input type={InputType.Text} /> | ||
</FormItem> | ||
<FormItem labelText={'Wage'}> | ||
<Input type={InputType.Number} value={'5000'} disabled /> | ||
</FormItem> | ||
<FormItem labelText={'Pilot license'}> | ||
<CheckBox checked /> | ||
</FormItem> | ||
</FormGroup> | ||
</Form> | ||
); | ||
}; | ||
|
||
export default { | ||
title: 'Components | Form', | ||
component: Form, | ||
parameters: { notes } | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { mountThemedComponent } from '@shared/tests/utils'; | ||
import * as React from 'react'; | ||
import { Form } from '@ui5/webcomponents-react/lib/Form'; | ||
import { FormGroup } from '@ui5/webcomponents-react/lib/FormGroup'; | ||
import { FormItem } from '@ui5/webcomponents-react/lib/FormItem'; | ||
import { Input } from '../../webComponents/Input'; | ||
import { InputType } from '../..'; | ||
|
||
const SIZE_S = 200; | ||
const SIZE_M = 800; | ||
const SIZE_L = 1200; | ||
const SIZE_XL = 1600; | ||
const component = ( | ||
<Form title={'Test form'}> | ||
<FormGroup title={'Group 1'}> | ||
<FormItem labelText={'item 1'}> | ||
<Input type={InputType.Text}></Input> | ||
</FormItem> | ||
<FormItem labelText={'item 2'}> | ||
<Input type={InputType.Number}></Input> | ||
</FormItem> | ||
</FormGroup> | ||
<FormGroup title={'Group 2'}> | ||
<FormItem labelText={'item 1'}> | ||
<Input type={InputType.Text}></Input> | ||
</FormItem> | ||
<FormItem labelText={'item 2'}> | ||
<Input type={InputType.Number}></Input> | ||
</FormItem> | ||
</FormGroup> | ||
</Form> | ||
); | ||
|
||
describe('Create a Form', () => { | ||
test('size rate S; should create Label and Element with 100% width and display: block for top FormItem div', () => { | ||
window = Object.assign(window, { innerWidth: SIZE_S }); | ||
const wrapper = mountThemedComponent(component); | ||
expect(wrapper.render()).toMatchSnapshot(); | ||
}); | ||
|
||
test('size rate M; should create Label and Element with 16% and 83% width respectively and display: flex for top FormItem div', () => { | ||
window = Object.assign(window, { innerWidth: SIZE_M }); | ||
const wrapper = mountThemedComponent(component); | ||
expect(wrapper.render()).toMatchSnapshot(); | ||
}); | ||
|
||
test('size rate L; should create Label and Element with 33% and 66% width respectively and display: flex for top FormItem div', () => { | ||
window = Object.assign(window, { innerWidth: SIZE_L }); | ||
const wrapper = mountThemedComponent(component); | ||
expect(wrapper.render()).toMatchSnapshot(); | ||
}); | ||
|
||
test('size rate XL; should create Label and Element with 33% and 66% width respectively and display: flex for top FormItem div', () => { | ||
window = Object.assign(window, { innerWidth: SIZE_XL }); | ||
const wrapper = mountThemedComponent(component); | ||
expect(wrapper.render()).toMatchSnapshot(); | ||
}); | ||
|
||
test('should create a FormGroup and put ungrouped FormItems into it', () => { | ||
const ungroupedChildren = ( | ||
<Form title={'Test form'}> | ||
<FormItem labelText={'item 1'}> | ||
<Input type={InputType.Text}></Input> | ||
</FormItem> | ||
<FormItem labelText={'item 2'}> | ||
<Input type={InputType.Number}></Input> | ||
</FormItem> | ||
</Form> | ||
); | ||
const wrapper = mountThemedComponent(ungroupedChildren); | ||
expect(wrapper.render()).toMatchSnapshot(); | ||
}); | ||
|
||
test("should use a single FormGroup's title as a Form title if one is not set", () => { | ||
const ungroupedChildren = ( | ||
<Form> | ||
<FormGroup title={'To be Form title'}> | ||
<FormItem labelText={'item 1'}> | ||
<Input type={InputType.Text}></Input> | ||
</FormItem> | ||
<FormItem labelText={'item 2'}> | ||
<Input type={InputType.Number}></Input> | ||
</FormItem> | ||
</FormGroup> | ||
</Form> | ||
); | ||
const wrapper = mountThemedComponent(ungroupedChildren); | ||
expect(wrapper.render()).toMatchSnapshot(); | ||
}); | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import React, { Children, FC, forwardRef, ReactNode, ReactNodeArray, Ref } from 'react'; | ||
import { FlexBox } from '@ui5/webcomponents-react/lib/FlexBox'; | ||
import { styles } from '../Form.jss'; | ||
import { FlexBoxAlignItems } from '@ui5/webcomponents-react/lib/FlexBoxAlignItems'; | ||
import { FlexBoxDirection } from '@ui5/webcomponents-react/lib/FlexBoxDirection'; | ||
import { FlexBoxJustifyContent } from '@ui5/webcomponents-react/lib/FlexBoxJustifyContent'; | ||
import { Title } from '@ui5/webcomponents-react/lib/Title'; | ||
import { TitleLevel } from '@ui5/webcomponents-react/lib/TitleLevel'; | ||
import { createUseStyles } from 'react-jss'; | ||
import { JSSTheme } from '../../../interfaces/JSSTheme'; | ||
|
||
export interface FormGroupProps { | ||
title?: string; | ||
children: ReactNode | ReactNodeArray; | ||
type?: string; | ||
} | ||
|
||
const useStyles = createUseStyles<JSSTheme, keyof ReturnType<typeof styles>>(styles, { name: 'FormGroup' }); | ||
|
||
const FormGroup: FC<FormGroupProps> = forwardRef((props: FormGroupProps, ref: Ref<HTMLDivElement>) => { | ||
const { title, children } = props; | ||
|
||
const classes = useStyles(); | ||
|
||
return ( | ||
<div ref={ref}> | ||
{title && ( | ||
<Title level={TitleLevel.H5} className={classes.formPaddingBottom}> | ||
{title} | ||
</Title> | ||
)} | ||
<FlexBox | ||
justifyContent={FlexBoxJustifyContent.Start} | ||
alignItems={FlexBoxAlignItems.End} | ||
fitContainer | ||
direction={FlexBoxDirection.Column} | ||
> | ||
{Children.map(children, (child, index) => { | ||
return ( | ||
<div key={index.toString()} className={classes.formGroupStyle}> | ||
{child} | ||
</div> | ||
); | ||
})} | ||
</FlexBox> | ||
</div> | ||
); | ||
}); | ||
|
||
FormGroup.defaultProps = { | ||
type: 'formGroup' | ||
}; | ||
|
||
export { FormGroup }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import React, { FC, forwardRef, Ref, ReactNode, ReactNodeArray, useMemo, useContext } from 'react'; | ||
import { Label } from '@ui5/webcomponents-react/lib/Label'; | ||
import { styles } from '../Form.jss'; | ||
import { createUseStyles } from 'react-jss'; | ||
import { CurrentRange } from '../index'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahhh. I know we talked about this but I now realize that we have a cyclic dependency if we do it this way.... sorry! |
||
import { JSSTheme } from '../../../interfaces/JSSTheme'; | ||
|
||
export interface FormItemProps { | ||
labelText?: string; | ||
children: ReactNode | ReactNodeArray; | ||
type?: string; | ||
} | ||
|
||
const calculateWidth = (rate) => { | ||
return Math.floor((100 / 12) * rate) + '%'; | ||
}; | ||
|
||
const useStyles = createUseStyles<JSSTheme, keyof ReturnType<typeof styles>>(styles, { name: 'FormItem' }); | ||
|
||
const FormItem: FC<FormItemProps> = forwardRef((props: FormItemProps, ref: Ref<HTMLDivElement>) => { | ||
const { labelText, children } = props; | ||
|
||
const currentRange = useContext(CurrentRange); | ||
|
||
const classes = useStyles(); | ||
const topDivClass = classes.formItemTopDiv; | ||
const labelClass = classes.formLabel; | ||
const elementClass = classes.formElement; | ||
|
||
const memoizedStyles = useMemo(() => { | ||
let labelWidth; | ||
let labelTextAlign = 'flex-end'; | ||
let display = 'flex'; | ||
let elementWidth; | ||
|
||
switch (currentRange) { | ||
case 'Phone': | ||
labelWidth = '100%'; | ||
elementWidth = '100%'; | ||
display = 'block'; | ||
labelTextAlign = 'flex-start'; | ||
break; | ||
case 'Tablet': | ||
labelWidth = calculateWidth(2); | ||
elementWidth = calculateWidth(10); | ||
break; | ||
case 'Desktop': | ||
case 'LargeDesktop': | ||
labelWidth = calculateWidth(4); | ||
elementWidth = calculateWidth(8); | ||
break; | ||
} | ||
|
||
return { | ||
topDivStyle: { | ||
display: display | ||
}, | ||
labelStyle: { | ||
width: labelWidth, | ||
justifyContent: labelTextAlign | ||
}, | ||
elementStyle: { | ||
width: elementWidth | ||
} | ||
}; | ||
}, [children, currentRange]); | ||
|
||
return ( | ||
<div ref={ref}> | ||
<div style={memoizedStyles.topDivStyle} className={topDivClass}> | ||
<Label style={memoizedStyles.labelStyle} className={labelClass}> | ||
{labelText ? labelText : ''} | ||
</Label> | ||
<div style={memoizedStyles.elementStyle} className={elementClass}> | ||
{children} | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
}); | ||
|
||
FormItem.defaultProps = { | ||
type: 'formItem' | ||
}; | ||
|
||
export { FormItem }; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is still not correct. Please import each of those components separately. e.g.
import { CheckBox } from '@ui5/webcomponents-react/lib/CheckBox';