Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

1,069 changes: 1,001 additions & 68 deletions src/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.razor.cs

Large diffs are not rendered by default.

502 changes: 400 additions & 102 deletions src/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scss

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,22 @@ namespace BitBlazorUI {
// A single line input drops the line breaks out of whatever is pasted into it, so a
// column copied out of a spreadsheet would otherwise arrive as one run-on tag. The
// breaks are turned into the first separator before the text lands, which is what the
// splitting on the .NET side then reads as a list. Without a separator there is nothing
// to express a list with, so the paste is left to the browser.
// splitting on the .NET side then reads as a list.
if (input.readOnly || input.disabled) return;

const separators = TagsInput.getSeparators(input);
if (separators.length === 0) return;

const text = e.clipboardData?.getData('text');
if (!text || !/[\r\n]/.test(text)) return;

e.preventDefault();

const value = text.replace(/(\r\n|[\r\n])+/g, separators[0]);
// Without a separator there is nothing to express a list with, so the lines cannot become
// tags of their own - but they must not be run together into one word either, which is
// what a single line input does with the breaks it drops. They are joined by a space, so
// what lands is the text that was copied rather than "firstsecond".
const separators = TagsInput.getSeparators(input);
const joiner = separators.length > 0 ? separators[0] : ' ';

const value = text.replace(/(\r\n|[\r\n])+/g, joiner);

// insertText keeps the caret, the selection it replaces and the undo stack of the field
// intact, and raises the input event that the component listens to. It is a deprecated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ namespace Bit.BlazorUI;
public class BitTagsInputBeforeArgs
{
/// <summary>
/// The tag text being added or removed.
/// The tag text being added or removed, after the trimming and the transformation were applied to it.
/// <br />
/// On an add it is also what the handler hands back: writing to it is what canonicalizes a value that
/// only the server knows the right spelling of - the address an alias resolves to, the id a code stands
/// for - and what is written is what the list is given, exactly as an OnEdit handler corrects a tag on
/// its way in. Leaving it empty is not a way to call the add off, which is what <see cref="Cancel"/> is
/// for: the tag is then added as it stood. On a remove there is nothing to rewrite, the tag having been
/// named by the list it is being taken out of.
/// </summary>
public string Tag { get; set; } = string.Empty;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ public class BitTagsInputClassStyles
public string? Root { get; set; }

/// <summary>
/// Custom CSS classes/styles for the focused state of the root element.
/// Custom CSS classes/styles carried by the root element while the input holds the focus. A tag reached
/// with the arrow keys is the field's focus rather than the input's, so it lights the field's own ring
/// (through :focus-within) without adding this one.
/// </summary>
public string? Focused { get; set; }

Expand Down Expand Up @@ -47,11 +49,45 @@ public class BitTagsInputClassStyles
/// </summary>
public string? FocusedTag { get; set; }

/// <summary>
/// Custom CSS classes/styles for a tag the CanRemoveTag predicate holds in place, which carries no
/// dismiss button of its own.
/// </summary>
public string? FixedTag { get; set; }

/// <summary>
/// Custom CSS classes/styles for the tag that is currently being corrected in place, which carries
/// the little edit input instead of its text.
/// </summary>
public string? EditingTag { get; set; }

/// <summary>
/// Custom CSS classes/styles for the tag that has been picked up with its reorder handle and is
/// waiting to be put down.
/// </summary>
public string? PickedUpTag { get; set; }

/// <summary>
/// Custom CSS classes/styles for the tag a refused duplicate collided with, which is marked until the
/// user types again.
/// </summary>
public string? DuplicateTag { get; set; }

/// <summary>
/// Custom CSS classes/styles for the tag text.
/// </summary>
public string? TagText { get; set; }

/// <summary>
/// Custom CSS classes/styles for the reorder handle AllowReorder draws on each tag.
/// </summary>
public string? ReorderButton { get; set; }

/// <summary>
/// Custom CSS classes/styles for the icon of that reorder handle.
/// </summary>
public string? ReorderIcon { get; set; }

/// <summary>
/// Custom CSS classes/styles for the dismiss button of each tag.
/// </summary>
Expand Down Expand Up @@ -83,6 +119,11 @@ public class BitTagsInputClassStyles
/// </summary>
public string? Counter { get; set; }

/// <summary>
/// Custom CSS classes/styles for the spinner IsLoading draws at the end of the field.
/// </summary>
public string? Spinner { get; set; }

/// <summary>
/// Custom CSS classes/styles for the clear button of the BitTagsInput.
/// </summary>
Expand All @@ -97,4 +138,10 @@ public class BitTagsInputClassStyles
/// Custom CSS classes/styles for the description (helper text) of the BitTagsInput.
/// </summary>
public string? Description { get; set; }

/// <summary>
/// Custom CSS classes/styles for the sentence ShowInvalidMessage draws under the field when a tag is
/// refused, which stands where the description otherwise would.
/// </summary>
public string? InvalidMessage { get; set; }
}
Loading
Loading