-
Notifications
You must be signed in to change notification settings - Fork 138
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Rename inline edit (V1) (#2881)
* feat: rename InlineEdit * chore: remove incorrect commentry --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
- Loading branch information
1 parent
121dbf1
commit cff465d
Showing
11 changed files
with
404 additions
and
6 deletions.
There are no files selected for viewing
42 changes: 42 additions & 0 deletions
42
packages/cloud-cognitive/src/components/EditInPlace/EditInPlace.js
This file contains 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,42 @@ | ||
/** | ||
* Copyright IBM Corp. 2022, 2022 | ||
* | ||
* This source code is licensed under the Apache-2.0 license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
import React, { forwardRef } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { pkg } from '../../settings'; | ||
import { InlineEditV1 } from '../InlineEditV1'; | ||
import { InlineEditV2 } from '../InlineEditV2'; | ||
|
||
/** | ||
* this is a wrapper component that will allow us to support the rename of InlineEdit to EditInPlace | ||
* | ||
* if the user passes in the v2 feature flag the v2 version of the component will be rendered | ||
* since this is a temporary solution the named export should just remain InlineEdit unlike how | ||
* Card works as a base layer for Productive and Expressive cards. | ||
*/ | ||
|
||
const componentName = 'EditInPlace'; | ||
|
||
export let EditInPlace = forwardRef(({ v2, ...rest }, ref) => { | ||
const props = { | ||
...rest, | ||
ref, | ||
}; | ||
if (v2 === true) { | ||
return <InlineEditV2 {...props} />; | ||
} | ||
|
||
return <InlineEditV1 {...props} />; | ||
}); | ||
|
||
EditInPlace = pkg.checkComponentEnabled(EditInPlace, componentName); | ||
|
||
EditInPlace.displayName = componentName; | ||
|
||
EditInPlace.propTypes = { | ||
v2: PropTypes.bool, | ||
}; |
232 changes: 232 additions & 0 deletions
232
packages/cloud-cognitive/src/components/EditInPlace/EditInPlaceV1.stories.js
This file contains 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,232 @@ | ||
/** | ||
* Copyright IBM Corp. 2022, 2022 | ||
* | ||
* This source code is licensed under the Apache-2.0 license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
import React, { useEffect, useState } from 'react'; | ||
import { action } from '@storybook/addon-actions'; | ||
|
||
import { | ||
getStoryTitle, | ||
prepareStory, | ||
} from '../../global/js/utils/story-helper'; | ||
import { DisplayBox } from '../../global/js/utils/DisplayBox'; | ||
|
||
import { EditInPlace } from '.'; | ||
|
||
import mdx from '../InlineEditV1//InlineEditV1.mdx'; | ||
|
||
import styles from '../InlineEditV1/_storybook-styles.scss'; | ||
|
||
const storyClass = 'inline-edit-stories'; | ||
|
||
const validationOptions = { | ||
'Default, no validation change': {}, | ||
'On change or save invalid if empty': { onChangeInvalidIfEmpty: true }, | ||
'On change or save includes ABC invalid': { onChangeInvalidWithABC: true }, | ||
'On save invalid if empty': { onSaveInvalidIfEmpty: true }, | ||
'On save includes ABC invalid': { onSaveInvalidWithABC: true }, | ||
}; | ||
|
||
const buttonTooltipAlignmentOptions = { | ||
'Default / undefined': undefined, | ||
'All start': 'start', | ||
'All center': 'center', | ||
'All end': 'end', | ||
'Edit start, Cancel center, save end': { | ||
edit: 'start', | ||
cancel: 'center', | ||
save: 'end', | ||
}, | ||
}; | ||
|
||
const buttonTooltipPositionOptions = { | ||
'Default / undefined': undefined, | ||
'All top': 'top', | ||
'All right': 'right', | ||
'All bottom': 'bottom', | ||
'All left': 'left', | ||
'Edit and save right, cancel left': { | ||
edit: 'right', | ||
cancel: 'left', | ||
save: 'right', | ||
}, | ||
}; | ||
|
||
export default { | ||
title: getStoryTitle(EditInPlace.displayName), | ||
component: EditInPlace, | ||
argTypes: { | ||
buttonTooltipAlignment: { | ||
control: { | ||
type: 'select', | ||
labels: Object.keys(buttonTooltipAlignmentOptions), | ||
}, | ||
options: Object.values(buttonTooltipAlignmentOptions).map((_k, i) => i), | ||
mapping: Object.values(buttonTooltipAlignmentOptions), | ||
}, | ||
buttonTooltipPosition: { | ||
control: { | ||
type: 'select', | ||
labels: Object.keys(buttonTooltipPositionOptions), | ||
}, | ||
options: Object.values(buttonTooltipPositionOptions).map((_k, i) => i), | ||
mapping: Object.values(buttonTooltipPositionOptions), | ||
}, | ||
containerWidth: { | ||
control: { type: 'range', min: 20, max: 800, step: 10 }, | ||
description: | ||
'Controls containing element width. Used for demonstration purposes, not property of the component.', | ||
}, | ||
EditInPlaceFullWidth: { | ||
control: { type: 'boolean' }, | ||
description: | ||
'Sets component width `100%`. Used for demonstration purposes, not property of the component.', | ||
}, | ||
validation: { | ||
control: { | ||
type: 'select', | ||
labels: Object.keys(validationOptions), | ||
}, | ||
options: Object.values(validationOptions).map((_k, i) => i), | ||
mapping: Object.values(validationOptions), | ||
defaultValue: 0, | ||
}, | ||
}, | ||
parameters: { | ||
styles, | ||
layout: 'padded', | ||
docs: { | ||
page: mdx, | ||
}, | ||
}, | ||
decorators: [ | ||
(story) => ( | ||
<DisplayBox className={`${storyClass}__viewport`}>{story()}</DisplayBox> | ||
), | ||
], | ||
}; | ||
|
||
const actionSave = action('save'); | ||
const actionRejectSave = action('rejected save'); | ||
const actionChange = action('change'); | ||
const actionRejectChange = action('rejected change'); | ||
const actionCancel = action('cancel'); | ||
|
||
/** | ||
* TODO: Declare template(s) for one or more scenarios. | ||
*/ | ||
const Template = ({ | ||
containerWidth, | ||
EditInPlaceFullWidth, | ||
invalid, | ||
invalidText, | ||
editDescription, | ||
cancelDescription, | ||
saveDescription, | ||
validation, | ||
value: initialValue, | ||
...rest | ||
}) => { | ||
const [value, setValue] = useState(initialValue); | ||
const [liveInvalid, setLiveInvalid] = useState(invalid); | ||
const [liveInvalidText, setLiveInvalidText] = useState(invalidText); | ||
|
||
useEffect(() => { | ||
setLiveInvalid(invalid); | ||
}, [invalid]); | ||
|
||
const handleValidation = (val, change, save) => { | ||
let newInvalid = false; | ||
let invalidText = ''; | ||
let updateValidation = false; | ||
|
||
const zeroLength = val.length === 0; | ||
const hasABC = /ABC/.test(val); | ||
|
||
if ( | ||
(change && validation?.onChangeInvalidIfEmpty) || | ||
(save && validation?.onSaveInvalidIfEmpty) | ||
) { | ||
newInvalid = zeroLength; | ||
invalidText = newInvalid ? 'This field cannot be empty' : ''; | ||
updateValidation = true; | ||
} else if ( | ||
(change && validation?.onChangeInvalidWithABC) || | ||
(save && validation?.onSaveInvalidWithABC) | ||
) { | ||
newInvalid = hasABC; | ||
invalidText = newInvalid ? 'Cannot contain ABC in the entry' : ''; | ||
updateValidation = true; | ||
} | ||
|
||
if (updateValidation) { | ||
setLiveInvalid(newInvalid); | ||
setLiveInvalidText(invalidText); | ||
} | ||
return updateValidation && newInvalid; | ||
}; | ||
|
||
const onSave = (val) => { | ||
const reject = handleValidation(val, false, true); | ||
|
||
if (reject) { | ||
actionRejectSave(val); | ||
} else { | ||
setValue(val); | ||
actionSave(val); | ||
} | ||
}; | ||
const onChange = (val) => { | ||
const reject = handleValidation(val, true, false); | ||
|
||
if (reject) { | ||
actionRejectChange(val); | ||
} else { | ||
actionChange(val); | ||
} | ||
}; | ||
const onCancel = actionCancel; | ||
|
||
useEffect(() => { | ||
setValue(initialValue); | ||
}, [initialValue]); | ||
|
||
return ( | ||
<div | ||
style={{ width: containerWidth }} | ||
className={EditInPlaceFullWidth ? 'component-full-width' : ''} | ||
> | ||
<EditInPlace | ||
{...rest} | ||
{...{ | ||
editDescription, | ||
invalid: liveInvalid, | ||
invalidText: liveInvalidText, | ||
onSave, | ||
onChange, | ||
onCancel, | ||
cancelDescription, | ||
saveDescription, | ||
value, | ||
}} | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
export const Version1 = prepareStory(Template, { | ||
args: { | ||
containerWidth: 300, | ||
EditInPlaceFullWidth: true, | ||
editDescription: 'Edit', | ||
id: 'edit button', | ||
labelText: 'Inline edit', | ||
cancelDescription: 'Cancel', | ||
saveDescription: 'Save', | ||
value: 'hello, world', | ||
placeholder: 'placeholder text', | ||
}, | ||
}); |
90 changes: 90 additions & 0 deletions
90
packages/cloud-cognitive/src/components/EditInPlace/EditInPlaceV2.stories.js
This file contains 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 @@ | ||
/** | ||
* Copyright IBM Corp. 2022, 2022 | ||
* | ||
* This source code is licensed under the Apache-2.0 license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
import React, { useState } from 'react'; | ||
import { | ||
getStoryTitle, | ||
prepareStory, | ||
} from '../../global/js/utils/story-helper'; | ||
import { action } from '@storybook/addon-actions'; | ||
import { EditInPlace } from '.'; | ||
import mdx from '../InlineEditV2/InlineEditV2.mdx'; | ||
import styles from '../InlineEditV2/_storybook-styles.scss'; | ||
|
||
export default { | ||
title: getStoryTitle(EditInPlace.displayName), | ||
component: EditInPlace, | ||
parameters: { | ||
styles, | ||
docs: { | ||
page: mdx, | ||
}, | ||
}, | ||
}; | ||
|
||
const actionSave = action('save'); | ||
const actionChange = action('change'); | ||
const actionCancel = action('cancel'); | ||
|
||
const defaultProps = { | ||
cancelLabel: 'Cancel', | ||
editLabel: 'Edit', | ||
id: 'story-id', | ||
invalid: false, | ||
invalidLabel: 'This field is required', | ||
labelText: 'Label text', | ||
onCancel: () => {}, | ||
onChange: () => {}, | ||
onSave: () => {}, | ||
// readOnly: false, | ||
// readOnlyLabel: 'This value is read only', | ||
saveLabel: 'Save', | ||
v2: true, | ||
value: 'default', | ||
}; | ||
|
||
const Template = (args) => { | ||
const [value, setValue] = useState(defaultProps.value); | ||
|
||
const onChange = (val) => { | ||
setValue(val); | ||
actionChange(val); | ||
}; | ||
|
||
const onSave = () => { | ||
console.log('saved!', value); | ||
actionSave(value); | ||
}; | ||
|
||
const onCancel = (initialVal) => { | ||
setValue(initialVal); | ||
actionCancel(initialVal); | ||
}; | ||
|
||
const props = { | ||
...args, | ||
value, | ||
onChange, | ||
onSave, | ||
onCancel, | ||
}; | ||
|
||
return <EditInPlace {...props} className="inline-edit-v2-example" />; | ||
}; | ||
|
||
export const Version2 = prepareStory(Template, { | ||
args: { | ||
...defaultProps, | ||
}, | ||
}); | ||
|
||
// export const ReadOnly = prepareStory(Template, { | ||
// args: { | ||
// ...defaultProps, | ||
// readOnly: true, | ||
// }, | ||
// }); |
This file contains 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,8 @@ | ||
/** | ||
* Copyright IBM Corp. 2022, 2022 | ||
* | ||
* This source code is licensed under the Apache-2.0 license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
export { EditInPlace } from './EditInPlace'; |
This file contains 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
Oops, something went wrong.