@fluid-topics/ftds-text-area 0.0.0-stage → 2.2.41

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/README.md CHANGED
@@ -1,3 +1,26 @@
1
- # Temporary Holding Version
1
+ Design system text-area
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ ## Install
4
+
5
+ ```shell
6
+ npm install @fluid-topics/ftds-text-area
7
+ yarn add @fluid-topics/ftds-text-area
8
+ ```
9
+
10
+ ## Usage
11
+
12
+ ```typescript
13
+ import { html } from "lit"
14
+ import "@fluid-topics/ftds-text-area"
15
+
16
+ function render() {
17
+ return html`
18
+ <ftds-text-area
19
+ label="Description"
20
+ value="Some text"
21
+ helperText="Describe your content in a few words"
22
+ height="150"
23
+ ></ftds-text-area>
24
+ `
25
+ }
26
+ ```
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import { customElements } from "@fluid-topics/ft-wc-utils";
2
+ import definitions from "./definitions";
3
+ customElements(definitions);
@@ -0,0 +1,5 @@
1
+ import { FtdsTextArea } from "./ftds-text-area";
2
+ declare const _default: {
3
+ "ftds-text-area": typeof FtdsTextArea;
4
+ };
5
+ export default _default;
@@ -0,0 +1,4 @@
1
+ import { FtdsTextArea } from "./ftds-text-area";
2
+ export default {
3
+ "ftds-text-area": FtdsTextArea,
4
+ };
@@ -0,0 +1,29 @@
1
+ import { PropertyValues } from "lit";
2
+ import { ElementDefinitionsMap, FtdsBase } from "@fluid-topics/ft-wc-utils";
3
+ import { FtdsTextAreaProperties } from "./ftds-text-area.properties";
4
+ declare const FtdsTextArea_base: typeof FtdsBase & import("@fluid-topics/ft-wc-utils").Constructor<import("@fluid-topics/ft-wc-utils").FtInputInterface<string>> & import("@fluid-topics/ft-wc-utils").Constructor<import("@fluid-topics/ft-i18n").FtLitElementWithI18nInterface>;
5
+ export declare class FtdsTextArea extends FtdsTextArea_base implements FtdsTextAreaProperties {
6
+ static elementDefinitions: ElementDefinitionsMap;
7
+ static styles: import("lit").CSSResult[];
8
+ height?: number;
9
+ private fittedHeight;
10
+ private textarea?;
11
+ private baseInput?;
12
+ private scrollbarWidth;
13
+ private pendingHeightFit;
14
+ constructor();
15
+ protected willUpdate(changedProperties: PropertyValues): void;
16
+ focus(): void;
17
+ onInput(): void;
18
+ protected render(): import("lit").TemplateResult<1>;
19
+ protected firstUpdated(changedProperties: PropertyValues): void;
20
+ protected updated(changedProperties: PropertyValues): void;
21
+ private get fieldHeight();
22
+ private measureScrollbar;
23
+ private get insideStructure();
24
+ private fitHeightToContent;
25
+ private clampHeight;
26
+ private onKeyDown;
27
+ private onResize;
28
+ }
29
+ export {};
@@ -0,0 +1,179 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { html, } from "lit";
8
+ import { query, state, } from "lit/decorators.js";
9
+ import { FtdsBase, ignoreComposingEvents, numberProperty, Status, toFtInput, } from "@fluid-topics/ft-wc-utils";
10
+ import { scrollbarWidthCssVariable, styles, } from "./ftds-text-area.styles";
11
+ import { FtdsTypography } from "@fluid-topics/ftds-typography";
12
+ import { FtResizer, } from "@fluid-topics/ft-resizer";
13
+ import { withI18n } from "@fluid-topics/ft-i18n";
14
+ import { DesignSystemSize } from "@fluid-topics/design-system-variables";
15
+ import { ifDefined } from "lit/directives/if-defined.js";
16
+ import { classMap } from "lit/directives/class-map.js";
17
+ import { FtdsBaseInput } from "@fluid-topics/ftds-base-input";
18
+ export class FtdsTextArea extends withI18n(toFtInput(FtdsBase)) {
19
+ constructor() {
20
+ var _a;
21
+ super();
22
+ this.fittedHeight = 0;
23
+ this.scrollbarWidth = 0;
24
+ this.pendingHeightFit = false;
25
+ this.value = (_a = this.value) !== null && _a !== void 0 ? _a : "";
26
+ }
27
+ willUpdate(changedProperties) {
28
+ var _a;
29
+ super.willUpdate(changedProperties);
30
+ this.value = (_a = this.value) !== null && _a !== void 0 ? _a : "";
31
+ }
32
+ focus() {
33
+ var _a;
34
+ (_a = this.textarea) === null || _a === void 0 ? void 0 : _a.focus();
35
+ }
36
+ onInput() {
37
+ var _a;
38
+ this.value = ((_a = this.textarea) === null || _a === void 0 ? void 0 : _a.value) || "";
39
+ super.onInput();
40
+ }
41
+ render() {
42
+ return html `
43
+ <style>
44
+ ftds-base-input::part(inside-structure) {
45
+ height: ${this.fieldHeight}px;
46
+ }
47
+ </style>
48
+ <ftds-base-input
49
+ .status=${this.status}
50
+ .size=${DesignSystemSize.large}
51
+ ?disabled=${this.disabled}
52
+
53
+ .errorMessages=${this.errorMessages}
54
+ .warningMessages=${this.warningMessages}
55
+ .helperText=${this.helperText}
56
+
57
+ .label=${ifDefined(this.label)}
58
+ ?raiseLabel=${this.focused || !!this.value}
59
+ >
60
+ <textarea
61
+ class="${classMap({ "ftds-text-area--with-scrollbar": this.scrollbarWidth > 0 })}"
62
+ name="${this.name}"
63
+ .value=${this.value}
64
+ ?disabled=${this.disabled}
65
+ @input=${this.onInput}
66
+ @focus=${this.onFocus}
67
+ @blur=${this.onBlur}
68
+ @keydown=${this.onKeyDown}
69
+ aria-label="${ifDefined(this.label)}"
70
+ aria-invalid="${this.status === Status.error}"
71
+ aria-describedby="${this.messagesForScreenReaderElementId}"
72
+ ></textarea>
73
+ ${this.renderMessagesForScreenReader()}
74
+ <ft-resizer
75
+ style="${scrollbarWidthCssVariable.set(`${this.scrollbarWidth}px`)}"
76
+ @resize=${this.onResize}
77
+ @click=${(e) => e.stopPropagation()}
78
+ initialHeight="${this.fieldHeight}"
79
+ cursor="ns-resize"
80
+ ariaLabel="Resize text area">
81
+ </ft-resizer>
82
+ </ftds-base-input>
83
+ `;
84
+ }
85
+ firstUpdated(changedProperties) {
86
+ super.firstUpdated(changedProperties);
87
+ this.fitHeightToContent();
88
+ new ResizeObserver(() => this.measureScrollbar()).observe(this.textarea);
89
+ new ResizeObserver(() => {
90
+ if (this.pendingHeightFit) {
91
+ this.fitHeightToContent();
92
+ }
93
+ }).observe(this);
94
+ }
95
+ updated(changedProperties) {
96
+ super.updated(changedProperties);
97
+ this.measureScrollbar();
98
+ if (changedProperties.has("height") || (changedProperties.has("value") && !this.focused && this.height === undefined)) {
99
+ this.fitHeightToContent();
100
+ }
101
+ }
102
+ get fieldHeight() {
103
+ var _a;
104
+ return (_a = this.height) !== null && _a !== void 0 ? _a : this.fittedHeight;
105
+ }
106
+ measureScrollbar() {
107
+ this.scrollbarWidth = this.textarea ? this.textarea.offsetWidth - this.textarea.clientWidth : 0;
108
+ }
109
+ get insideStructure() {
110
+ var _a, _b;
111
+ return (_b = (_a = this.baseInput) === null || _a === void 0 ? void 0 : _a.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector("[part~=inside-structure]");
112
+ }
113
+ async fitHeightToContent() {
114
+ var _a;
115
+ await ((_a = this.baseInput) === null || _a === void 0 ? void 0 : _a.updateComplete);
116
+ const insideStructure = this.insideStructure;
117
+ if (!insideStructure || !this.textarea) {
118
+ return;
119
+ }
120
+ if (insideStructure.offsetHeight === 0) {
121
+ // Hidden (e.g. inside a closed modal): fit once visible
122
+ this.pendingHeightFit = true;
123
+ return;
124
+ }
125
+ this.pendingHeightFit = false;
126
+ if (this.height !== undefined) {
127
+ this.height = this.clampHeight(this.height);
128
+ return;
129
+ }
130
+ const containerHeight = insideStructure.offsetHeight - this.textarea.clientHeight;
131
+ const previousHeight = this.textarea.style.height;
132
+ this.textarea.style.height = "0px";
133
+ const contentHeight = this.textarea.scrollHeight;
134
+ this.textarea.style.height = previousHeight;
135
+ this.fittedHeight = this.clampHeight(containerHeight + contentHeight);
136
+ }
137
+ clampHeight(height) {
138
+ var _a, _b;
139
+ const style = this.insideStructure ? getComputedStyle(this.insideStructure) : undefined;
140
+ const minHeight = parseFloat((_a = style === null || style === void 0 ? void 0 : style.minHeight) !== null && _a !== void 0 ? _a : "") || 0;
141
+ const maxHeight = parseFloat((_b = style === null || style === void 0 ? void 0 : style.maxHeight) !== null && _b !== void 0 ? _b : "") || Infinity;
142
+ return Math.min(Math.max(height, minHeight), Math.max(minHeight, maxHeight));
143
+ }
144
+ onKeyDown(e) {
145
+ if (e.key === "Enter" || e.key === " ") {
146
+ e.stopPropagation();
147
+ }
148
+ }
149
+ onResize(event) {
150
+ this.height = this.clampHeight(event.detail.height);
151
+ }
152
+ }
153
+ FtdsTextArea.elementDefinitions = {
154
+ "ftds-base-input": FtdsBaseInput,
155
+ "ft-resizer": FtResizer,
156
+ "ftds-typography": FtdsTypography,
157
+ };
158
+ // language=CSS
159
+ FtdsTextArea.styles = [
160
+ styles,
161
+ ];
162
+ __decorate([
163
+ numberProperty()
164
+ ], FtdsTextArea.prototype, "height", void 0);
165
+ __decorate([
166
+ state()
167
+ ], FtdsTextArea.prototype, "fittedHeight", void 0);
168
+ __decorate([
169
+ query("textarea")
170
+ ], FtdsTextArea.prototype, "textarea", void 0);
171
+ __decorate([
172
+ query("ftds-base-input")
173
+ ], FtdsTextArea.prototype, "baseInput", void 0);
174
+ __decorate([
175
+ state()
176
+ ], FtdsTextArea.prototype, "scrollbarWidth", void 0);
177
+ __decorate([
178
+ ignoreComposingEvents()
179
+ ], FtdsTextArea.prototype, "onKeyDown", null);