From 368a8dce660f5e02f838bdeda907699bae27c2bb Mon Sep 17 00:00:00 2001 From: Vincent Valentin Date: Fri, 6 Sep 2024 11:29:02 +0200 Subject: [PATCH] [Textarea] Add autoResize and scrollIntoView options --- .../textarea-input.component.html | 7 +++- .../textarea-input.component.ts | 21 +++++++++- .../src/components/textField/component.scss | 1 + .../scss/src/components/textField/index.scss | 4 ++ .../scss/src/components/textField/mods.scss | 25 ++++++++++++ ...ea.stories.ts => textareafield.stories.ts} | 20 ++++++---- .../html&css/textareafield.stories.ts | 40 ++++++++++++++++--- 7 files changed, 103 insertions(+), 15 deletions(-) rename stories/documentation/forms/fields/textarea/angular/{textarea.stories.ts => textareafield.stories.ts} (79%) diff --git a/packages/ng/forms/textarea-input/textarea-input.component.html b/packages/ng/forms/textarea-input/textarea-input.component.html index bf1d83b363..965af4d71a 100644 --- a/packages/ng/forms/textarea-input/textarea-input.component.html +++ b/packages/ng/forms/textarea-input/textarea-input.component.html @@ -1,11 +1,16 @@ -
+
+ @if (autoResize) { + + }
diff --git a/packages/ng/forms/textarea-input/textarea-input.component.ts b/packages/ng/forms/textarea-input/textarea-input.component.ts index 562061b9b9..7798881996 100644 --- a/packages/ng/forms/textarea-input/textarea-input.component.ts +++ b/packages/ng/forms/textarea-input/textarea-input.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core'; +import { booleanAttribute, ChangeDetectionStrategy, Component, ElementRef, Input, ViewChild, ViewEncapsulation } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; import { InputDirective } from '@lucca-front/ng/form-field'; import { injectNgControl } from '../inject-ng-control'; @@ -14,6 +14,9 @@ import { NoopValueAccessorDirective } from '../noop-value-accessor.directive'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class TextareaInputComponent { + @ViewChild('textarea', { read: ElementRef, static: true }) + textarea: ElementRef; + ngControl = injectNgControl(); @Input() @@ -21,4 +24,20 @@ export class TextareaInputComponent { @Input() rows?: number; + + @Input({ + transform: booleanAttribute, + }) + autoResize = false; + + @Input({ + transform: booleanAttribute, + }) + scrollIntoViewOnAutoResizing = false; + + updateScroll() { + if (this.scrollIntoViewOnAutoResizing) { + this.textarea.nativeElement.scrollIntoView(); + } + } } diff --git a/packages/scss/src/components/textField/component.scss b/packages/scss/src/components/textField/component.scss index 0b4c284fc1..67ceefcf81 100644 --- a/packages/scss/src/components/textField/component.scss +++ b/packages/scss/src/components/textField/component.scss @@ -55,6 +55,7 @@ } } + .textField-input-valueClone, .textField-input-value { border: 0; outline: 0; diff --git a/packages/scss/src/components/textField/index.scss b/packages/scss/src/components/textField/index.scss index 3ba2234d8c..3d198b2ec0 100644 --- a/packages/scss/src/components/textField/index.scss +++ b/packages/scss/src/components/textField/index.scss @@ -25,4 +25,8 @@ &:has(.textField-input-value:disabled) { @include disabled; } + + &.mod-autoResize { + @include autoResize; + } } diff --git a/packages/scss/src/components/textField/mods.scss b/packages/scss/src/components/textField/mods.scss index eb7ee35165..df507b6f6c 100644 --- a/packages/scss/src/components/textField/mods.scss +++ b/packages/scss/src/components/textField/mods.scss @@ -44,3 +44,28 @@ text-align: right; } } + +@mixin autoResize { + .textField-input { + display: grid; + align-items: normal; + min-width: 0; + } + + .textField-input-valueClone, + .textField-input-value { + white-space: pre-wrap; + overflow-wrap: break-word; + grid-area: 1 / 1 / 2 / 2; + resize: none; + min-width: 0; + } + + .textField-input-valueClone { + visibility: hidden; + + &::after { + content: ' '; + } + } +} diff --git a/stories/documentation/forms/fields/textarea/angular/textarea.stories.ts b/stories/documentation/forms/fields/textarea/angular/textareafield.stories.ts similarity index 79% rename from stories/documentation/forms/fields/textarea/angular/textarea.stories.ts rename to stories/documentation/forms/fields/textarea/angular/textareafield.stories.ts index b29f5252fa..6be6d4b882 100644 --- a/stories/documentation/forms/fields/textarea/angular/textarea.stories.ts +++ b/stories/documentation/forms/fields/textarea/angular/textareafield.stories.ts @@ -35,15 +35,22 @@ export default { counter: { description: '[v17.4]', }, + autoResize: { + type: 'boolean', + }, + scrollIntoViewOnAutoResizing: { + type: 'boolean', + if: { arg: 'autoResize', truthy: true }, + }, hiddenLabel: { - description: 'Masque le label en le conservant dans le DOM pour les lecteurs d\'écrans', + description: "Masque le label en le conservant dans le DOM pour les lecteurs d'écrans", }, }, } as Meta; export const Basic: StoryObj = { render: (args, { argTypes }) => { - const { label, hiddenLabel, tooltip, inlineMessage, inlineMessageState, size, counter, ...inputArgs } = args; + const { label, hiddenLabel, tooltip, inlineMessage, inlineMessageState, size, counter, autoResize, scrollIntoViewOnAutoResizing, ...inputArgs } = args; return { template: cleanupTemplate(` - - - - -{{example}}`), +`), moduleMetadata: { imports: [TextareaInputComponent, FormFieldComponent, FormsModule, BrowserAnimationsModule], }, @@ -81,6 +85,8 @@ export const Basic: StoryObj
' : ''; + let input = ''; + if (args.autoResize) { + if (args.scrollIntoViewOnAutoResizing) { + input = 'onInput="this.previousElementSibling.dataset.contentBefore = this.value; this.scrollIntoViewOnAutoResizing"'; + } else { + input = 'onInput="this.previousElementSibling.dataset.contentBefore = this.value"'; + } + } + return `
-
+
- + ${clone} +

- Helper text + Helper Text

`; @@ -30,4 +55,7 @@ const Template: StoryFn = (args) => ({ }); export const Basic = Template.bind({}); -Basic.args = {}; +Basic.args = { + autoResize: false, + scrollIntoViewOnAutoResizing: false, +};