2021-09-07 13:46:34 +08:00
using System.Diagnostics ;
2021-03-01 22:50:22 +08:00
using System.Text.Json ;
2020-03-23 09:31:08 +08:00
using System.Threading.Tasks ;
2020-09-09 00:52:14 +08:00
using AntDesign.JsInterop ;
using Microsoft.AspNetCore.Components ;
2021-03-01 22:50:22 +08:00
using Microsoft.JSInterop ;
2020-03-23 09:31:08 +08:00
2020-05-29 00:33:49 +08:00
namespace AntDesign
2020-03-23 09:31:08 +08:00
{
2020-06-27 01:20:52 +08:00
public partial class TextArea : Input < string >
2020-03-23 09:31:08 +08:00
{
2020-04-16 12:05:59 +08:00
private const uint DEFAULT_MIN_ROWS = 1 ;
2020-04-24 18:32:50 +08:00
2021-04-17 17:42:28 +08:00
protected override string InputType = > "textarea" ;
2020-03-31 21:23:25 +08:00
/// <summary>
/// scrollHeight of 1 row
/// </summary>
private double _rowHeight ;
/// <summary>
2020-04-16 12:05:59 +08:00
/// total height = row * <see cref="_rowHeight" /> + <see cref="_offsetHeight" />
2020-03-31 21:23:25 +08:00
/// </summary>
private double _offsetHeight ;
2021-03-01 22:50:22 +08:00
private uint _minRows = DEFAULT_MIN_ROWS ;
private uint _maxRows = uint . MaxValue ;
private bool _hasMinOrMaxSet ;
2021-09-07 13:46:34 +08:00
private bool _hasMinSet ;
2021-03-01 22:50:22 +08:00
private DotNetObjectReference < TextArea > _reference ;
2020-03-23 09:31:08 +08:00
2021-09-07 13:46:34 +08:00
/// <summary>
/// Will adjust (grow or shrink) the `TextArea` according to content.
/// Can work in connection with `MaxRows` & `MinRows`.
/// Sets resize attribute of the textarea HTML element to: none.
/// </summary>
2020-03-23 09:31:08 +08:00
[Parameter]
2021-09-07 13:46:34 +08:00
public bool AutoSize
{
get = > _autoSize ;
set
{
if ( _hasMinOrMaxSet & & ! value )
{
Debug . WriteLine ( "AntBlazor.TextArea: AutoSize cannot be set to false when either MinRows or MaxRows has been set.AutoSize has been switched to true." ) ;
_autoSize = true ;
}
else
{
_autoSize = value ;
}
if ( _autoSize )
{
_resizeStyle = "resize: none" ;
}
else
{
_resizeStyle = "" ;
}
}
}
2020-03-23 09:31:08 +08:00
2021-05-27 18:13:26 +08:00
/// <summary>
/// When `false`, value will be set to `null` when content is empty
/// or whitespace. When `true`, value will be set to empty string.
/// </summary>
2021-04-03 15:22:11 +08:00
[Parameter]
public bool DefaultToEmptyString { get ; set ; }
2021-03-01 22:50:22 +08:00
2021-05-27 18:13:26 +08:00
/// <summary>
/// `TextArea` will allow growing, but it will stop when visible
/// rows = MaxRows (will not grow further).
/// Default value = uint.MaxValue
/// </summary>
2020-03-23 09:31:08 +08:00
[Parameter]
2021-05-27 18:13:26 +08:00
public uint MaxRows
2020-03-31 21:23:25 +08:00
{
get
{
2021-05-27 18:13:26 +08:00
return _maxRows ;
2020-03-31 21:23:25 +08:00
}
set
{
2021-03-01 22:50:22 +08:00
_hasMinOrMaxSet = true ;
2021-05-27 18:13:26 +08:00
if ( value > = MinRows )
2020-03-31 21:23:25 +08:00
{
2021-05-27 18:13:26 +08:00
_maxRows = value ;
2021-09-07 13:46:34 +08:00
Debug . WriteLineIf ( ! AutoSize , "AntBlazor.TextArea: AutoSize cannot be set to false when either MinRows or MaxRows has been set.AutoSize has been switched to true." ) ;
2020-03-31 21:23:25 +08:00
AutoSize = true ;
}
else
{
2021-05-27 18:13:26 +08:00
_maxRows = uint . MaxValue ;
2021-09-07 13:46:34 +08:00
Debug . WriteLine ( $"AntBlazor.TextArea: Value of {nameof(MaxRows)}({MaxRows}) has to be between {nameof(MinRows)}({MinRows}) and {uint.MaxValue}" ) ;
2020-03-31 21:23:25 +08:00
}
}
}
2021-05-27 18:13:26 +08:00
/// <summary>
/// `TextArea` will allow shrinking, but it will stop when visible
/// rows = MinRows (will not shrink further).
/// Default value = DEFAULT_MIN_ROWS = 1
/// </summary>
2020-03-31 21:23:25 +08:00
[Parameter]
2021-05-27 18:13:26 +08:00
public uint MinRows
2020-03-31 21:23:25 +08:00
{
get
{
2021-05-27 18:13:26 +08:00
return _minRows ;
2020-03-31 21:23:25 +08:00
}
set
{
2021-03-01 22:50:22 +08:00
_hasMinOrMaxSet = true ;
2021-09-07 13:46:34 +08:00
_hasMinSet = true ;
2021-05-27 18:13:26 +08:00
if ( value > = DEFAULT_MIN_ROWS & & value < = MaxRows )
2020-03-31 21:23:25 +08:00
{
2021-05-27 18:13:26 +08:00
_minRows = value ;
2021-09-07 13:46:34 +08:00
Debug . WriteLineIf ( ! AutoSize , "AntBlazor.TextArea: AutoSize cannot be set to false when either MinRows or MaxRows has been set.AutoSize has been switched to true." ) ;
2020-03-31 21:23:25 +08:00
AutoSize = true ;
}
else
{
2021-05-27 18:13:26 +08:00
_minRows = DEFAULT_MIN_ROWS ;
2021-09-07 13:46:34 +08:00
Debug . WriteLine ( $"AntBlazor.TextArea: Value of {nameof(MinRows)}({MinRows}) has to be between {DEFAULT_MIN_ROWS} and {nameof(MaxRows)}({MaxRows})" ) ;
2020-03-31 21:23:25 +08:00
}
}
}
2021-09-07 13:46:34 +08:00
/// <summary>
/// Sets the height of the TextArea expressed in number of rows.
/// Default value is 3.
/// </summary>
[Parameter]
public uint Rows { get ; set ; } = 3 ;
2021-05-27 18:13:26 +08:00
/// <summary>
/// Callback when the size changes
/// </summary>
2020-03-31 21:23:25 +08:00
[Parameter]
2020-07-07 12:44:10 +08:00
public EventCallback < OnResizeEventArgs > OnResize { get ; set ; }
2020-03-23 09:31:08 +08:00
2021-05-27 18:13:26 +08:00
/// <summary>
/// Show character counting.
/// </summary>
[Parameter]
public bool ShowCount
{
get = > _showCount & & MaxLength > = 0 ;
set = > _showCount = value ;
}
private bool _showCount ;
2021-03-12 17:02:11 +08:00
private ClassMapper _warpperClassMapper = new ClassMapper ( ) ;
protected override void OnInitialized ( )
{
base . OnInitialized ( ) ;
_warpperClassMapper
. Get ( ( ) = > $"{PrefixCls}-affix-wrapper" )
. Get ( ( ) = > $"{PrefixCls}-affix-wrapper-textarea-with-clear-btn" )
. GetIf ( ( ) = > $"{PrefixCls}-affix-wrapper-rtl" , ( ) = > RTL ) ;
}
2020-03-31 21:23:25 +08:00
protected async override Task OnFirstAfterRenderAsync ( )
{
await base . OnFirstAfterRenderAsync ( ) ;
if ( AutoSize )
{
2021-03-01 22:50:22 +08:00
DomEventService . AddEventListener ( "window" , "beforeunload" , Reloading , false ) ;
2020-03-31 21:23:25 +08:00
}
2021-09-07 13:46:34 +08:00
await CalculateRowHeightAsync ( ) ;
2020-03-31 21:23:25 +08:00
}
2021-04-03 15:22:11 +08:00
protected override bool TryParseValueFromString ( string value , out string result , out string validationErrorMessage )
{
2021-09-07 13:46:34 +08:00
validationErrorMessage = null ;
2021-04-03 15:22:11 +08:00
if ( string . IsNullOrWhiteSpace ( value ) )
{
if ( DefaultToEmptyString )
result = string . Empty ;
else
result = default ;
return true ;
}
2021-09-07 13:46:34 +08:00
result = value ;
return true ;
2021-04-03 15:22:11 +08:00
}
2020-03-23 09:31:08 +08:00
2021-03-01 22:50:22 +08:00
protected override void Dispose ( bool disposing )
{
if ( AutoSize & & ! _isReloading )
2020-03-23 09:31:08 +08:00
{
2021-03-01 22:50:22 +08:00
_reference ? . Dispose ( ) ;
DomEventService . RemoveEventListerner < JsonElement > ( "window" , "beforeunload" , Reloading ) ;
_ = InvokeAsync ( async ( ) = >
{
await JsInvokeAsync ( JSInteropConstants . DisposeResizeTextArea , Ref ) ;
} ) ;
2020-03-23 09:31:08 +08:00
}
2021-03-01 22:50:22 +08:00
base . Dispose ( disposing ) ;
}
/// <summary>
2021-03-12 17:02:11 +08:00
/// Indicates that a page is being refreshed
2021-03-01 22:50:22 +08:00
/// </summary>
private bool _isReloading ;
2021-09-07 13:46:34 +08:00
private bool _autoSize ;
private string _resizeStyle = "" ;
2021-03-12 17:02:11 +08:00
2021-03-01 22:50:22 +08:00
private void Reloading ( JsonElement jsonElement ) = > _isReloading = true ;
[JSInvokable]
public void ChangeSizeAsyncJs ( float width , float height )
{
2021-05-27 18:13:26 +08:00
if ( OnResize . HasDelegate )
OnResize . InvokeAsync ( new OnResizeEventArgs { Width = width , Height = height } ) ;
2020-03-23 09:31:08 +08:00
}
2021-03-01 22:50:22 +08:00
private async Task CalculateRowHeightAsync ( )
2020-03-23 09:31:08 +08:00
{
2021-03-01 22:50:22 +08:00
if ( _reference = = null )
{
_reference = DotNetObjectReference . Create < TextArea > ( this ) ;
}
2020-03-31 21:23:25 +08:00
2021-09-07 13:46:34 +08:00
uint rows = Rows ;
if ( _hasMinSet )
rows = MinRows ;
TextAreaInfo textAreaInfo ;
if ( AutoSize )
{
textAreaInfo = await JsInvokeAsync < TextAreaInfo > (
JSInteropConstants . InputComponentHelper . RegisterResizeTextArea , Ref , rows , MaxRows , _reference ) ;
}
else
{
textAreaInfo = await JsInvokeAsync < TextAreaInfo > (
JSInteropConstants . InputComponentHelper . GetTextAreaInfo , Ref ) ;
}
2021-03-01 22:50:22 +08:00
_rowHeight = textAreaInfo . LineHeight ;
2021-03-12 17:02:11 +08:00
_offsetHeight = textAreaInfo . PaddingTop + textAreaInfo . PaddingBottom
2021-03-01 22:50:22 +08:00
+ textAreaInfo . BorderTop + textAreaInfo . BorderBottom ;
2020-03-31 21:23:25 +08:00
if ( rows > MaxRows )
{
2021-09-07 13:46:34 +08:00
Style = $"height: {MaxRows * _rowHeight + _offsetHeight}px;{_resizeStyle};overflow-x: hidden" ;
2020-03-31 21:23:25 +08:00
}
else
{
2021-09-07 13:46:34 +08:00
string overflow = _autoSize ? "hidden" : "visible" ;
Style = $"height: {rows * _rowHeight + _offsetHeight}px;overflow-y: {overflow};{_resizeStyle};overflow-x: hidden" ;
2020-03-31 21:23:25 +08:00
}
2020-03-23 09:31:08 +08:00
}
2021-09-07 13:46:34 +08:00
internal class TextAreaInfo
2020-07-07 12:44:10 +08:00
{
2021-03-01 22:50:22 +08:00
public double ScrollHeight { get ; set ; }
public double LineHeight { get ; set ; }
public double PaddingTop { get ; set ; }
public double PaddingBottom { get ; set ; }
public double BorderTop { get ; set ; }
public double BorderBottom { get ; set ; }
2020-07-07 12:44:10 +08:00
}
2020-03-23 09:31:08 +08:00
}
2021-04-17 17:42:28 +08:00
}