mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-12 08:25:44 +01:00
Checkbox and Chipinput have been improved, and a button has been added
Pushed-by: Konstantin Schaper<konstantin.schaper@cloudogu.com> Pushed-by: Tarik Gürsoy<tarik.guersoy@cloudogu.com> Co-authored-by: Konstantin Schaper<konstantin.schaper@cloudogu.com> Co-authored-by: Tarik Gürsoy<tarik.guersoy@cloudogu.com>
This commit is contained in:
4
gradle/changelog/improve_ui_forms.yaml
Normal file
4
gradle/changelog/improve_ui_forms.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
- type: changed
|
||||||
|
description: The checkbox now has a bigger click target
|
||||||
|
- type: changed
|
||||||
|
description: The chip input api now provides an external add button
|
||||||
@@ -2478,13 +2478,13 @@ exports[`Storyshots Forms/Checkbox Default 1`] = `
|
|||||||
className="control"
|
className="control"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
className="checkbox"
|
className="Checkbox__StyledLabel-sc-r42kwe-1 ZZdrN checkbox is-align-items-center"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
aria-describedby="checkbox_11"
|
aria-describedby="checkbox_11"
|
||||||
aria-labelledby="checkbox_10"
|
aria-labelledby="checkbox_10"
|
||||||
checked={false}
|
checked={false}
|
||||||
className="checkbox"
|
className="Checkbox__StyledInput-sc-r42kwe-0 kCgKZT m-3"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@@ -2501,13 +2501,13 @@ exports[`Storyshots Forms/Checkbox Default 1`] = `
|
|||||||
className="control"
|
className="control"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
className="checkbox"
|
className="Checkbox__StyledLabel-sc-r42kwe-1 ZZdrN checkbox is-align-items-center"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
aria-describedby="checkbox_13"
|
aria-describedby="checkbox_13"
|
||||||
aria-labelledby="checkbox_12"
|
aria-labelledby="checkbox_12"
|
||||||
checked={true}
|
checked={true}
|
||||||
className="checkbox"
|
className="Checkbox__StyledInput-sc-r42kwe-0 kCgKZT m-3"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@@ -2524,13 +2524,13 @@ exports[`Storyshots Forms/Checkbox Default 1`] = `
|
|||||||
className="control"
|
className="control"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
className="checkbox"
|
className="Checkbox__StyledLabel-sc-r42kwe-1 ZZdrN checkbox is-align-items-center"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
aria-describedby="checkbox_15"
|
aria-describedby="checkbox_15"
|
||||||
aria-labelledby="checkbox_14"
|
aria-labelledby="checkbox_14"
|
||||||
checked={true}
|
checked={true}
|
||||||
className="checkbox"
|
className="Checkbox__StyledInput-sc-r42kwe-0 kCgKZT m-3"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@@ -2554,14 +2554,14 @@ exports[`Storyshots Forms/Checkbox Disabled 1`] = `
|
|||||||
className="control"
|
className="control"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
className="checkbox"
|
className="Checkbox__StyledLabel-sc-r42kwe-1 ZZdrN checkbox is-align-items-center"
|
||||||
disabled={true}
|
disabled={true}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
aria-describedby="checkbox_17"
|
aria-describedby="checkbox_17"
|
||||||
aria-labelledby="checkbox_16"
|
aria-labelledby="checkbox_16"
|
||||||
checked={true}
|
checked={true}
|
||||||
className="checkbox"
|
className="Checkbox__StyledInput-sc-r42kwe-0 kCgKZT m-3"
|
||||||
disabled={true}
|
disabled={true}
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
@@ -2584,13 +2584,13 @@ Array [
|
|||||||
className="control"
|
className="control"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
className="checkbox"
|
className="Checkbox__StyledLabel-sc-r42kwe-1 ZZdrN checkbox is-align-items-center"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
aria-describedby="checkbox_25"
|
aria-describedby="checkbox_25"
|
||||||
aria-labelledby="checkbox_24"
|
aria-labelledby="checkbox_24"
|
||||||
checked={false}
|
checked={false}
|
||||||
className="checkbox"
|
className="Checkbox__StyledInput-sc-r42kwe-0 kCgKZT m-3"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@@ -2618,12 +2618,12 @@ exports[`Storyshots Forms/Checkbox ReactHookForm 1`] = `
|
|||||||
className="control"
|
className="control"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
className="checkbox"
|
className="Checkbox__StyledLabel-sc-r42kwe-1 ZZdrN checkbox is-align-items-center"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
aria-describedby="checkbox_27"
|
aria-describedby="checkbox_27"
|
||||||
aria-labelledby="checkbox_26"
|
aria-labelledby="checkbox_26"
|
||||||
className="checkbox"
|
className="Checkbox__StyledInput-sc-r42kwe-0 kCgKZT m-3"
|
||||||
name="rememberMe"
|
name="rememberMe"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
@@ -2641,12 +2641,12 @@ exports[`Storyshots Forms/Checkbox ReactHookForm 1`] = `
|
|||||||
className="control"
|
className="control"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
className="checkbox"
|
className="Checkbox__StyledLabel-sc-r42kwe-1 ZZdrN checkbox is-align-items-center"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
aria-describedby="checkbox_29"
|
aria-describedby="checkbox_29"
|
||||||
aria-labelledby="checkbox_28"
|
aria-labelledby="checkbox_28"
|
||||||
className="checkbox"
|
className="Checkbox__StyledInput-sc-r42kwe-0 kCgKZT m-3"
|
||||||
name="scramblePassword"
|
name="scramblePassword"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
@@ -2664,13 +2664,13 @@ exports[`Storyshots Forms/Checkbox ReactHookForm 1`] = `
|
|||||||
className="control"
|
className="control"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
className="checkbox"
|
className="Checkbox__StyledLabel-sc-r42kwe-1 ZZdrN checkbox is-align-items-center"
|
||||||
disabled={true}
|
disabled={true}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
aria-describedby="checkbox_31"
|
aria-describedby="checkbox_31"
|
||||||
aria-labelledby="checkbox_30"
|
aria-labelledby="checkbox_30"
|
||||||
className="checkbox"
|
className="Checkbox__StyledInput-sc-r42kwe-0 kCgKZT m-3"
|
||||||
disabled={true}
|
disabled={true}
|
||||||
name="disabled"
|
name="disabled"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
@@ -2690,12 +2690,12 @@ exports[`Storyshots Forms/Checkbox ReactHookForm 1`] = `
|
|||||||
className="control"
|
className="control"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
className="checkbox"
|
className="Checkbox__StyledLabel-sc-r42kwe-1 ZZdrN checkbox is-align-items-center"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
aria-describedby="checkbox_33"
|
aria-describedby="checkbox_33"
|
||||||
aria-labelledby="checkbox_32"
|
aria-labelledby="checkbox_32"
|
||||||
className="checkbox"
|
className="Checkbox__StyledInput-sc-r42kwe-0 kCgKZT m-3"
|
||||||
name="readonly"
|
name="readonly"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
@@ -2735,13 +2735,13 @@ Array [
|
|||||||
className="control"
|
className="control"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
className="checkbox"
|
className="Checkbox__StyledLabel-sc-r42kwe-1 ZZdrN checkbox is-align-items-center"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
aria-describedby="checkbox_23"
|
aria-describedby="checkbox_23"
|
||||||
aria-labelledby="checkbox_22"
|
aria-labelledby="checkbox_22"
|
||||||
checked={false}
|
checked={false}
|
||||||
className="checkbox"
|
className="Checkbox__StyledInput-sc-r42kwe-0 kCgKZT m-3"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@@ -2776,13 +2776,13 @@ exports[`Storyshots Forms/Checkbox With HelpText 1`] = `
|
|||||||
className="control"
|
className="control"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
className="checkbox"
|
className="Checkbox__StyledLabel-sc-r42kwe-1 ZZdrN checkbox is-align-items-center"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
aria-describedby="checkbox_19"
|
aria-describedby="checkbox_19"
|
||||||
aria-labelledby="checkbox_18"
|
aria-labelledby="checkbox_18"
|
||||||
checked={false}
|
checked={false}
|
||||||
className="checkbox"
|
className="Checkbox__StyledInput-sc-r42kwe-0 kCgKZT m-3"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@@ -2811,13 +2811,13 @@ exports[`Storyshots Forms/Checkbox With HelpText 1`] = `
|
|||||||
className="control"
|
className="control"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
className="checkbox"
|
className="Checkbox__StyledLabel-sc-r42kwe-1 ZZdrN checkbox is-align-items-center"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
aria-describedby="checkbox_21"
|
aria-describedby="checkbox_21"
|
||||||
aria-labelledby="checkbox_20"
|
aria-labelledby="checkbox_20"
|
||||||
checked={true}
|
checked={true}
|
||||||
className="checkbox"
|
className="Checkbox__StyledInput-sc-r42kwe-0 kCgKZT m-3"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@@ -18413,13 +18413,13 @@ Array [
|
|||||||
className="control"
|
className="control"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
className="checkbox"
|
className="Checkbox__StyledLabel-sc-r42kwe-1 ZZdrN checkbox is-align-items-center"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
aria-describedby="checkbox_130"
|
aria-describedby="checkbox_130"
|
||||||
aria-labelledby="checkbox_129"
|
aria-labelledby="checkbox_129"
|
||||||
checked={true}
|
checked={true}
|
||||||
className="checkbox"
|
className="Checkbox__StyledInput-sc-r42kwe-0 kCgKZT m-3"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
|||||||
@@ -28,6 +28,17 @@ import useInnerRef from "./useInnerRef";
|
|||||||
import { createFormFieldWrapper, FieldProps, FieldType, isLegacy, isUsingRef } from "./FormFieldTypes";
|
import { createFormFieldWrapper, FieldProps, FieldType, isLegacy, isUsingRef } from "./FormFieldTypes";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { createA11yId } from "../createA11yId";
|
import { createA11yId } from "../createA11yId";
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
const StyledInput = styled.input`
|
||||||
|
height: 1rem;
|
||||||
|
width: 1rem;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledLabel = styled.label`
|
||||||
|
margin-left: -0.75rem;
|
||||||
|
display: inline-flex;
|
||||||
|
`;
|
||||||
|
|
||||||
export interface CheckboxElement extends HTMLElement {
|
export interface CheckboxElement extends HTMLElement {
|
||||||
value: boolean;
|
value: boolean;
|
||||||
@@ -109,11 +120,11 @@ const InnerCheckbox: FC<FieldProps<BaseProps, HTMLInputElement, boolean>> = ({
|
|||||||
because jsx label does not the custom disabled attribute
|
because jsx label does not the custom disabled attribute
|
||||||
but bulma does.
|
but bulma does.
|
||||||
// @ts-ignore */}
|
// @ts-ignore */}
|
||||||
<label className="checkbox" disabled={disabled}>
|
<StyledLabel className="checkbox is-align-items-center" disabled={disabled}>
|
||||||
<input
|
<StyledInput
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
name={name}
|
name={name}
|
||||||
className={classNames("checkbox", className)}
|
className={classNames("m-3", className)}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
onBlur={handleBlur}
|
onBlur={handleBlur}
|
||||||
ref={field}
|
ref={field}
|
||||||
@@ -126,7 +137,7 @@ const InnerCheckbox: FC<FieldProps<BaseProps, HTMLInputElement, boolean>> = ({
|
|||||||
/>{" "}
|
/>{" "}
|
||||||
{label}
|
{label}
|
||||||
{renderHelp()}
|
{renderHelp()}
|
||||||
</label>
|
</StyledLabel>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -25,20 +25,52 @@
|
|||||||
import React, { InputHTMLAttributes } from "react";
|
import React, { InputHTMLAttributes } from "react";
|
||||||
import { createAttributesForTesting } from "@scm-manager/ui-components";
|
import { createAttributesForTesting } from "@scm-manager/ui-components";
|
||||||
import Help from "../base/help/Help";
|
import Help from "../base/help/Help";
|
||||||
|
import styled from "styled-components";
|
||||||
|
import classNames from "classnames";
|
||||||
|
|
||||||
|
const StyledInput = styled.input`
|
||||||
|
height: 1rem;
|
||||||
|
width: 1rem;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledLabel = styled.label`
|
||||||
|
margin-left: -0.75rem;
|
||||||
|
display: inline-flex;
|
||||||
|
`;
|
||||||
|
|
||||||
type InputFieldProps = {
|
type InputFieldProps = {
|
||||||
label: string;
|
label: string;
|
||||||
helpText?: string;
|
helpText?: string;
|
||||||
testId?: string;
|
testId?: string;
|
||||||
|
labelClassName?: string;
|
||||||
} & Omit<InputHTMLAttributes<HTMLInputElement>, "type">;
|
} & Omit<InputHTMLAttributes<HTMLInputElement>, "type">;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://bulma.io/documentation/form/checkbox/
|
* @see https://bulma.io/documentation/form/checkbox/
|
||||||
*/
|
*/
|
||||||
const Checkbox = React.forwardRef<HTMLInputElement, InputFieldProps>(
|
const Checkbox = React.forwardRef<HTMLInputElement, InputFieldProps>(
|
||||||
({ readOnly, label, value, name, checked, defaultChecked, defaultValue, testId, helpText, ...props }, ref) => (
|
(
|
||||||
|
{
|
||||||
|
readOnly,
|
||||||
|
label,
|
||||||
|
className,
|
||||||
|
labelClassName,
|
||||||
|
value,
|
||||||
|
name,
|
||||||
|
checked,
|
||||||
|
defaultChecked,
|
||||||
|
defaultValue,
|
||||||
|
testId,
|
||||||
|
helpText,
|
||||||
|
...props
|
||||||
|
},
|
||||||
|
ref
|
||||||
|
) => (
|
||||||
|
<StyledLabel
|
||||||
|
className={classNames("checkbox is-align-items-center", labelClassName)}
|
||||||
// @ts-ignore bulma uses the disabled attribute on labels, although it is not part of the html spec
|
// @ts-ignore bulma uses the disabled attribute on labels, although it is not part of the html spec
|
||||||
<label className="checkbox" disabled={readOnly || props.disabled}>
|
disabled={readOnly || props.disabled}
|
||||||
|
>
|
||||||
{readOnly ? (
|
{readOnly ? (
|
||||||
<>
|
<>
|
||||||
<input
|
<input
|
||||||
@@ -50,9 +82,9 @@ const Checkbox = React.forwardRef<HTMLInputElement, InputFieldProps>(
|
|||||||
defaultChecked={defaultChecked}
|
defaultChecked={defaultChecked}
|
||||||
readOnly
|
readOnly
|
||||||
/>
|
/>
|
||||||
<input
|
<StyledInput
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
className="mr-1"
|
className={classNames("m-3", className)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
value={value}
|
value={value}
|
||||||
defaultValue={defaultValue}
|
defaultValue={defaultValue}
|
||||||
@@ -64,9 +96,9 @@ const Checkbox = React.forwardRef<HTMLInputElement, InputFieldProps>(
|
|||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<input
|
<StyledInput
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
className="mr-1"
|
className={classNames("m-3", className)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
name={name}
|
name={name}
|
||||||
value={value}
|
value={value}
|
||||||
@@ -77,9 +109,10 @@ const Checkbox = React.forwardRef<HTMLInputElement, InputFieldProps>(
|
|||||||
{...createAttributesForTesting(testId)}
|
{...createAttributesForTesting(testId)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{label}
|
{label}
|
||||||
{helpText ? <Help className="ml-1" text={helpText} /> : null}
|
{helpText ? <Help className="ml-1" text={helpText} /> : null}
|
||||||
</label>
|
</StyledLabel>
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
export default Checkbox;
|
export default Checkbox;
|
||||||
|
|||||||
@@ -23,22 +23,28 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { storiesOf } from "@storybook/react";
|
import { storiesOf } from "@storybook/react";
|
||||||
import React, { useState } from "react";
|
import React, { useRef, useState } from "react";
|
||||||
import ChipInputField from "./ChipInputField";
|
import ChipInputField from "./ChipInputField";
|
||||||
import Combobox from "../combobox/Combobox";
|
import Combobox from "../combobox/Combobox";
|
||||||
import { Option } from "@scm-manager/ui-types";
|
import { Option } from "@scm-manager/ui-types";
|
||||||
|
import ChipInput from "../headless-chip-input/ChipInput";
|
||||||
|
|
||||||
storiesOf("Chip Input Field", module)
|
storiesOf("Chip Input Field", module)
|
||||||
.add("Default", () => {
|
.add("Default", () => {
|
||||||
const [value, setValue] = useState<Option<string>[]>([]);
|
const [value, setValue] = useState<Option<string>[]>([]);
|
||||||
|
const ref = useRef<HTMLInputElement>(null);
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<ChipInputField
|
<ChipInputField
|
||||||
value={value}
|
value={value}
|
||||||
onChange={setValue}
|
onChange={setValue}
|
||||||
label="Test Chips"
|
label="Test Chips"
|
||||||
placeholder="Type a new chip name and press enter to add"
|
placeholder="Type a new chip name and press enter to add"
|
||||||
aria-label="My personal chip list"
|
aria-label="My personal chip list"
|
||||||
|
ref={ref}
|
||||||
/>
|
/>
|
||||||
|
<ChipInput.AddButton inputRef={ref}>Add</ChipInput.AddButton>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.add("With Autocomplete", () => {
|
.add("With Autocomplete", () => {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { KeyboardEventHandler, ReactElement, useCallback } from "react";
|
import React, { KeyboardEventHandler, PropsWithRef, ReactElement, Ref, RefObject, useCallback } from "react";
|
||||||
import { createAttributesForTesting, useGeneratedId } from "@scm-manager/ui-components";
|
import { createAttributesForTesting, useGeneratedId } from "@scm-manager/ui-components";
|
||||||
import Field from "../base/Field";
|
import Field from "../base/Field";
|
||||||
import Label from "../base/label/Label";
|
import Label from "../base/label/Label";
|
||||||
@@ -81,6 +81,7 @@ type InputFieldProps<T> = {
|
|||||||
className?: string;
|
className?: string;
|
||||||
isLoading?: boolean;
|
isLoading?: boolean;
|
||||||
isNewItemDuplicate?: (existingItem: Option<T>, newItem: Option<T>) => boolean;
|
isNewItemDuplicate?: (existingItem: Option<T>, newItem: Option<T>) => boolean;
|
||||||
|
ref?: Ref<HTMLInputElement>;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,7 +106,7 @@ const ChipInputField = function ChipInputField<T>(
|
|||||||
isLoading,
|
isLoading,
|
||||||
isNewItemDuplicate,
|
isNewItemDuplicate,
|
||||||
...props
|
...props
|
||||||
}: InputFieldProps<T>,
|
}: PropsWithRef<InputFieldProps<T>>,
|
||||||
ref: React.ForwardedRef<HTMLInputElement>
|
ref: React.ForwardedRef<HTMLInputElement>
|
||||||
) {
|
) {
|
||||||
const [t] = useTranslation("commons", { keyPrefix: "form.chipList" });
|
const [t] = useTranslation("commons", { keyPrefix: "form.chipList" });
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
import React, {
|
import React, {
|
||||||
ButtonHTMLAttributes,
|
ButtonHTMLAttributes,
|
||||||
|
ComponentProps,
|
||||||
ComponentType,
|
ComponentType,
|
||||||
Context,
|
Context,
|
||||||
createContext,
|
createContext,
|
||||||
@@ -40,6 +41,7 @@ import React, {
|
|||||||
import { Slot } from "@radix-ui/react-slot";
|
import { Slot } from "@radix-ui/react-slot";
|
||||||
import { Option } from "@scm-manager/ui-types";
|
import { Option } from "@scm-manager/ui-types";
|
||||||
import { mergeRefs, withForwardRef } from "../helpers";
|
import { mergeRefs, withForwardRef } from "../helpers";
|
||||||
|
import { Button } from "@scm-manager/ui-buttons";
|
||||||
|
|
||||||
type ChipInputContextType<T> = {
|
type ChipInputContextType<T> = {
|
||||||
add(newValue: Option<T>): void;
|
add(newValue: Option<T>): void;
|
||||||
@@ -215,8 +217,21 @@ const ChipInput = withForwardRef(function ChipInput<T>(
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const AddButton = React.forwardRef<
|
||||||
|
HTMLButtonElement,
|
||||||
|
Omit<ComponentProps<typeof Button>, "onClick"> & { inputRef: RefObject<HTMLInputElement | null> }
|
||||||
|
>(({ inputRef, children, ...props }, ref) => (
|
||||||
|
<Button
|
||||||
|
{...props}
|
||||||
|
onClick={() => inputRef.current?.dispatchEvent(new KeyboardEvent("keydown", { key: "Enter", bubbles: true }))}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Button>
|
||||||
|
));
|
||||||
|
|
||||||
export default Object.assign(ChipInput, {
|
export default Object.assign(ChipInput, {
|
||||||
Chip: Object.assign(Chip, {
|
Chip: Object.assign(Chip, {
|
||||||
Delete: ChipDelete,
|
Delete: ChipDelete,
|
||||||
}),
|
}),
|
||||||
|
AddButton,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -36,17 +36,23 @@ import ControlledColumn from "./table/ControlledColumn";
|
|||||||
import AddListEntryForm from "./AddListEntryForm";
|
import AddListEntryForm from "./AddListEntryForm";
|
||||||
import { ScmNestedFormPathContextProvider } from "./FormPathContext";
|
import { ScmNestedFormPathContextProvider } from "./FormPathContext";
|
||||||
import ControlledComboboxField from "./combobox/ControlledComboboxField";
|
import ControlledComboboxField from "./combobox/ControlledComboboxField";
|
||||||
|
import ChipInputFieldComponent from "./chip-input/ChipInputField";
|
||||||
|
import ChipInput from "./headless-chip-input/ChipInput";
|
||||||
|
|
||||||
|
export { default as Checkbox } from "./checkbox/Checkbox";
|
||||||
export { default as Combobox } from "./combobox/Combobox";
|
export { default as Combobox } from "./combobox/Combobox";
|
||||||
export { default as ConfigurationForm } from "./ConfigurationForm";
|
export { default as ConfigurationForm } from "./ConfigurationForm";
|
||||||
export { default as SelectField } from "./select/SelectField";
|
export { default as SelectField } from "./select/SelectField";
|
||||||
export { default as ChipInputField } from "./chip-input/ChipInputField";
|
|
||||||
export { default as ComboboxField } from "./combobox/ComboboxField";
|
export { default as ComboboxField } from "./combobox/ComboboxField";
|
||||||
export { default as Input } from "./input/Input";
|
export { default as Input } from "./input/Input";
|
||||||
export { default as Select } from "./select/Select";
|
export { default as Select } from "./select/Select";
|
||||||
export * from "./resourceHooks";
|
export * from "./resourceHooks";
|
||||||
export { default as Label } from "./base/label/Label";
|
export { default as Label } from "./base/label/Label";
|
||||||
|
|
||||||
|
export const ChipInputField = Object.assign(ChipInputFieldComponent, {
|
||||||
|
AddButton: ChipInput.AddButton,
|
||||||
|
});
|
||||||
|
|
||||||
export const Form = Object.assign(FormCmp, {
|
export const Form = Object.assign(FormCmp, {
|
||||||
Row: FormRow,
|
Row: FormRow,
|
||||||
Input: ControlledInputField,
|
Input: ControlledInputField,
|
||||||
|
|||||||
Reference in New Issue
Block a user