@planningcenter/tapestry 2.10.2-rc.1 → 2.10.2-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/input/Input.d.ts +44 -0
- package/dist/components/input/Input.d.ts.map +1 -0
- package/dist/components/input/Input.js +44 -0
- package/dist/components/input/Input.js.map +1 -0
- package/dist/components/input/index.d.ts +4 -0
- package/dist/components/input/index.d.ts.map +1 -0
- package/dist/components/textarea/TextArea.d.ts +38 -0
- package/dist/components/textarea/TextArea.d.ts.map +1 -0
- package/dist/components/textarea/TextArea.js +27 -0
- package/dist/components/textarea/TextArea.js.map +1 -0
- package/dist/components/textarea/index.d.ts +4 -0
- package/dist/components/textarea/index.d.ts.map +1 -0
- package/dist/reactRender.css +589 -210
- package/dist/reactRender.css.map +1 -1
- package/dist/reactRenderLegacy.css +589 -210
- package/dist/reactRenderLegacy.css.map +1 -1
- package/dist/unstable.css +379 -0
- package/dist/unstable.css.map +1 -1
- package/dist/unstable.d.ts +2 -0
- package/dist/unstable.d.ts.map +1 -1
- package/dist/unstable.js +2 -0
- package/dist/unstable.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import "./index.css";
|
|
2
|
+
import React, { type InputHTMLAttributes } from "react";
|
|
3
|
+
export type InputSize = "lg" | "md";
|
|
4
|
+
export type InputType = "email" | "number" | "password" | "search" | "tel" | "text" | "url";
|
|
5
|
+
interface InputBaseProps {
|
|
6
|
+
/** If true, the input width grows to fit content (inline editing) */
|
|
7
|
+
autoWidth?: boolean;
|
|
8
|
+
/** Helper text below the input. Red when invalid. */
|
|
9
|
+
description?: string;
|
|
10
|
+
/** Triggers invalid state (red border, red description) */
|
|
11
|
+
invalid?: boolean;
|
|
12
|
+
/** Highlights all text when the field receives focus */
|
|
13
|
+
selectTextOnFocus?: boolean;
|
|
14
|
+
/** Visual size of the input */
|
|
15
|
+
size?: InputSize;
|
|
16
|
+
/** Supported input types — defaults to 'text' */
|
|
17
|
+
type?: InputType;
|
|
18
|
+
}
|
|
19
|
+
interface InputWithVisibleLabel extends InputBaseProps {
|
|
20
|
+
/** If true, label is rendered as aria-label instead of visible label */
|
|
21
|
+
hideLabel?: false;
|
|
22
|
+
/** Label text displayed above the input */
|
|
23
|
+
label: React.ReactNode;
|
|
24
|
+
}
|
|
25
|
+
interface InputWithHiddenLabel extends InputBaseProps {
|
|
26
|
+
/** If true, label is rendered as aria-label instead of visible label */
|
|
27
|
+
hideLabel: true;
|
|
28
|
+
/** Label text used as aria-label (must be string when hidden) */
|
|
29
|
+
label: string;
|
|
30
|
+
}
|
|
31
|
+
interface InputWithAriaLabelledBy extends InputBaseProps {
|
|
32
|
+
"aria-labelledby": string;
|
|
33
|
+
hideLabel?: never;
|
|
34
|
+
label?: never;
|
|
35
|
+
}
|
|
36
|
+
export type InputProps = InputWithAriaLabelledBy | InputWithHiddenLabel | InputWithVisibleLabel;
|
|
37
|
+
/**
|
|
38
|
+
* Combines standard HTML input attributes with custom Input props.
|
|
39
|
+
* Omits 'size' and 'type' from HTML attributes to avoid conflict with our strict types.
|
|
40
|
+
*/
|
|
41
|
+
export type InputElementProps = Omit<InputHTMLAttributes<HTMLInputElement>, keyof InputProps | "size" | "type"> & InputProps;
|
|
42
|
+
export declare const Input: React.ForwardRefExoticComponent<InputElementProps & React.RefAttributes<HTMLInputElement>>;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=Input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/components/input/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAKpB,OAAO,KAAK,EAAE,EAAc,KAAK,mBAAmB,EAAE,MAAM,OAAO,CAAA;AAEnE,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,CAAA;AAEnC,MAAM,MAAM,SAAS,GACjB,OAAO,GACP,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,KAAK,GACL,MAAM,GACN,KAAK,CAAA;AAET,UAAU,cAAc;IACtB,qEAAqE;IACrE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,+BAA+B;IAC/B,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,iDAAiD;IACjD,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAED,UAAU,qBAAsB,SAAQ,cAAc;IACpD,wEAAwE;IACxE,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,2CAA2C;IAC3C,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;CACvB;AAED,UAAU,oBAAqB,SAAQ,cAAc;IACnD,wEAAwE;IACxE,SAAS,EAAE,IAAI,CAAA;IACf,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAA;CACd;AAED,UAAU,uBAAwB,SAAQ,cAAc;IACtD,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;AAED,MAAM,MAAM,UAAU,GAClB,uBAAuB,GACvB,oBAAoB,GACpB,qBAAqB,CAAA;AAEzB;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,CACnC,GACC,UAAU,CAAA;AAEZ,eAAO,MAAM,KAAK,4FAmFjB,CAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import Icon from '../../utilities/Icon.js';
|
|
2
|
+
import { useId } from '../../utilities/useId.js';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
import React, { forwardRef } from 'react';
|
|
5
|
+
|
|
6
|
+
const Input = forwardRef(function Input({ "aria-label": ariaLabel, autoComplete, autoWidth, className, description, hideLabel, id, invalid, label, onFocus, selectTextOnFocus, size = "md", type = "text", ...restProps }, ref) {
|
|
7
|
+
const combinedClassName = classNames("tds-input", {
|
|
8
|
+
"tds-input--auto-width": autoWidth,
|
|
9
|
+
"tds-input--invalid": invalid,
|
|
10
|
+
"tds-input--lg": size === "lg",
|
|
11
|
+
}, className);
|
|
12
|
+
const stableId = useId();
|
|
13
|
+
const inputId = id || `tds-input-${stableId}`;
|
|
14
|
+
const descriptionId = description ? `${inputId}-description` : undefined;
|
|
15
|
+
const autoCompleteBlockingProps = autoComplete === "off"
|
|
16
|
+
? {
|
|
17
|
+
"data-1p-ignore": true,
|
|
18
|
+
"data-bwignore": true,
|
|
19
|
+
"data-form-type": "other",
|
|
20
|
+
"data-lpignore": true,
|
|
21
|
+
}
|
|
22
|
+
: {};
|
|
23
|
+
const handleFocus = selectTextOnFocus
|
|
24
|
+
? (event) => {
|
|
25
|
+
try {
|
|
26
|
+
event.currentTarget.select();
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// Some input types (e.g. number) do not support text selection.
|
|
30
|
+
}
|
|
31
|
+
onFocus?.(event);
|
|
32
|
+
}
|
|
33
|
+
: onFocus;
|
|
34
|
+
return (React.createElement("div", { className: combinedClassName },
|
|
35
|
+
!hideLabel && label ? React.createElement("label", { htmlFor: inputId }, label) : null,
|
|
36
|
+
React.createElement("input", { ...restProps, ...autoCompleteBlockingProps, "aria-describedby": descriptionId, "aria-invalid": invalid || undefined, "aria-label": hideLabel ? ariaLabel || label : ariaLabel, autoComplete: autoComplete, id: inputId, onFocus: handleFocus, ref: ref, type: type }),
|
|
37
|
+
description && (React.createElement("p", { className: "tds-input-description", id: descriptionId },
|
|
38
|
+
React.createElement(Icon, { "aria-hidden": true, className: "tds-input-description-invalid-icon", symbol: "general#exclamation-triangle" }),
|
|
39
|
+
description))));
|
|
40
|
+
});
|
|
41
|
+
Input.displayName = "Input";
|
|
42
|
+
|
|
43
|
+
export { Input };
|
|
44
|
+
//# sourceMappingURL=Input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Input.js","sources":["../../../src/components/input/Input.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport Icon from \"@utilities/Icon\"\nimport { useId } from \"@utilities/useId\"\nimport classNames from \"classnames\"\nimport React, { forwardRef, type InputHTMLAttributes } from \"react\"\n\nexport type InputSize = \"lg\" | \"md\"\n\nexport type InputType =\n | \"email\"\n | \"number\"\n | \"password\"\n | \"search\"\n | \"tel\"\n | \"text\"\n | \"url\"\n\ninterface InputBaseProps {\n /** If true, the input width grows to fit content (inline editing) */\n autoWidth?: boolean\n /** Helper text below the input. Red when invalid. */\n description?: string\n /** Triggers invalid state (red border, red description) */\n invalid?: boolean\n /** Highlights all text when the field receives focus */\n selectTextOnFocus?: boolean\n /** Visual size of the input */\n size?: InputSize\n /** Supported input types — defaults to 'text' */\n type?: InputType\n}\n\ninterface InputWithVisibleLabel extends InputBaseProps {\n /** If true, label is rendered as aria-label instead of visible label */\n hideLabel?: false\n /** Label text displayed above the input */\n label: React.ReactNode\n}\n\ninterface InputWithHiddenLabel extends InputBaseProps {\n /** If true, label is rendered as aria-label instead of visible label */\n hideLabel: true\n /** Label text used as aria-label (must be string when hidden) */\n label: string\n}\n\ninterface InputWithAriaLabelledBy extends InputBaseProps {\n \"aria-labelledby\": string\n hideLabel?: never\n label?: never\n}\n\nexport type InputProps =\n | InputWithAriaLabelledBy\n | InputWithHiddenLabel\n | InputWithVisibleLabel\n\n/**\n * Combines standard HTML input attributes with custom Input props.\n * Omits 'size' and 'type' from HTML attributes to avoid conflict with our strict types.\n */\nexport type InputElementProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n keyof InputProps | \"size\" | \"type\"\n> &\n InputProps\n\nexport const Input = forwardRef<HTMLInputElement, InputElementProps>(\n function Input(\n {\n \"aria-label\": ariaLabel,\n autoComplete,\n autoWidth,\n className,\n description,\n hideLabel,\n id,\n invalid,\n label,\n onFocus,\n selectTextOnFocus,\n size = \"md\",\n type = \"text\",\n ...restProps\n }: InputElementProps,\n ref\n ) {\n const combinedClassName = classNames(\n \"tds-input\",\n {\n \"tds-input--auto-width\": autoWidth,\n \"tds-input--invalid\": invalid,\n \"tds-input--lg\": size === \"lg\",\n },\n className\n )\n\n const stableId = useId()\n const inputId = id || `tds-input-${stableId}`\n const descriptionId = description ? `${inputId}-description` : undefined\n\n const autoCompleteBlockingProps =\n autoComplete === \"off\"\n ? {\n \"data-1p-ignore\": true,\n \"data-bwignore\": true,\n \"data-form-type\": \"other\",\n \"data-lpignore\": true,\n }\n : {}\n\n const handleFocus = selectTextOnFocus\n ? (event: React.FocusEvent<HTMLInputElement>) => {\n try {\n event.currentTarget.select()\n } catch {\n // Some input types (e.g. number) do not support text selection.\n }\n onFocus?.(event)\n }\n : onFocus\n\n return (\n <div className={combinedClassName}>\n {!hideLabel && label ? <label htmlFor={inputId}>{label}</label> : null}\n <input\n {...restProps}\n {...autoCompleteBlockingProps}\n aria-describedby={descriptionId}\n aria-invalid={invalid || undefined}\n aria-label={hideLabel ? ariaLabel || (label as string) : ariaLabel}\n autoComplete={autoComplete}\n id={inputId}\n onFocus={handleFocus}\n ref={ref}\n type={type}\n />\n {description && (\n <p className=\"tds-input-description\" id={descriptionId}>\n <Icon\n aria-hidden\n className=\"tds-input-description-invalid-icon\"\n symbol=\"general#exclamation-triangle\"\n />\n {description}\n </p>\n )}\n </div>\n )\n }\n)\n\nInput.displayName = \"Input\"\n"],"names":[],"mappings":";;;;;MAoEa,KAAK,GAAG,UAAU,CAC7B,SAAS,KAAK,CACZ,EACE,YAAY,EAAE,SAAS,EACvB,YAAY,EACZ,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,EAAE,EACF,OAAO,EACP,KAAK,EACL,OAAO,EACP,iBAAiB,EACjB,IAAI,GAAG,IAAI,EACX,IAAI,GAAG,MAAM,EACb,GAAG,SAAS,EACM,EACpB,GAAG,EAAA;AAEH,IAAA,MAAM,iBAAiB,GAAG,UAAU,CAClC,WAAW,EACX;AACE,QAAA,uBAAuB,EAAE,SAAS;AAClC,QAAA,oBAAoB,EAAE,OAAO;QAC7B,eAAe,EAAE,IAAI,KAAK,IAAI;KAC/B,EACD,SAAS,CACV;AAED,IAAA,MAAM,QAAQ,GAAG,KAAK,EAAE;AACxB,IAAA,MAAM,OAAO,GAAG,EAAE,IAAI,CAAA,UAAA,EAAa,QAAQ,EAAE;AAC7C,IAAA,MAAM,aAAa,GAAG,WAAW,GAAG,CAAA,EAAG,OAAO,CAAA,YAAA,CAAc,GAAG,SAAS;AAExE,IAAA,MAAM,yBAAyB,GAC7B,YAAY,KAAK;AACf,UAAE;AACE,YAAA,gBAAgB,EAAE,IAAI;AACtB,YAAA,eAAe,EAAE,IAAI;AACrB,YAAA,gBAAgB,EAAE,OAAO;AACzB,YAAA,eAAe,EAAE,IAAI;AACtB;UACD,EAAE;IAER,MAAM,WAAW,GAAG;AAClB,UAAE,CAAC,KAAyC,KAAI;AAC5C,YAAA,IAAI;AACF,gBAAA,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE;YAC9B;AAAE,YAAA,MAAM;;YAER;AACA,YAAA,OAAO,GAAG,KAAK,CAAC;QAClB;UACA,OAAO;AAEX,IAAA,QACE,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,iBAAiB,EAAA;AAC9B,QAAA,CAAC,SAAS,IAAI,KAAK,GAAG,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,EAAO,OAAO,EAAE,OAAO,IAAG,KAAK,CAAS,GAAG,IAAI;AACtE,QAAA,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,EAAA,GACM,SAAS,EAAA,GACT,yBAAyB,sBACX,aAAa,EAAA,cAAA,EACjB,OAAO,IAAI,SAAS,EAAA,YAAA,EACtB,SAAS,GAAG,SAAS,IAAK,KAAgB,GAAG,SAAS,EAClE,YAAY,EAAE,YAAY,EAC1B,EAAE,EAAE,OAAO,EACX,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,IAAI,EAAA,CACV;QACD,WAAW,KACV,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAG,SAAS,EAAC,uBAAuB,EAAC,EAAE,EAAE,aAAa,EAAA;YACpD,KAAA,CAAA,aAAA,CAAC,IAAI,yBAEH,SAAS,EAAC,oCAAoC,EAC9C,MAAM,EAAC,8BAA8B,EAAA,CACrC;AACD,YAAA,WAAW,CACV,CACL,CACG;AAEV,CAAC;AAGH,KAAK,CAAC,WAAW,GAAG,OAAO;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/input/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAEpB,YAAY,EACV,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,SAAS,GACV,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import "./index.css";
|
|
2
|
+
import React, { type TextareaHTMLAttributes } from "react";
|
|
3
|
+
export type TextAreaResize = "auto" | "none" | "vertical";
|
|
4
|
+
export type TextAreaSize = "lg" | "md";
|
|
5
|
+
interface TextAreaBaseProps {
|
|
6
|
+
/** Helper text displayed below the field. Styles as error text when `invalid` is true. */
|
|
7
|
+
description?: string;
|
|
8
|
+
/** If true, applies error styling to border and description. */
|
|
9
|
+
invalid?: boolean;
|
|
10
|
+
/** Controls resize behavior. Defaults to `'vertical'`. */
|
|
11
|
+
resize?: TextAreaResize;
|
|
12
|
+
/** Specifies visible height in lines. Defaults to `3`. */
|
|
13
|
+
rows?: number;
|
|
14
|
+
/** Controls spacing and font size. Defaults to `'md'`. */
|
|
15
|
+
size?: TextAreaSize;
|
|
16
|
+
}
|
|
17
|
+
interface TextAreaWithVisibleLabel extends TextAreaBaseProps {
|
|
18
|
+
/** If true, label is rendered as aria-label instead of visible label */
|
|
19
|
+
hideLabel?: false;
|
|
20
|
+
/** Label text displayed above the textarea */
|
|
21
|
+
label: React.ReactNode;
|
|
22
|
+
}
|
|
23
|
+
interface TextAreaWithHiddenLabel extends TextAreaBaseProps {
|
|
24
|
+
/** If true, label is rendered as aria-label instead of visible label */
|
|
25
|
+
hideLabel: true;
|
|
26
|
+
/** Label text used as aria-label (must be string when hidden) */
|
|
27
|
+
label: string;
|
|
28
|
+
}
|
|
29
|
+
interface TextAreaWithAriaLabelledBy extends TextAreaBaseProps {
|
|
30
|
+
"aria-labelledby": string;
|
|
31
|
+
hideLabel?: never;
|
|
32
|
+
label?: never;
|
|
33
|
+
}
|
|
34
|
+
export type TextAreaCustomProps = TextAreaWithAriaLabelledBy | TextAreaWithHiddenLabel | TextAreaWithVisibleLabel;
|
|
35
|
+
export type TextAreaProps = Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, keyof TextAreaCustomProps | "rows"> & TextAreaCustomProps;
|
|
36
|
+
export declare const TextArea: React.ForwardRefExoticComponent<TextAreaProps & React.RefAttributes<HTMLTextAreaElement>>;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=TextArea.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TextArea.d.ts","sourceRoot":"","sources":["../../../src/components/textarea/TextArea.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAKpB,OAAO,KAAK,EAAE,EAAc,KAAK,sBAAsB,EAAE,MAAM,OAAO,CAAA;AAEtE,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAA;AAEzD,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,CAAA;AAEtC,UAAU,iBAAiB;IACzB,0FAA0F;IAC1F,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gEAAgE;IAChE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0DAA0D;IAC1D,IAAI,CAAC,EAAE,YAAY,CAAA;CACpB;AAED,UAAU,wBAAyB,SAAQ,iBAAiB;IAC1D,wEAAwE;IACxE,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,8CAA8C;IAC9C,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;CACvB;AAED,UAAU,uBAAwB,SAAQ,iBAAiB;IACzD,wEAAwE;IACxE,SAAS,EAAE,IAAI,CAAA;IACf,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAA;CACd;AAED,UAAU,0BAA2B,SAAQ,iBAAiB;IAC5D,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;AAED,MAAM,MAAM,mBAAmB,GAC3B,0BAA0B,GAC1B,uBAAuB,GACvB,wBAAwB,CAAA;AAE5B,MAAM,MAAM,aAAa,GAAG,IAAI,CAC9B,sBAAsB,CAAC,mBAAmB,CAAC,EAC3C,MAAM,mBAAmB,GAAG,MAAM,CACnC,GACC,mBAAmB,CAAA;AAErB,eAAO,MAAM,QAAQ,2FA4DpB,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import Icon from '../../utilities/Icon.js';
|
|
2
|
+
import { useId } from '../../utilities/useId.js';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
import React, { forwardRef } from 'react';
|
|
5
|
+
|
|
6
|
+
const TextArea = forwardRef(function TextArea({ "aria-label": ariaLabel, className, description, hideLabel, id, invalid, label, resize = "vertical", rows = 3, size = "md", ...restProps }, ref) {
|
|
7
|
+
const combinedClassName = classNames("tds-textarea", {
|
|
8
|
+
"tds-textarea--invalid": invalid,
|
|
9
|
+
"tds-textarea--lg": size === "lg",
|
|
10
|
+
"tds-textarea--resize-auto": resize === "auto",
|
|
11
|
+
"tds-textarea--resize-none": resize === "none",
|
|
12
|
+
"tds-textarea--resize-vertical": resize === "vertical",
|
|
13
|
+
}, className);
|
|
14
|
+
const stableId = useId();
|
|
15
|
+
const textareaId = id || `tds-textarea-${stableId}`;
|
|
16
|
+
const descriptionId = description ? `${textareaId}-description` : undefined;
|
|
17
|
+
return (React.createElement("div", { className: combinedClassName },
|
|
18
|
+
!hideLabel && label ? (React.createElement("label", { htmlFor: textareaId }, label)) : null,
|
|
19
|
+
React.createElement("textarea", { ...restProps, "aria-describedby": descriptionId, "aria-invalid": invalid || undefined, "aria-label": hideLabel ? ariaLabel || label : ariaLabel, id: textareaId, ref: ref, rows: rows }),
|
|
20
|
+
description && (React.createElement("p", { className: "tds-textarea-description", id: descriptionId },
|
|
21
|
+
React.createElement(Icon, { "aria-hidden": true, className: "tds-textarea-description-invalid-icon", symbol: "general#exclamation-triangle" }),
|
|
22
|
+
description))));
|
|
23
|
+
});
|
|
24
|
+
TextArea.displayName = "TextArea";
|
|
25
|
+
|
|
26
|
+
export { TextArea };
|
|
27
|
+
//# sourceMappingURL=TextArea.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TextArea.js","sources":["../../../src/components/textarea/TextArea.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport Icon from \"@utilities/Icon\"\nimport { useId } from \"@utilities/useId\"\nimport classNames from \"classnames\"\nimport React, { forwardRef, type TextareaHTMLAttributes } from \"react\"\n\nexport type TextAreaResize = \"auto\" | \"none\" | \"vertical\"\n\nexport type TextAreaSize = \"lg\" | \"md\"\n\ninterface TextAreaBaseProps {\n /** Helper text displayed below the field. Styles as error text when `invalid` is true. */\n description?: string\n /** If true, applies error styling to border and description. */\n invalid?: boolean\n /** Controls resize behavior. Defaults to `'vertical'`. */\n resize?: TextAreaResize\n /** Specifies visible height in lines. Defaults to `3`. */\n rows?: number\n /** Controls spacing and font size. Defaults to `'md'`. */\n size?: TextAreaSize\n}\n\ninterface TextAreaWithVisibleLabel extends TextAreaBaseProps {\n /** If true, label is rendered as aria-label instead of visible label */\n hideLabel?: false\n /** Label text displayed above the textarea */\n label: React.ReactNode\n}\n\ninterface TextAreaWithHiddenLabel extends TextAreaBaseProps {\n /** If true, label is rendered as aria-label instead of visible label */\n hideLabel: true\n /** Label text used as aria-label (must be string when hidden) */\n label: string\n}\n\ninterface TextAreaWithAriaLabelledBy extends TextAreaBaseProps {\n \"aria-labelledby\": string\n hideLabel?: never\n label?: never\n}\n\nexport type TextAreaCustomProps =\n | TextAreaWithAriaLabelledBy\n | TextAreaWithHiddenLabel\n | TextAreaWithVisibleLabel\n\nexport type TextAreaProps = Omit<\n TextareaHTMLAttributes<HTMLTextAreaElement>,\n keyof TextAreaCustomProps | \"rows\"\n> &\n TextAreaCustomProps\n\nexport const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(\n function TextArea(\n {\n \"aria-label\": ariaLabel,\n className,\n description,\n hideLabel,\n id,\n invalid,\n label,\n resize = \"vertical\",\n rows = 3,\n size = \"md\",\n ...restProps\n }: TextAreaProps,\n ref\n ) {\n const combinedClassName = classNames(\n \"tds-textarea\",\n {\n \"tds-textarea--invalid\": invalid,\n \"tds-textarea--lg\": size === \"lg\",\n \"tds-textarea--resize-auto\": resize === \"auto\",\n \"tds-textarea--resize-none\": resize === \"none\",\n \"tds-textarea--resize-vertical\": resize === \"vertical\",\n },\n className\n )\n\n const stableId = useId()\n const textareaId = id || `tds-textarea-${stableId}`\n const descriptionId = description ? `${textareaId}-description` : undefined\n\n return (\n <div className={combinedClassName}>\n {!hideLabel && label ? (\n <label htmlFor={textareaId}>{label}</label>\n ) : null}\n <textarea\n {...restProps}\n aria-describedby={descriptionId}\n aria-invalid={invalid || undefined}\n aria-label={hideLabel ? ariaLabel || (label as string) : ariaLabel}\n id={textareaId}\n ref={ref}\n rows={rows}\n />\n {description && (\n <p className=\"tds-textarea-description\" id={descriptionId}>\n <Icon\n aria-hidden\n className=\"tds-textarea-description-invalid-icon\"\n symbol=\"general#exclamation-triangle\"\n />\n {description}\n </p>\n )}\n </div>\n )\n }\n)\n\nTextArea.displayName = \"TextArea\"\n"],"names":[],"mappings":";;;;;AAuDO,MAAM,QAAQ,GAAG,UAAU,CAChC,SAAS,QAAQ,CACf,EACE,YAAY,EAAE,SAAS,EACvB,SAAS,EACT,WAAW,EACX,SAAS,EACT,EAAE,EACF,OAAO,EACP,KAAK,EACL,MAAM,GAAG,UAAU,EACnB,IAAI,GAAG,CAAC,EACR,IAAI,GAAG,IAAI,EACX,GAAG,SAAS,EACE,EAChB,GAAG,EAAA;AAEH,IAAA,MAAM,iBAAiB,GAAG,UAAU,CAClC,cAAc,EACd;AACE,QAAA,uBAAuB,EAAE,OAAO;QAChC,kBAAkB,EAAE,IAAI,KAAK,IAAI;QACjC,2BAA2B,EAAE,MAAM,KAAK,MAAM;QAC9C,2BAA2B,EAAE,MAAM,KAAK,MAAM;QAC9C,+BAA+B,EAAE,MAAM,KAAK,UAAU;KACvD,EACD,SAAS,CACV;AAED,IAAA,MAAM,QAAQ,GAAG,KAAK,EAAE;AACxB,IAAA,MAAM,UAAU,GAAG,EAAE,IAAI,CAAA,aAAA,EAAgB,QAAQ,EAAE;AACnD,IAAA,MAAM,aAAa,GAAG,WAAW,GAAG,CAAA,EAAG,UAAU,CAAA,YAAA,CAAc,GAAG,SAAS;AAE3E,IAAA,QACE,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,iBAAiB,EAAA;AAC9B,QAAA,CAAC,SAAS,IAAI,KAAK,IAClB,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,EAAO,OAAO,EAAE,UAAU,IAAG,KAAK,CAAS,IACzC,IAAI;AACR,QAAA,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAA,GACM,SAAS,EAAA,kBAAA,EACK,aAAa,EAAA,cAAA,EACjB,OAAO,IAAI,SAAS,EAAA,YAAA,EACtB,SAAS,GAAG,SAAS,IAAK,KAAgB,GAAG,SAAS,EAClE,EAAE,EAAE,UAAU,EACd,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,IAAI,EAAA,CACV;QACD,WAAW,KACV,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAG,SAAS,EAAC,0BAA0B,EAAC,EAAE,EAAE,aAAa,EAAA;YACvD,KAAA,CAAA,aAAA,CAAC,IAAI,yBAEH,SAAS,EAAC,uCAAuC,EACjD,MAAM,EAAC,8BAA8B,EAAA,CACrC;AACD,YAAA,WAAW,CACV,CACL,CACG;AAEV,CAAC;AAGH,QAAQ,CAAC,WAAW,GAAG,UAAU;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/textarea/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAEpB,YAAY,EACV,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,YAAY,GACb,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA"}
|