diff --git a/CHANGELOG.md b/CHANGELOG.md index 7807c1fbe0..ed140e3f09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Added "tab" border style https://github.com/Textualize/textual/pull/5335 - Added support for XML syntax highlighting https://github.com/Textualize/textual/pull/5320 - Added `TextArea.update_highlight_query` https://github.com/Textualize/textual/pull/5320 +- `Input` widget now supports text selection via mouse and keyboard https://github.com/Textualize/textual/pull/5340 +- Added new keybinds (hold shift) for text selection in `Input` https://github.com/Textualize/textual/pull/5340 +- Added `Input.selection` reactive attribute for reading and updating the current selection https://github.com/Textualize/textual/pull/5340 +- Added `Input.select_on_focus` (default `True`) to enable/disable selecting all text in an `Input` on focus https://github.com/Textualize/textual/pull/5340 +- Added methods `Input.replace`, `Input.insert`, `Input.delete`, `Input.delete_selection` for editing text https://github.com/Textualize/textual/pull/5340 +- Added `Input.selected_text` property for getting the currently selected text https://github.com/Textualize/textual/pull/5340 +- `Input` can now be scrolled independently of cursor position (hold shift and scroll with the mouse wheel in supported environments) https://github.com/Textualize/textual/pull/5340 + +## Changed + +- Breaking change: Removed `Input` reactive attributes `view_position`, `cursor_position` (now exists as a property which proxies to the `Input.selection` reactive attribute), https://github.com/Textualize/textual/pull/5340 +- `Input.restrict` now checked on all edit operations (rather than just on `insert`) https://github.com/Textualize/textual/pull/5340 ## Fixed diff --git a/docs/guide/design.md b/docs/guide/design.md index 4226d06aaf..08fc2bb42b 100644 --- a/docs/guide/design.md +++ b/docs/guide/design.md @@ -276,7 +276,6 @@ Here's a comprehensive list of these variables, their purposes, and default valu | `$input-cursor-foreground` | Text color of the input cursor | `$background` | | `$input-cursor-text-style` | Text style of the input cursor | `"none"` | | `$input-selection-background` | Background color of selected text | `$primary-lighten-1` with 40% opacity | -| `$input-selection-foreground` | Text color of selected text | `$background` | ### Scrollbar diff --git a/src/textual/design.py b/src/textual/design.py index f782b8803d..33d0e6c3e4 100644 --- a/src/textual/design.py +++ b/src/textual/design.py @@ -321,9 +321,6 @@ def luminosity_range(spread: float) -> Iterable[tuple[str, float]]: "input-selection-background", Color.parse(colors["primary-lighten-1"]).with_alpha(0.4).hex, ) - colors["input-selection-foreground"] = get( - "input-selection-foreground", background.hex - ) # Markdown header styles colors["markdown-h1-color"] = get("markdown-h1-color", primary.hex) diff --git a/src/textual/theme.py b/src/textual/theme.py index f3ff5045df..af36369b8f 100644 --- a/src/textual/theme.py +++ b/src/textual/theme.py @@ -171,7 +171,6 @@ def to_color_system(self) -> ColorSystem: "block-cursor-text-style": "b", "block-cursor-blurred-text-style": "i", "input-selection-background": "ansi_blue", - "input-selection-foreground": "ansi_white", "input-cursor-text-style": "reverse", "scrollbar": "ansi_blue", "border-blurred": "ansi_blue", diff --git a/src/textual/widgets/_input.py b/src/textual/widgets/_input.py index b25ac0af36..7a14fc393f 100644 --- a/src/textual/widgets/_input.py +++ b/src/textual/widgets/_input.py @@ -2,32 +2,31 @@ import re from dataclasses import dataclass -from typing import TYPE_CHECKING, ClassVar, Iterable +from typing import TYPE_CHECKING, ClassVar, Iterable, NamedTuple from rich.cells import cell_len, get_character_cell_size -from rich.console import Console, ConsoleOptions, RenderableType -from rich.console import RenderResult as RichRenderResult +from rich.console import RenderableType from rich.highlighter import Highlighter -from rich.segment import Segment from rich.text import Text from typing_extensions import Literal from textual import events -from textual._segment_tools import line_crop +from textual.expand_tabs import expand_tabs_inline +from textual.scroll_view import ScrollView +from textual.strip import Strip if TYPE_CHECKING: - from textual.app import RenderResult + pass from textual.binding import Binding, BindingType from textual.css._error_tools import friendly_list from textual.events import Blur, Focus, Mount -from textual.geometry import Offset, Size +from textual.geometry import Offset, Region, Size, clamp from textual.message import Message from textual.reactive import Reactive, reactive, var from textual.suggester import Suggester, SuggestionReady from textual.timer import Timer from textual.validation import ValidationResult, Validator -from textual.widget import Widget InputValidationOn = Literal["blur", "changed", "submitted"] """Possible messages that trigger input validation.""" @@ -42,66 +41,70 @@ InputType = Literal["integer", "number", "text"] -class _InputRenderable: - """Render the input content.""" - - def __init__(self, input: Input, cursor_visible: bool) -> None: - self.input = input - self.cursor_visible = cursor_visible - - def __rich_console__( - self, console: "Console", options: "ConsoleOptions" - ) -> RichRenderResult: - input = self.input - result = input._value - width = input.content_size.width - - # Add the completion with a faded style. - value = input.value - value_length = len(value) - suggestion = input._suggestion - show_suggestion = len(suggestion) > value_length and input.has_focus - if show_suggestion: - result += Text( - suggestion[value_length:], - input.get_component_rich_style("input--suggestion"), - ) +class Selection(NamedTuple): + """A range of selected text within the Input. - if self.cursor_visible and input.has_focus: - if not show_suggestion and input._cursor_at_end: - result.pad_right(1) - cursor_style = input.get_component_rich_style("input--cursor") - cursor = input.cursor_position - result.stylize(cursor_style, cursor, cursor + 1) - - segments = list(result.render(console)) - line_length = Segment.get_line_length(segments) - if line_length < width: - segments = Segment.adjust_line_length(segments, width) - line_length = width - - line = line_crop( - list(segments), - input.view_position, - input.view_position + width, - line_length, - ) - yield from line + Text can be selected by clicking and dragging the mouse, or by pressing + shift+arrow keys. + + Attributes: + start: The start index of the selection. + end: The end index of the selection. + """ + + start: int + end: int + + @classmethod + def cursor(cls, cursor_position: int) -> Selection: + """Create a selection from a cursor position.""" + return cls(cursor_position, cursor_position) + + @property + def is_empty(self) -> bool: + """Return True if the selection is empty.""" + return self.start == self.end -class Input(Widget, can_focus=True): +class Input(ScrollView): """A text input widget.""" BINDINGS: ClassVar[list[BindingType]] = [ Binding("left", "cursor_left", "Move cursor left", show=False), + Binding( + "shift+left", + "cursor_left(True)", + "Move cursor left and select", + show=False, + ), Binding("ctrl+left", "cursor_left_word", "Move cursor left a word", show=False), + Binding( + "ctrl+shift+left", + "cursor_left_word(True)", + "Move cursor left a word and select", + show=False, + ), Binding("right", "cursor_right", "Move cursor right", show=False), + Binding( + "shift+right", + "cursor_right(True)", + "Move cursor right and select", + show=False, + ), Binding( "ctrl+right", "cursor_right_word", "Move cursor right a word", show=False ), + Binding( + "ctrl+shift+right", + "cursor_right_word(True)", + "Move cursor right a word and select", + show=False, + ), Binding("backspace", "delete_left", "Delete character left", show=False), Binding("home,ctrl+a", "home", "Go to start", show=False), Binding("end,ctrl+e", "end", "Go to end", show=False), + Binding("shift+home", "home(True)", "Select line start", show=False), + Binding("shift+end", "end(True)", "Select line end", show=False), Binding("delete,ctrl+d", "delete_right", "Delete character right", show=False), Binding("enter", "submit", "Submit", show=False), Binding( @@ -112,6 +115,7 @@ class Input(Widget, can_focus=True): "ctrl+f", "delete_right_word", "Delete right to start of word", show=False ), Binding("ctrl+k", "delete_right_all", "Delete all to the right", show=False), + Binding("ctrl+c", "copy_selection", "Copy selected text", show=False), ] """ | Key(s) | Description | @@ -135,6 +139,7 @@ class Input(Widget, can_focus=True): "input--cursor", "input--placeholder", "input--suggestion", + "input--selection", } """ | Class | Description | @@ -142,6 +147,7 @@ class Input(Widget, can_focus=True): | `input--cursor` | Target the cursor. | | `input--placeholder` | Target the placeholder text (when it exists). | | `input--suggestion` | Target the auto-completion suggestion (when it exists). | + | `input--selection` | Target the selected text. | """ DEFAULT_CSS = """ @@ -152,6 +158,7 @@ class Input(Widget, can_focus=True): border: tall $border-blurred; width: 100%; height: 3; + scrollbar-size-horizontal: 0; &:focus { border: tall $border; @@ -162,6 +169,9 @@ class Input(Widget, can_focus=True): color: $input-cursor-foreground; text-style: $input-cursor-text-style; } + &>.input--selection { + background: $input-selection-background; + } &>.input--placeholder, &>.input--suggestion { color: $text-disabled; } @@ -195,13 +205,23 @@ class Input(Widget, can_focus=True): """ cursor_blink = reactive(True, init=False) - value = reactive("", layout=True, init=False) - input_scroll_offset = reactive(0) - cursor_position: Reactive[int] = reactive(0) - view_position = reactive(0) + # TODO - check with width: auto to see if layout=True is needed + value: Reactive[str] = reactive("", init=False) + + @property + def cursor_position(self) -> int: + """The current position of the cursor, corresponding to the end of the selection.""" + return self.selection.end + + @cursor_position.setter + def cursor_position(self, position: int) -> None: + """Set the current position of the cursor.""" + self.selection = Selection.cursor(position) + + selection: Reactive[Selection] = reactive(Selection.cursor(0)) + """The currently selected range of text.""" + placeholder = reactive("") - complete = reactive("") - width = reactive(1) _cursor_visible = reactive(True) password = reactive(False) suggester: Suggester | None @@ -276,6 +296,7 @@ def __init__( validators: Validator | Iterable[Validator] | None = None, validate_on: Iterable[InputValidationOn] | None = None, valid_empty: bool = False, + select_on_focus: bool = True, name: str | None = None, id: str | None = None, classes: str | None = None, @@ -299,6 +320,7 @@ def __init__( which determine when to do input validation. The default is to do validation for all messages. valid_empty: Empty values are valid. + select_on_focus: Whether to select all text on focus. name: Optional name for the input widget. id: Optional ID for the widget. classes: Optional initial classes for the widget. @@ -358,6 +380,9 @@ def __init__( elif self.type == "number": self.validators.append(Number()) + self._selecting = False + """True if the user is selecting text with the mouse.""" + self._initial_value = True """Indicates if the value has been set for the first time yet.""" if value is not None: @@ -366,10 +391,18 @@ def __init__( if tooltip is not None: self.tooltip = tooltip + self.select_on_focus = select_on_focus + def _position_to_cell(self, position: int) -> int: - """Convert an index within the value to cell position.""" - cell_offset = cell_len(self.value[:position]) - return cell_offset + """Convert an index within the value to cell position. + + Args: + position: The index within the value to convert. + + Returns: + The cell position corresponding to the index. + """ + return cell_len(expand_tabs_inline(self.value[:position], 4)) @property def _cursor_offset(self) -> int: @@ -382,7 +415,7 @@ def _cursor_offset(self) -> int: @property def _cursor_at_end(self) -> bool: """Flag to indicate if the cursor is at the end""" - return self.cursor_position >= len(self.value) + return self.cursor_position == len(self.value) def check_consume_key(self, key: str, character: str | None) -> bool: """Check if the widget may consume the given key. @@ -398,32 +431,19 @@ def check_consume_key(self, key: str, character: str | None) -> bool: """ return character is not None and character.isprintable() - def validate_cursor_position(self, cursor_position: int) -> int: - return min(max(0, cursor_position), len(self.value)) - - def validate_view_position(self, view_position: int) -> int: - width = self.content_size.width - new_view_position = max(0, min(view_position, self.cursor_width - width)) - return new_view_position - - def _watch_cursor_position(self) -> None: - width = self.content_size.width - if width == 0: - # If the input has no width the view position can't be elsewhere. - self.view_position = 0 - return - - view_start = self.view_position - view_end = view_start + width - cursor_offset = self._cursor_offset - - if cursor_offset >= view_end or cursor_offset < view_start: - view_position = cursor_offset - width // 2 - self.view_position = view_position - else: - self.view_position = self.view_position + def validate_selection(self, selection: Selection) -> Selection: + start, end = selection + value_length = len(self.value) + return Selection(clamp(start, 0, value_length), clamp(end, 0, value_length)) + def _watch_selection(self, selection: Selection) -> None: self.app.cursor_position = self.cursor_screen_offset + if not self._initial_value: + self.scroll_to_region( + Region(self._cursor_offset, 0, width=1, height=1), + force=True, + animate=False, + ) def _watch_cursor_blink(self, blink: bool) -> None: """Ensure we handle updating the cursor blink at runtime.""" @@ -431,16 +451,19 @@ def _watch_cursor_blink(self, blink: bool) -> None: if blink: self._blink_timer.resume() else: - self._pause_blink_cycle() + self._pause_blink() self._cursor_visible = True @property def cursor_screen_offset(self) -> Offset: """The offset of the cursor of this input in screen-space. (x, y)/(column, row)""" x, y, _width, _height = self.content_region - return Offset(x + self._cursor_offset - self.view_position, y) + scroll_x, _ = self.scroll_offset + return Offset(x + self._cursor_offset - scroll_x, y) def _watch_value(self, value: str) -> None: + """Update the virtual size and suggestion when the value changes.""" + self.virtual_size = Size(self.content_width, 1) self._suggestion = "" if self.suggester and value: self.run_worker(self.suggester._get_suggestion(self, value)) @@ -507,17 +530,15 @@ def is_valid(self) -> bool: """Check if the value has passed validation.""" return self._valid - @property - def cursor_width(self) -> int: - """The width of the input (with extra space for cursor at the end).""" - if self.placeholder and not self.value: - return cell_len(self.placeholder) - return self._position_to_cell(len(self.value)) + 1 + def render_line(self, y: int) -> Strip: + if y != 0: + return Strip.blank(self.size.width) + + console = self.app.console + max_content_width = self.scrollable_content_region.width - def render(self) -> RenderResult: - self.view_position = self.view_position if not self.value: - placeholder = Text(self.placeholder, justify="left") + placeholder = Text(self.placeholder, justify="left", end="") placeholder.stylize(self.get_component_rich_style("input--placeholder")) if self.has_focus: cursor_style = self.get_component_rich_style("input--cursor") @@ -525,24 +546,77 @@ def render(self) -> RenderResult: # If the placeholder is empty, there's no characters to stylise # to make the cursor flash, so use a single space character if len(placeholder) == 0: - placeholder = Text(" ") + placeholder = Text(" ", end="") placeholder.stylize(cursor_style, 0, 1) - return placeholder - return _InputRenderable(self, self._cursor_visible) + + strip = Strip( + console.render( + placeholder, console.options.update_width(max_content_width + 1) + ) + ) + else: + result = self._value + + # Add the completion with a faded style. + value = self.value + value_length = len(value) + suggestion = self._suggestion + show_suggestion = len(suggestion) > value_length and self.has_focus + if show_suggestion: + result += Text( + suggestion[value_length:], + self.get_component_rich_style("input--suggestion"), + end="", + ) + + if self.has_focus: + if not self.selection.is_empty: + start, end = self.selection + start, end = sorted((start, end)) + selection_style = self.get_component_rich_style("input--selection") + result.stylize_before(selection_style, start, end) + + if self._cursor_visible: + cursor_style = self.get_component_rich_style("input--cursor") + cursor = self.cursor_position + if not show_suggestion and self._cursor_at_end: + result.pad_right(1) + result.stylize(cursor_style, cursor, cursor + 1) + + segments = list( + console.render(result, console.options.update_width(self.content_width)) + ) + + strip = Strip(segments) + scroll_x, _ = self.scroll_offset + strip = strip.crop(scroll_x, scroll_x + max_content_width + 1) + strip = strip.extend_cell_length(max_content_width + 1) + + return strip.apply_style(self.rich_style) @property def _value(self) -> Text: """Value rendered as text.""" if self.password: - return Text("•" * len(self.value), no_wrap=True, overflow="ignore") + return Text("•" * len(self.value), no_wrap=True, overflow="ignore", end="") else: - text = Text(self.value, no_wrap=True, overflow="ignore") + text = Text(self.value, no_wrap=True, overflow="ignore", end="") if self.highlighter is not None: text = self.highlighter(text) return text + @property + def content_width(self) -> int: + """The width of the content.""" + if self.placeholder and not self.value: + return cell_len(self.placeholder) + + # Extra space for cursor at the end. + return self._value.cell_len + 1 + def get_content_width(self, container: Size, viewport: Size) -> int: - return self.cursor_width + """Get the widget of the content.""" + return self.content_width def get_content_height(self, container: Size, viewport: Size, width: int) -> int: return 1 @@ -559,67 +633,97 @@ def _on_mount(self, event: Mount) -> None: ) def _on_blur(self, event: Blur) -> None: - self._pause_blink_cycle() + self._pause_blink() if "blur" in self.validate_on: self.validate(self.value) def _on_focus(self, event: Focus) -> None: - self._restart_blink_cycle() + self._restart_blink() + if self.select_on_focus: + self.selection = Selection(0, len(self.value)) self.app.cursor_position = self.cursor_screen_offset self._suggestion = "" async def _on_key(self, event: events.Key) -> None: - self._restart_blink_cycle() + self._restart_blink() if event.is_printable: event.stop() assert event.character is not None - self.insert_text_at_cursor(event.character) + selection = self.selection + if selection.is_empty: + self.insert_text_at_cursor(event.character) + else: + self.replace(event.character, *selection) event.prevent_default() def _on_paste(self, event: events.Paste) -> None: if event.text: line = event.text.splitlines()[0] - self.insert_text_at_cursor(line) + selection = self.selection + if selection.is_empty: + self.insert_text_at_cursor(line) + else: + self.replace(line, *selection) event.stop() - async def _on_click(self, event: events.Click) -> None: - offset = event.get_content_offset(self) - if offset is None: - return - event.stop() - click_x = offset.x + self.view_position + def _cell_offset_to_index(self, offset: int) -> int: + """Convert a cell offset to a character index, accounting for character width. + + Args: + offset: The cell offset to convert. + + Returns: + The character index corresponding to the cell offset. + """ cell_offset = 0 _cell_size = get_character_cell_size + scroll_x, _ = self.scroll_offset + offset += scroll_x for index, char in enumerate(self.value): cell_width = _cell_size(char) - if cell_offset <= click_x < (cell_offset + cell_width): - self.cursor_position = index - break + if cell_offset <= offset < (cell_offset + cell_width): + return index cell_offset += cell_width - else: - self.cursor_position = len(self.value) + return clamp(offset, 0, len(self.value)) async def _on_mouse_down(self, event: events.MouseDown) -> None: - self._pause_blink_cycle() + self._pause_blink(visible=True) + offset_x, _ = event.get_content_offset_capture(self) + self.selection = Selection.cursor(self._cell_offset_to_index(offset_x)) + self._selecting = True + self.capture_mouse() async def _on_mouse_up(self, event: events.MouseUp) -> None: - self._restart_blink_cycle() + if self._selecting: + self._selecting = False + self.release_mouse() + self._restart_blink() + + async def _on_mouse_move(self, event: events.MouseMove) -> None: + if self._selecting: + # As we drag the mouse, we update the end position of the selection, + # keeping the start position fixed. + offset = event.get_content_offset_capture(self) + selection_start, _ = self.selection + self.selection = Selection( + selection_start, self._cell_offset_to_index(offset.x) + ) async def _on_suggestion_ready(self, event: SuggestionReady) -> None: """Handle suggestion messages and set the suggestion when relevant.""" if event.value == self.value: self._suggestion = event.suggestion - def _restart_blink_cycle(self) -> None: + def _restart_blink(self) -> None: """Restart the cursor blink cycle.""" self._cursor_visible = True if self.cursor_blink and self._blink_timer: self._blink_timer.reset() - def _pause_blink_cycle(self) -> None: + def _pause_blink(self, visible: bool = False) -> None: """Hide the blinking cursor and pause the blink cycle.""" - self._cursor_visible = False + self._cursor_visible = visible if self._blink_timer: self._blink_timer.pause() @@ -629,43 +733,7 @@ def insert_text_at_cursor(self, text: str) -> None: Args: text: New text to insert. """ - - def check_allowed_value(value: str) -> bool: - """Check if new value is restricted.""" - # Check max length - if self.max_length and len(value) > self.max_length: - return False - # Check explicit restrict - if self.restrict and re.fullmatch(self.restrict, value) is None: - return False - # Check type restrict - if self.type: - type_restrict = _RESTRICT_TYPES.get(self.type, None) - if ( - type_restrict is not None - and re.fullmatch(type_restrict, value) is None - ): - return False - # Character is allowed - return True - - if self.cursor_position >= len(self.value): - new_value = self.value + text - if check_allowed_value(new_value): - self.value = new_value - self.cursor_position = len(self.value) - else: - self.restricted() - else: - value = self.value - before = value[: self.cursor_position] - after = value[self.cursor_position :] - new_value = f"{before}{text}{after}" - if check_allowed_value(new_value): - self.value = new_value - self.cursor_position += len(text) - else: - self.restricted() + self.insert(text, self.cursor_position) def restricted(self) -> None: """Called when a character has been restricted. @@ -679,68 +747,187 @@ def clear(self) -> None: """Clear the input.""" self.value = "" - def action_cursor_left(self) -> None: - """Move the cursor one position to the left.""" - self.cursor_position -= 1 + @property + def selected_text(self) -> str: + """The text between the start and end points of the current selection.""" + start, end = sorted(self.selection) + return self.value[start:end] - def action_cursor_right(self) -> None: - """Accept an auto-completion or move the cursor one position to the right.""" - if self._cursor_at_end and self._suggestion: - self.value = self._suggestion - self.cursor_position = len(self.value) + def action_cursor_left(self, select: bool = False) -> None: + """Move the cursor one position to the left. + + Args: + select: If `True`, select the text to the left of the cursor. + """ + if select: + start, end = self.selection + self.selection = Selection(start, end - 1) else: - self.cursor_position += 1 + self.cursor_position -= 1 - def action_home(self) -> None: - """Move the cursor to the start of the input.""" - self.cursor_position = 0 + def action_cursor_right(self, select: bool = False) -> None: + """Accept an auto-completion or move the cursor one position to the right. - def action_end(self) -> None: - """Move the cursor to the end of the input.""" - self.cursor_position = len(self.value) + Args: + select: If `True`, select the text to the right of the cursor. + """ + if select: + start, end = self.selection + self.selection = Selection(start, end + 1) + else: + if self._cursor_at_end and self._suggestion: + self.value = self._suggestion + self.cursor_position = len(self.value) + else: + self.cursor_position += 1 + + def action_home(self, select: bool = False) -> None: + """Move the cursor to the start of the input. + + Args: + select: If `True`, select the text between the old and new cursor positions. + """ + if select: + self.selection = Selection(self.cursor_position, 0) + else: + self.cursor_position = 0 + + def action_end(self, select: bool = False) -> None: + """Move the cursor to the end of the input. + + Args: + select: If `True`, select the text between the old and new cursor positions. + """ + if select: + self.selection = Selection(self.cursor_position, len(self.value)) + else: + self.cursor_position = len(self.value) _WORD_START = re.compile(r"(?<=\W)\w") - def action_cursor_left_word(self) -> None: - """Move the cursor left to the start of a word.""" + def action_cursor_left_word(self, select: bool = False) -> None: + """Move the cursor left to the start of a word. + + Args: + select: If `True`, select the text between the old and new cursor positions. + """ if self.password: # This is a password field so don't give any hints about word # boundaries, even during movement. - self.action_home() + self.action_home(select) else: + start, _ = self.selection try: *_, hit = re.finditer( self._WORD_START, self.value[: self.cursor_position] ) except ValueError: - self.cursor_position = 0 + target = 0 else: - self.cursor_position = hit.start() + target = hit.start() - def action_cursor_right_word(self) -> None: - """Move the cursor right to the start of a word.""" + if select: + self.selection = Selection(start, target) + else: + self.cursor_position = target + + def action_cursor_right_word(self, select: bool = False) -> None: + """Move the cursor right to the start of a word. + + Args: + select: If `True`, select the text between the old and new cursor positions. + """ if self.password: # This is a password field so don't give any hints about word # boundaries, even during movement. - self.action_end() + self.action_end(select) else: hit = re.search(self._WORD_START, self.value[self.cursor_position :]) + + start, end = self.selection if hit is None: - self.cursor_position = len(self.value) + target = len(self.value) + else: + target = end + hit.start() + + if select: + self.selection = Selection(start, target) else: - self.cursor_position += hit.start() + self.cursor_position = target + + def replace(self, text: str, start: int, end: int) -> None: + """Replace the text between the start and end locations with the given text. + + Args: + text: Text to replace the existing text with. + start: Start index to replace (inclusive). + end: End index to replace (inclusive). + """ + + def check_allowed_value(value: str) -> bool: + """Check if new value is restricted.""" + + # Check max length + if self.max_length and len(value) > self.max_length: + return False + # Check explicit restrict + if self.restrict and re.fullmatch(self.restrict, value) is None: + return False + # Check type restrict + if self.type: + type_restrict = _RESTRICT_TYPES.get(self.type, None) + if ( + type_restrict is not None + and re.fullmatch(type_restrict, value) is None + ): + return False + # Character is allowed + return True + + value = self.value + start, end = sorted((max(0, start), min(len(value), end))) + new_value = f"{value[:start]}{text}{value[end:]}" + if check_allowed_value(new_value): + self.value = new_value + self.cursor_position = start + len(text) + else: + self.restricted() + + def insert(self, text: str, index: int) -> None: + """Insert text at the given index. + + Args: + text: Text to insert. + index: Index to insert the text at (inclusive). + """ + self.replace(text, index, index) + + def delete(self, start: int, end: int) -> None: + """Delete the text between the start and end locations. + + Args: + start: Start index to delete (inclusive). + end: End index to delete (inclusive). + """ + self.replace("", start, end) + + def delete_selection(self) -> None: + """Delete the current selection.""" + self.delete(*self.selection) def action_delete_right(self) -> None: """Delete one character at the current cursor position.""" - value = self.value - delete_position = self.cursor_position - before = value[:delete_position] - after = value[delete_position + 1 :] - self.value = f"{before}{after}" - self.cursor_position = delete_position + if self.selection.is_empty: + self.delete(self.cursor_position, self.cursor_position + 1) + else: + self.delete_selection() def action_delete_right_word(self) -> None: """Delete the current character and all rightward to the start of the next word.""" + if not self.selection.is_empty: + self.delete_selection() + return + if self.password: # This is a password field so don't give any hints about word # boundaries, even during deletion. @@ -749,60 +936,54 @@ def action_delete_right_word(self) -> None: after = self.value[self.cursor_position :] hit = re.search(self._WORD_START, after) if hit is None: - self.value = self.value[: self.cursor_position] + self.action_delete_right_all() else: - self.value = ( - f"{self.value[: self.cursor_position]}{after[hit.end() - 1:]}" - ) + start = self.cursor_position + end = start + hit.end() - 1 + self.delete(start, end) def action_delete_right_all(self) -> None: """Delete the current character and all characters to the right of the cursor position.""" - self.value = self.value[: self.cursor_position] + if self.selection.is_empty: + self.delete(self.cursor_position, len(self.value)) + else: + self.delete_selection() def action_delete_left(self) -> None: """Delete one character to the left of the current cursor position.""" - if self.cursor_position <= 0: - # Cursor at the start, so nothing to delete - return - if self.cursor_position == len(self.value): - # Delete from end - self.value = self.value[:-1] - self.cursor_position = len(self.value) + if self.selection.is_empty: + self.delete(self.cursor_position - 1, self.cursor_position) else: - # Cursor in the middle - value = self.value - delete_position = self.cursor_position - 1 - before = value[:delete_position] - after = value[delete_position + 1 :] - self.value = f"{before}{after}" - self.cursor_position = delete_position + self.delete_selection() def action_delete_left_word(self) -> None: """Delete leftward of the cursor position to the start of a word.""" - if self.cursor_position <= 0: + if not self.selection.is_empty: + self.delete_selection() return + if self.password: # This is a password field so don't give any hints about word # boundaries, even during deletion. self.action_delete_left_all() else: - after = self.value[self.cursor_position :] try: *_, hit = re.finditer( self._WORD_START, self.value[: self.cursor_position] ) except ValueError: - self.cursor_position = 0 + target = 0 else: - self.cursor_position = hit.start() - new_value = f"{self.value[: self.cursor_position]}{after}" - self.value = new_value + target = hit.start() + + self.delete(target, self.cursor_position) def action_delete_left_all(self) -> None: """Delete all characters to the left of the cursor position.""" - if self.cursor_position > 0: - self.value = self.value[self.cursor_position :] - self.cursor_position = 0 + if self.selection.is_empty: + self.delete(0, self.cursor_position) + else: + self.delete_selection() async def action_submit(self) -> None: """Handle a submit action. @@ -813,3 +994,7 @@ async def action_submit(self) -> None: self.validate(self.value) if "submitted" in self.validate_on else None ) self.post_message(self.Submitted(self, self.value, validation_result)) + + def action_copy_selection(self) -> None: + """Copy the current selection to the clipboard.""" + self.app.copy_to_clipboard(self.selected_text) diff --git a/src/textual/widgets/_masked_input.py b/src/textual/widgets/_masked_input.py index 4fc0e00b3d..560258f332 100644 --- a/src/textual/widgets/_masked_input.py +++ b/src/textual/widgets/_masked_input.py @@ -5,19 +5,18 @@ from enum import Flag, auto from typing import TYPE_CHECKING, Iterable, Pattern -from rich.console import Console, ConsoleOptions, RenderableType -from rich.console import RenderResult as RichRenderResult +from rich.console import RenderableType from rich.segment import Segment from rich.text import Text from typing_extensions import Literal from textual import events -from textual._segment_tools import line_crop +from textual.strip import Strip if TYPE_CHECKING: - from textual.app import RenderResult + pass -from textual.reactive import var +from textual.reactive import Reactive, var from textual.validation import ValidationResult, Validator from textual.widgets._input import Input @@ -63,55 +62,6 @@ class _CharFlags(Flag): } -class _InputRenderable: - """Render the input content.""" - - def __init__(self, input: Input, cursor_visible: bool) -> None: - self.input = input - self.cursor_visible = cursor_visible - - def __rich_console__( - self, console: "Console", options: "ConsoleOptions" - ) -> RichRenderResult: - input = self.input - result = input._value - width = input.content_size.width - - # Add the completion with a faded style. - value = input.value - value_length = len(value) - template = input._template - style = input.get_component_rich_style("input--placeholder") - result += Text( - template.mask[value_length:], - style, - ) - for index, (char, char_definition) in enumerate(zip(value, template.template)): - if char == " ": - result.stylize(style, index, index + 1) - - if self.cursor_visible and input.has_focus: - if input._cursor_at_end: - result.pad_right(1) - cursor_style = input.get_component_rich_style("input--cursor") - cursor = input.cursor_position - result.stylize(cursor_style, cursor, cursor + 1) - - segments = list(result.render(console)) - line_length = Segment.get_line_length(segments) - if line_length < width: - segments = Segment.adjust_line_length(segments, width) - line_length = width - - line = line_crop( - list(segments), - input.view_position, - input.view_position + width, - line_length, - ) - yield from line - - class _Template(Validator): """Template mask enforcer.""" @@ -493,7 +443,7 @@ def empty_mask(self) -> str: class MaskedInput(Input, can_focus=True): """A masked text input widget.""" - template = var("") + template: Reactive[str] = var("") """Input template mask currently in use.""" def __init__( @@ -505,6 +455,7 @@ def __init__( validators: Validator | Iterable[Validator] | None = None, validate_on: Iterable[InputValidationOn] | None = None, valid_empty: bool = False, + select_on_focus: bool = True, name: str | None = None, id: str | None = None, classes: str | None = None, @@ -534,6 +485,7 @@ def __init__( validators=validators, validate_on=validate_on, valid_empty=valid_empty, + select_on_focus=select_on_focus, name=name, id=id, classes=classes, @@ -596,14 +548,48 @@ def set_classes() -> None: return combined_result - def render(self) -> RenderResult: - return _InputRenderable(self, self._cursor_visible) + def render_line(self, y: int) -> Strip: + if y != 0: + return Strip.blank(self.size.width) + + result = self._value + width = self.content_size.width + + # Add the completion with a faded style. + value = self.value + value_length = len(value) + template = self._template + style = self.get_component_rich_style("input--placeholder") + result += Text( + template.mask[value_length:], + style, + end="", + ) + for index, (char, char_definition) in enumerate(zip(value, template.template)): + if char == " ": + result.stylize(style, index, index + 1) + + if self._cursor_visible and self.has_focus: + if self._cursor_at_end: + result.pad_right(1) + cursor_style = self.get_component_rich_style("input--cursor") + cursor = self.cursor_position + result.stylize(cursor_style, cursor, cursor + 1) + + segments = list(result.render(self.app.console)) + line_length = Segment.get_line_length(segments) + if line_length < width: + segments = Segment.adjust_line_length(segments, width) + line_length = width + + strip = Strip(segments).crop(self.scroll_offset.x, self.scroll_offset.x + width) + return strip.apply_style(self.rich_style) @property def _value(self) -> Text: """Value rendered as text.""" value = self._template.display(self.value) - return Text(value, no_wrap=True, overflow="ignore") + return Text(value, no_wrap=True, overflow="ignore", end="") async def _on_click(self, event: events.Click) -> None: """Ensure clicking on value does not leave cursor on a separator.""" diff --git a/src/textual/widgets/_text_area.py b/src/textual/widgets/_text_area.py index e498210336..2b68efbc60 100644 --- a/src/textual/widgets/_text_area.py +++ b/src/textual/widgets/_text_area.py @@ -238,6 +238,7 @@ class TextArea(ScrollView): ), Binding("ctrl+z", "undo", "Undo", show=False), Binding("ctrl+y", "redo", "Redo", show=False), + Binding("ctrl+c", "copy_selection", "Copy selected text", show=False), ] """ | Key(s) | Description | @@ -2279,6 +2280,10 @@ def action_delete_word_right(self) -> None: self._delete_via_keyboard(end, to_location) + def action_copy_selection(self) -> None: + """Copy the current selection to the clipboard.""" + self.app.copy_to_clipboard(self.selected_text) + @lru_cache(maxsize=128) def build_byte_to_codepoint_dict(data: bytes) -> dict[int, int]: diff --git a/src/textual/widgets/input.py b/src/textual/widgets/input.py index e69de29bb2..9d2e19975a 100644 --- a/src/textual/widgets/input.py +++ b/src/textual/widgets/input.py @@ -0,0 +1,3 @@ +from textual.widgets._input import Selection + +__all__ = ["Selection"] diff --git a/tests/input/test_input_mouse.py b/tests/input/test_input_mouse.py index a5249e5498..9793e21eac 100644 --- a/tests/input/test_input_mouse.py +++ b/tests/input/test_input_mouse.py @@ -68,11 +68,12 @@ async def test_mouse_clicks_within(text, click_at, should_land): assert pilot.app.query_one(Input).cursor_position == should_land -async def test_mouse_click_outwith(): - """Mouse clicks outside the input should not affect cursor position.""" +async def test_mouse_click_outwith_moves_cursor_to_nearest_cell(): + """Mouse clicks in the padding or border area should move the cursor as this makes + dragging and selecting text easier.""" async with InputApp(TEXT_SINGLE).run_test() as pilot: pilot.app.query_one(Input).cursor_position = 3 assert pilot.app.query_one(Input).cursor_position == 3 await pilot.click(Input, Offset(0, 0)) await pilot.pause() - assert pilot.app.query_one(Input).cursor_position == 3 + assert pilot.app.query_one(Input).cursor_position == 0 diff --git a/tests/input/test_input_properties.py b/tests/input/test_input_properties.py index 586989ceac..ef518ba69d 100644 --- a/tests/input/test_input_properties.py +++ b/tests/input/test_input_properties.py @@ -6,6 +6,7 @@ from textual.app import App, ComposeResult from textual.containers import Container from textual.widgets import Input +from textual.widgets.input import Selection class InputApp(App[None]): @@ -61,3 +62,34 @@ async def test_input_height(): input_widget.styles.height.value == input_widget.parent.styles.height.value ) assert input_widget.parent.styles.height.value == 1 + + +async def test_input_selected_text(): + async with InputApp().run_test() as pilot: + input_widget = pilot.app.query_one(Input) + input_widget.value = "Hello, world!" + input_widget.selection = Selection(0, 4) + assert input_widget.selected_text == "Hell" + + # Reverse selection + input_widget.selection = Selection(4, 0) + assert input_widget.selected_text == "Hell" + + # Empty selection + input_widget.selection = Selection(4, 4) + assert input_widget.selected_text == "" + + +async def test_input_selection_deleted_programmatically(): + async with InputApp().run_test() as pilot: + input_widget = pilot.app.query_one(Input) + input_widget.value = "Hello, world!" + input_widget.selection = Selection(0, 4) + input_widget.delete_selection() + assert input_widget.value == "o, world!" + + # Reverse selection + input_widget.value = "Hello, world!" + input_widget.selection = Selection(4, 0) + input_widget.delete_selection() + assert input_widget.value == "o, world!" diff --git a/tests/input/test_input_replace.py b/tests/input/test_input_replace.py new file mode 100644 index 0000000000..40276ffab1 --- /dev/null +++ b/tests/input/test_input_replace.py @@ -0,0 +1,64 @@ +from __future__ import annotations + +import pytest + +from textual.app import App, ComposeResult +from textual.widgets import Input + +_FORWARD_DELETIONS = [ + ((0, 0), "0123456789"), # Delete nothing + ((0, 10), ""), # Delete all + ((0, 1), "123456789"), # Delete first character + ((5, 10), "01234"), # Delete last 5 characters + ((3, 6), "0126789"), # Delete middle 3 characters + ((5, 20), "01234"), # Delete past end results in clamp +] +_REVERSE_DELETIONS = [ + ((end, start), value_after) for (start, end), value_after in _FORWARD_DELETIONS +] +DELETIONS = _FORWARD_DELETIONS + _REVERSE_DELETIONS +"""The same deletions performed in both forward and reverse directions.""" + + +@pytest.mark.parametrize("selection,value_after", DELETIONS) +async def test_input_delete(selection: tuple[int, int], value_after: str): + class InputApp(App[None]): + TEST_TEXT = "0123456789" + + def compose(self) -> ComposeResult: + yield Input(self.TEST_TEXT) + + async with InputApp().run_test() as pilot: + app = pilot.app + input = app.query_one(Input) + input.delete(*selection) + assert input.value == value_after + + +_FORWARD_REPLACEMENTS = [ + ((0, 0), "", "0123456789"), + ((0, 1), "X", "X123456789"), # Replace first character with "X" + ((5, 10), "X", "01234X"), # Replace last 5 characters with "X" + ((3, 6), "X", "012X6789"), # Replace middle 3 characters with "X" + ((5, 20), "X", "01234X"), # Replace past end results in clamp +] +_REVERSE_REPLACEMENTS = [ + ((end, start), replacement, result) + for (start, end), replacement, result in _FORWARD_REPLACEMENTS +] +REPLACEMENTS = _FORWARD_REPLACEMENTS + _REVERSE_REPLACEMENTS + + +@pytest.mark.parametrize("selection,replacement,result", REPLACEMENTS) +async def test_input_replace(selection: tuple[int, int], replacement: str, result: str): + class InputApp(App[None]): + TEST_TEXT = "0123456789" + + def compose(self) -> ComposeResult: + yield Input(self.TEST_TEXT) + + async with InputApp().run_test() as pilot: + app = pilot.app + input = app.query_one(Input) + input.replace(replacement, *selection) + assert input.value == result diff --git a/tests/input/test_input_value_visibility.py b/tests/input/test_input_value_visibility.py deleted file mode 100644 index e2de635028..0000000000 --- a/tests/input/test_input_value_visibility.py +++ /dev/null @@ -1,102 +0,0 @@ -from rich.console import Console - -from textual.app import App -from textual.widgets import Input - - -async def test_input_value_visible_on_instantiation(): - """Check if the full input value is rendered if the input is instantiated with it.""" - - class MyApp(App): - def compose(self): - yield Input(value="value") - - app = MyApp() - async with app.run_test(): - console = Console(width=5) - with console.capture() as capture: - console.print(app.query_one(Input).render()) - assert capture.get() == "value" - - -async def test_input_value_visible_after_value_assignment(): - """Check if the full input value is rendered if the value is assigned to programmatically.""" - - class MyApp(App): - def compose(self): - yield Input() - - def on_mount(self): - self.query_one(Input).value = "value" - - app = MyApp() - async with app.run_test(): - console = Console(width=5) - with console.capture() as capture: - console.print(app.query_one(Input).render()) - assert capture.get() == "value" - - -async def test_input_value_visible_if_mounted_later(): - """Check if full input value is rendered if the widget is mounted later.""" - - class MyApp(App): - BINDINGS = [("a", "add_input", "add_input")] - - async def action_add_input(self): - await self.mount(Input(value="value")) - - app = MyApp() - async with app.run_test() as pilot: - await pilot.press("a") - await pilot.pause() - console = Console(width=5) - with console.capture() as capture: - console.print(app.query_one(Input).render()) - assert capture.get() == "value" - - -async def test_input_value_visible_if_mounted_later_and_focused(): - """Check if full input value is rendered if the widget is mounted later and immediately focused.""" - - class MyApp(App): - BINDINGS = [("a", "add_input", "add_input")] - - async def action_add_input(self): - inp = Input(value="value") - await self.mount(inp) - inp.focus() - - app = MyApp() - async with app.run_test() as pilot: - await pilot.press("a") - await pilot.pause() - console = Console(width=5) - with console.capture() as capture: - console.print(app.query_one(Input).render()) - assert capture.get() == "value" - - -async def test_input_value_visible_if_mounted_later_and_assigned_after(): - """Check if full value rendered if the widget is mounted later and the value is then assigned to.""" - - class MyApp(App): - BINDINGS = [ - ("a", "add_input", "add_input"), - ("v", "set_value", "set_value"), - ] - - async def action_add_input(self): - await self.mount(Input()) - - def action_set_value(self): - self.query_one(Input).value = "value" - - app = MyApp() - async with app.run_test() as pilot: - await pilot.press("a") - await pilot.press("v") - console = Console(width=5) - with console.capture() as capture: - console.print(app.query_one(Input).render()) - assert capture.get() == "value" diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_ansi_command_palette.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_ansi_command_palette.svg index 806fe837e3..e8dbcb21f7 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_ansi_command_palette.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_ansi_command_palette.svg @@ -19,143 +19,143 @@ font-weight: 700; } - .terminal-2368587539-matrix { + .terminal-1724038555-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2368587539-title { + .terminal-1724038555-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2368587539-r1 { fill: #8a4346 } -.terminal-2368587539-r2 { fill: #868887 } -.terminal-2368587539-r3 { fill: #6b546f } -.terminal-2368587539-r4 { fill: #e0e0e0 } -.terminal-2368587539-r5 { fill: #292929 } -.terminal-2368587539-r6 { fill: #c5c8c6 } -.terminal-2368587539-r7 { fill: #0178d4 } -.terminal-2368587539-r8 { fill: #00ff00 } -.terminal-2368587539-r9 { fill: #000000 } -.terminal-2368587539-r10 { fill: #8d8d8d } -.terminal-2368587539-r11 { fill: #7e8486 } -.terminal-2368587539-r12 { fill: #e0e0e0;font-weight: bold } -.terminal-2368587539-r13 { fill: #a1a5a8 } + .terminal-1724038555-r1 { fill: #8a4346 } +.terminal-1724038555-r2 { fill: #868887 } +.terminal-1724038555-r3 { fill: #6b546f } +.terminal-1724038555-r4 { fill: #e0e0e0 } +.terminal-1724038555-r5 { fill: #292929 } +.terminal-1724038555-r6 { fill: #c5c8c6 } +.terminal-1724038555-r7 { fill: #0178d4 } +.terminal-1724038555-r8 { fill: #00ff00 } +.terminal-1724038555-r9 { fill: #000000 } +.terminal-1724038555-r10 { fill: #8d8d8d } +.terminal-1724038555-r11 { fill: #7e8486 } +.terminal-1724038555-r12 { fill: #e0e0e0;font-weight: bold } +.terminal-1724038555-r13 { fill: #a1a5a8 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - CommandPaletteApp + CommandPaletteApp - + - - RedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed -MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed -MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - -🔎Search for commands… - - -  Quit the application                                                           -Quit the application as soon as possible -  Save screenshot                                                                -Save an SVG 'screenshot' of the current screen -  Show keys and help panel                                                       -Show help for the focused widget and a summary of available keys -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed -MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed -MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed -MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed -MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed -MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed -MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed -MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed -MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed + + RedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed +MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed +MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + +🔎Search for commands… + + +  Quit the application                                                           +Quit the application as soon as possible +  Save screenshot                                                                +Save an SVG 'screenshot' of the current screen +  Show keys and help panel                                                       +Show help for the focused widget and a summary of available keys +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed +MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed +MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed +MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed +MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed +MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed +MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed +MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed +MagentaRedMagentaRedMagentaRedMagentaRedMagentaRedMagentaRed diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_app_blur.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_app_blur.svg index 87bfa8f0b8..800319e269 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_app_blur.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_app_blur.svg @@ -19,133 +19,133 @@ font-weight: 700; } - .terminal-1843476437-matrix { + .terminal-3758502277-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1843476437-title { + .terminal-3758502277-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1843476437-r1 { fill: #e0e0e0 } -.terminal-1843476437-r2 { fill: #c5c8c6 } -.terminal-1843476437-r3 { fill: #121212 } -.terminal-1843476437-r4 { fill: #191919 } + .terminal-3758502277-r1 { fill: #e0e0e0 } +.terminal-3758502277-r2 { fill: #c5c8c6 } +.terminal-3758502277-r3 { fill: #121212 } +.terminal-3758502277-r4 { fill: #191919 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - AppBlurApp + AppBlurApp - + - - - - - - - - - -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -This should be the blur style      -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -This should also be the blur style -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - - - + + + + + + + + + +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +This should be the blur style      +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +This should also be the blur style +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_app_search_commands_opens_and_displays_search_list.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_app_search_commands_opens_and_displays_search_list.svg index 89e9f90784..b4d5e82f04 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_app_search_commands_opens_and_displays_search_list.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_app_search_commands_opens_and_displays_search_list.svg @@ -19,138 +19,138 @@ font-weight: 700; } - .terminal-1636454365-matrix { + .terminal-2118731365-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1636454365-title { + .terminal-2118731365-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1636454365-r1 { fill: #646464 } -.terminal-1636454365-r2 { fill: #c5c8c6 } -.terminal-1636454365-r3 { fill: #0178d4 } -.terminal-1636454365-r4 { fill: #e0e0e0 } -.terminal-1636454365-r5 { fill: #00ff00 } -.terminal-1636454365-r6 { fill: #000000 } -.terminal-1636454365-r7 { fill: #121212 } -.terminal-1636454365-r8 { fill: #e0e0e0;font-weight: bold } -.terminal-1636454365-r9 { fill: #e0e0e0;font-weight: bold;text-decoration: underline; } + .terminal-2118731365-r1 { fill: #646464 } +.terminal-2118731365-r2 { fill: #c5c8c6 } +.terminal-2118731365-r3 { fill: #0178d4 } +.terminal-2118731365-r4 { fill: #e0e0e0 } +.terminal-2118731365-r5 { fill: #00ff00 } +.terminal-2118731365-r6 { fill: #000000 } +.terminal-2118731365-r7 { fill: #121212 } +.terminal-2118731365-r8 { fill: #e0e0e0;font-weight: bold } +.terminal-2118731365-r9 { fill: #e0e0e0;font-weight: bold;text-decoration: underline; } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - SearchApp + SearchApp - + - - Search Commands                                                                  - - -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - -🔎b - - -bar                                                                            -baz                                                                            -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - - - - - - - + + Search Commands                                                                  + + +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + +🔎b + + +bar                                                                            +baz                                                                            +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_auto_grid.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_auto_grid.svg index 45ed109155..cb49a7cd50 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_auto_grid.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_auto_grid.svg @@ -19,135 +19,135 @@ font-weight: 700; } - .terminal-2473255221-matrix { + .terminal-84069957-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2473255221-title { + .terminal-84069957-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2473255221-r1 { fill: #008000 } -.terminal-2473255221-r2 { fill: #c5c8c6 } -.terminal-2473255221-r3 { fill: #e0e0e0 } -.terminal-2473255221-r4 { fill: #121212 } -.terminal-2473255221-r5 { fill: #191919 } + .terminal-84069957-r1 { fill: #008000 } +.terminal-84069957-r2 { fill: #c5c8c6 } +.terminal-84069957-r3 { fill: #e0e0e0 } +.terminal-84069957-r4 { fill: #121212 } +.terminal-84069957-r5 { fill: #191919 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - GridApp + GridApp - + - - ┌──────────────────────────────────────────────────────────────────────────────┐ -foo         ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -Longer label▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -└──────────────────────────────────────────────────────────────────────────────┘ -┌──────────────────────────────────────────────────────────────────────────────┐ -foo▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -Longer label▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -└──────────────────────────────────────────────────────────────────────────────┘ -┌──────────────────────────────────────────────────────────────────────────────┐ -foo bar foo bar foo bar foo ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -bar foo bar foo bar foo bar  -foo bar foo bar foo bar ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -Longer label                  ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -└──────────────────────────────────────────────────────────────────────────────┘ + + ┌──────────────────────────────────────────────────────────────────────────────┐ +foo         ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +Longer label▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +└──────────────────────────────────────────────────────────────────────────────┘ +┌──────────────────────────────────────────────────────────────────────────────┐ +foo▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +Longer label▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +└──────────────────────────────────────────────────────────────────────────────┘ +┌──────────────────────────────────────────────────────────────────────────────┐ +foo bar foo bar foo bar foo ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +bar foo bar foo bar foo bar  +foo bar foo bar foo bar ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +Longer label                  ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +└──────────────────────────────────────────────────────────────────────────────┘ diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_auto_width_input.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_auto_width_input.svg index f6cb5271b6..d38c62c1bd 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_auto_width_input.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_auto_width_input.svg @@ -19,136 +19,136 @@ font-weight: 700; } - .terminal-4171447127-matrix { + .terminal-1608004871-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-4171447127-title { + .terminal-1608004871-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-4171447127-r1 { fill: #c5c8c6 } -.terminal-4171447127-r2 { fill: #e0e0e0 } -.terminal-4171447127-r3 { fill: #121212 } -.terminal-4171447127-r4 { fill: #0178d4 } -.terminal-4171447127-r5 { fill: #495259 } -.terminal-4171447127-r6 { fill: #ffa62b;font-weight: bold } + .terminal-1608004871-r1 { fill: #c5c8c6 } +.terminal-1608004871-r2 { fill: #e0e0e0 } +.terminal-1608004871-r3 { fill: #121212 } +.terminal-1608004871-r4 { fill: #0178d4 } +.terminal-1608004871-r5 { fill: #495259 } +.terminal-1608004871-r6 { fill: #ffa62b;font-weight: bold } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - InputWidthAutoApp + InputWidthAutoApp - + - - ⭘                           InputWidthAutoApp                        -▔▔▔▔▔▔▔▔▔▔ -Hello -▁▁▁▁▁▁▁▁▁▁ - - - - - - - - - - - - - - - - - - - -^p palette + + ⭘                           InputWidthAutoApp                        +▔▔▔▔▔▔▔▔▔▔ +Hello +▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + + + + + + + + + + +^p palette diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_blur_on_disabled.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_blur_on_disabled.svg index d6049dbc2c..6ecdc017a4 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_blur_on_disabled.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_blur_on_disabled.svg @@ -19,134 +19,134 @@ font-weight: 700; } - .terminal-3443652466-matrix { + .terminal-4138202186-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-3443652466-title { + .terminal-4138202186-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-3443652466-r1 { fill: #121212 } -.terminal-3443652466-r2 { fill: #141414 } -.terminal-3443652466-r3 { fill: #c5c8c6 } -.terminal-3443652466-r4 { fill: #a2a2a2 } -.terminal-3443652466-r5 { fill: #e0e0e0 } + .terminal-4138202186-r1 { fill: #121212 } +.terminal-4138202186-r2 { fill: #141414 } +.terminal-4138202186-r3 { fill: #c5c8c6 } +.terminal-4138202186-r4 { fill: #a2a2a2 } +.terminal-4138202186-r5 { fill: #e0e0e0 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - BlurApp + BlurApp - + - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -foo                                                                        -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - - - - - - - - - - - - - - - + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +foo                                                                        +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_check_consume_keys.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_check_consume_keys.svg index 4ee1043c10..97b7ba33f9 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_check_consume_keys.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_check_consume_keys.svg @@ -19,140 +19,140 @@ font-weight: 700; } - .terminal-1966019072-matrix { + .terminal-18154040-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1966019072-title { + .terminal-18154040-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1966019072-r1 { fill: #121212 } -.terminal-1966019072-r2 { fill: #0178d4 } -.terminal-1966019072-r3 { fill: #c5c8c6 } -.terminal-1966019072-r4 { fill: #797979 } -.terminal-1966019072-r5 { fill: #e0e0e0 } -.terminal-1966019072-r6 { fill: #191919 } -.terminal-1966019072-r7 { fill: #737373 } -.terminal-1966019072-r8 { fill: #1e1e1e } -.terminal-1966019072-r9 { fill: #495259 } -.terminal-1966019072-r10 { fill: #ffa62b;font-weight: bold } + .terminal-18154040-r1 { fill: #121212 } +.terminal-18154040-r2 { fill: #0178d4 } +.terminal-18154040-r3 { fill: #c5c8c6 } +.terminal-18154040-r4 { fill: #797979 } +.terminal-18154040-r5 { fill: #e0e0e0 } +.terminal-18154040-r6 { fill: #191919 } +.terminal-18154040-r7 { fill: #737373 } +.terminal-18154040-r8 { fill: #1e1e1e } +.terminal-18154040-r9 { fill: #495259 } +.terminal-18154040-r10 { fill: #ffa62b;font-weight: bold } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - MyApp + MyApp - + - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -First Name -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -Last Name -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -▔▔▔▔▔▔▔▔ - -▁▁▁▁▁▁▁▁ - - - - - - - - - - - - - - -^p palette + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +First Name +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +Last Name +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔ + +▁▁▁▁▁▁▁▁ + + + + + + + + + + + + + + +^p palette diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_command_palette.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_command_palette.svg index cba485475e..c92c7f2d9d 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_command_palette.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_command_palette.svg @@ -19,138 +19,138 @@ font-weight: 700; } - .terminal-566941328-matrix { + .terminal-3720858904-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-566941328-title { + .terminal-3720858904-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-566941328-r1 { fill: #646464 } -.terminal-566941328-r2 { fill: #c5c8c6 } -.terminal-566941328-r3 { fill: #0178d4 } -.terminal-566941328-r4 { fill: #e0e0e0 } -.terminal-566941328-r5 { fill: #00ff00 } -.terminal-566941328-r6 { fill: #000000 } -.terminal-566941328-r7 { fill: #121212 } -.terminal-566941328-r8 { fill: #e0e0e0;font-weight: bold } -.terminal-566941328-r9 { fill: #e0e0e0;font-weight: bold;text-decoration: underline; } + .terminal-3720858904-r1 { fill: #646464 } +.terminal-3720858904-r2 { fill: #c5c8c6 } +.terminal-3720858904-r3 { fill: #0178d4 } +.terminal-3720858904-r4 { fill: #e0e0e0 } +.terminal-3720858904-r5 { fill: #00ff00 } +.terminal-3720858904-r6 { fill: #000000 } +.terminal-3720858904-r7 { fill: #121212 } +.terminal-3720858904-r8 { fill: #e0e0e0;font-weight: bold } +.terminal-3720858904-r9 { fill: #e0e0e0;font-weight: bold;text-decoration: underline; } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - CommandPaletteApp + CommandPaletteApp - + - - - - -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - -🔎A - - -  This is a test of this code 9                                                  -  This is a test of this code 8                                                  -  This is a test of this code 7                                                  -  This is a test of this code 6                                                  -  This is a test of this code 5                                                  -  This is a test of this code 4                                                  -  This is a test of this code 3                                                  -  This is a test of this code 2                                                  -  This is a test of this code 1                                                  -  This is a test of this code 0                                                  -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - + + + + +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + +🔎A + + +  This is a test of this code 9                                                  +  This is a test of this code 8                                                  +  This is a test of this code 7                                                  +  This is a test of this code 6                                                  +  This is a test of this code 5                                                  +  This is a test of this code 4                                                  +  This is a test of this code 3                                                  +  This is a test of this code 2                                                  +  This is a test of this code 1                                                  +  This is a test of this code 0                                                  +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_command_palette_discovery.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_command_palette_discovery.svg index 60c08e5cee..48821c2c91 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_command_palette_discovery.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_command_palette_discovery.svg @@ -19,138 +19,138 @@ font-weight: 700; } - .terminal-1531744096-matrix { + .terminal-3222636008-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1531744096-title { + .terminal-3222636008-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1531744096-r1 { fill: #646464 } -.terminal-1531744096-r2 { fill: #c5c8c6 } -.terminal-1531744096-r3 { fill: #0178d4 } -.terminal-1531744096-r4 { fill: #e0e0e0 } -.terminal-1531744096-r5 { fill: #00ff00 } -.terminal-1531744096-r6 { fill: #000000 } -.terminal-1531744096-r7 { fill: #121212 } -.terminal-1531744096-r8 { fill: #6d7479 } -.terminal-1531744096-r9 { fill: #e0e0e0;font-weight: bold } + .terminal-3222636008-r1 { fill: #646464 } +.terminal-3222636008-r2 { fill: #c5c8c6 } +.terminal-3222636008-r3 { fill: #0178d4 } +.terminal-3222636008-r4 { fill: #e0e0e0 } +.terminal-3222636008-r5 { fill: #00ff00 } +.terminal-3222636008-r6 { fill: #000000 } +.terminal-3222636008-r7 { fill: #121212 } +.terminal-3222636008-r8 { fill: #6d7479 } +.terminal-3222636008-r9 { fill: #e0e0e0;font-weight: bold } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - CommandPaletteApp + CommandPaletteApp - + - - - - -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - -🔎Search for commands… - - -  This is a test of this code 0                                                  -  This is a test of this code 1                                                  -  This is a test of this code 2                                                  -  This is a test of this code 3                                                  -  This is a test of this code 4                                                  -  This is a test of this code 5                                                  -  This is a test of this code 6                                                  -  This is a test of this code 7                                                  -  This is a test of this code 8                                                  -  This is a test of this code 9                                                  -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - + + + + +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + +🔎Search for commands… + + +  This is a test of this code 0                                                  +  This is a test of this code 1                                                  +  This is a test of this code 2                                                  +  This is a test of this code 3                                                  +  This is a test of this code 4                                                  +  This is a test of this code 5                                                  +  This is a test of this code 6                                                  +  This is a test of this code 7                                                  +  This is a test of this code 8                                                  +  This is a test of this code 9                                                  +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_example_dictionary.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_example_dictionary.svg index df1d21a58b..1faeefe670 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_example_dictionary.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_example_dictionary.svg @@ -19,135 +19,135 @@ font-weight: 700; } - .terminal-3533541262-matrix { + .terminal-576095766-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-3533541262-title { + .terminal-576095766-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-3533541262-r1 { fill: #e0e0e0 } -.terminal-3533541262-r2 { fill: #c5c8c6 } -.terminal-3533541262-r3 { fill: #242f38 } -.terminal-3533541262-r4 { fill: #0178d4 } -.terminal-3533541262-r5 { fill: #121212 } -.terminal-3533541262-r6 { fill: #797979 } + .terminal-576095766-r1 { fill: #e0e0e0 } +.terminal-576095766-r2 { fill: #c5c8c6 } +.terminal-576095766-r3 { fill: #242f38 } +.terminal-576095766-r4 { fill: #0178d4 } +.terminal-576095766-r5 { fill: #121212 } +.terminal-576095766-r6 { fill: #797979 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - DictionaryApp + DictionaryApp - + - - -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -Search for a word -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - - - - - - - - - - - - - - - - -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +Search for a word +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + + + + + + + + + + + + + + + + +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_help_panel.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_help_panel.svg index 39f191cb71..ea40e194ef 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_help_panel.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_help_panel.svg @@ -19,161 +19,160 @@ font-weight: 700; } - .terminal-3307307900-matrix { + .terminal-3974648907-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-3307307900-title { + .terminal-3974648907-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-3307307900-r1 { fill: #121212 } -.terminal-3307307900-r2 { fill: #0178d4 } -.terminal-3307307900-r3 { fill: #4f4f4f } -.terminal-3307307900-r4 { fill: #c5c8c6 } -.terminal-3307307900-r5 { fill: #fea62b;font-weight: bold } -.terminal-3307307900-r6 { fill: #e0e0e0 } -.terminal-3307307900-r7 { fill: #8d8d8d } + .terminal-3974648907-r1 { fill: #121212 } +.terminal-3974648907-r2 { fill: #0178d4 } +.terminal-3974648907-r3 { fill: #4f4f4f } +.terminal-3974648907-r4 { fill: #c5c8c6 } +.terminal-3974648907-r5 { fill: #fea62b;font-weight: bold } +.terminal-3974648907-r6 { fill: #e0e0e0 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - HelpPanelApp + HelpPanelApp - - - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -        ←Move cursor left   -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁       ^←Move cursor left a -word               -        →Move cursor right  -       ^→Move cursor right  -a word             -        ⌫Delete character   -left               -  home ^aGo to start        -   end ^eGo to end          -   del ^dDelete character   -right              -        ⏎Submit             -       ^wDelete left to     -start of word      -       ^uDelete all to the  -left               -       ^fDelete right to    -start of word      -       ^kDelete all to the  -right              - -      tabFocus Next         -shift+tabFocus Previous     - -       ^cQuit               -       ^ppalette Open  -command palette - + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +         ↑Scroll Up       +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁         ↓Scroll Down     +         ←Move cursor     +left            +         →Move cursor     +right           +   home ^aGo to start     +    end ^eGo to end       +      pgupPage Up         +      pgdnPage Down       +     ^pgupPage Left       +     ^pgdnPage Right      +   shift+←Move cursor     +left and select +        ^←Move cursor     +left a word     +  shift+^←Move cursor     +left a word and +select          +   shift+→Move cursor     +right and       +select          +        ^→Move cursor     +right a word    +  shift+^→Move cursor     +right a word    +and select      +         ⌫Delete          +character left  diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_and_focus.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_and_focus.svg index 3561a95691..60366fbe9c 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_and_focus.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_and_focus.svg @@ -19,134 +19,134 @@ font-weight: 700; } - .terminal-1525652049-matrix { + .terminal-2998242737-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1525652049-title { + .terminal-2998242737-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1525652049-r1 { fill: #121212 } -.terminal-1525652049-r2 { fill: #191919 } -.terminal-1525652049-r3 { fill: #c5c8c6 } -.terminal-1525652049-r4 { fill: #e0e0e0 } -.terminal-1525652049-r5 { fill: #0178d4 } + .terminal-2998242737-r1 { fill: #121212 } +.terminal-2998242737-r2 { fill: #191919 } +.terminal-2998242737-r3 { fill: #c5c8c6 } +.terminal-2998242737-r4 { fill: #e0e0e0 } +.terminal-2998242737-r5 { fill: #0178d4 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - InputApp + InputApp - + - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -Darren                                                                     -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -Burns -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - - - - - - - - - - - - + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +Darren                                                                     +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +Burns +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + + + + + + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_cursor.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_cursor.svg new file mode 100644 index 0000000000..5086f54c9e --- /dev/null +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_cursor.svg @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + InputApp + + + + + + + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +こんにちは                                                                 +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +こんにち +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_initial_scroll.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_initial_scroll.svg new file mode 100644 index 0000000000..e7fb73aa58 --- /dev/null +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_initial_scroll.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + InputInitialScrollApp + + + + + + + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +the quick brow +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_percentage_width.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_percentage_width.svg index 9105a76248..ce82ac42e6 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_percentage_width.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_percentage_width.svg @@ -19,135 +19,135 @@ font-weight: 700; } - .terminal-2301157416-matrix { + .terminal-4155444696-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2301157416-title { + .terminal-4155444696-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2301157416-r1 { fill: #121212 } -.terminal-2301157416-r2 { fill: #e0e0e0 } -.terminal-2301157416-r3 { fill: #c5c8c6 } -.terminal-2301157416-r4 { fill: #ff0000 } -.terminal-2301157416-r5 { fill: #e0e0e0;font-weight: bold } + .terminal-4155444696-r1 { fill: #121212 } +.terminal-4155444696-r2 { fill: #e0e0e0 } +.terminal-4155444696-r3 { fill: #c5c8c6 } +.terminal-4155444696-r4 { fill: #ff0000 } +.terminal-4155444696-r5 { fill: #e0e0e0;font-weight: bold } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - InputVsTextArea + InputVsTextArea - - - - 01234567890123456789012345678901234567890123456789012345678901234567890123456789 -┌──────────────────────────────────────┐ - - - -└──────────────────────────────────────┘ -┌──────────────────────────────────────┐ - - - - -└──────────────────────────────────────┘ -┌──────────────────────────────────────┐ - - - - -└──────────────────────────────────────┘ -┌──────────────────────────────────────┐ - - Button  - - -└──────────────────────────────────────┘ + + + + 01234567890123456789012345678901234567890123456789012345678901234567890123456789 +┌──────────────────────────────────────┐ + + + +└──────────────────────────────────────┘ +┌──────────────────────────────────────┐ + + + + +└──────────────────────────────────────┘ +┌──────────────────────────────────────┐ + + + + +└──────────────────────────────────────┘ +┌──────────────────────────────────────┐ + + Button  + + +└──────────────────────────────────────┘ diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_scrolls_to_cursor.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_scrolls_to_cursor.svg new file mode 100644 index 0000000000..6ce95f3575 --- /dev/null +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_scrolls_to_cursor.svg @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + InputScrollingApp + + + + + + + + + + ▔▔▔▔▔▔▔▔▔▔ + ちは  +▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔ +56789 +▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_selection.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_selection.svg new file mode 100644 index 0000000000..21ee18096d --- /dev/null +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_selection.svg @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + InputSelectionApp + + + + + + + + + + ▔▔▔▔▔▔▔▔▔▔ +BCDEF +▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_setting_value.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_setting_value.svg new file mode 100644 index 0000000000..f9bf6c327d --- /dev/null +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_setting_value.svg @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + InputApp + + + + + + + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +default +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +set attribute in compose                                                   +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +Placeholder, no value +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +set in on_mount                                                            +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_suggestions.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_suggestions.svg index 36b75f3525..0bf720ec6b 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_suggestions.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_suggestions.svg @@ -19,136 +19,136 @@ font-weight: 700; } - .terminal-1684740891-matrix { + .terminal-1035141595-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1684740891-title { + .terminal-1035141595-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1684740891-r1 { fill: #121212 } -.terminal-1684740891-r2 { fill: #0178d4 } -.terminal-1684740891-r3 { fill: #c5c8c6 } -.terminal-1684740891-r4 { fill: #e0e0e0 } -.terminal-1684740891-r5 { fill: #121212;font-style: italic; } -.terminal-1684740891-r6 { fill: #ff0000;font-style: italic; } -.terminal-1684740891-r7 { fill: #191919 } + .terminal-1035141595-r1 { fill: #121212 } +.terminal-1035141595-r2 { fill: #0178d4 } +.terminal-1035141595-r3 { fill: #c5c8c6 } +.terminal-1035141595-r4 { fill: #e0e0e0 } +.terminal-1035141595-r5 { fill: #121212;font-style: italic; } +.terminal-1035141595-r6 { fill: #ff0000;font-style: italic; } +.terminal-1035141595-r7 { fill: #191919 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - FruitsApp + FruitsApp - + - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -strawberry -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -straw                                                                      -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -p                                                                          -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -b                                                                          -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -a                                                                          -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - - - + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +strawberry +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +straw                                                                      +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +p                                                                          +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +b                                                                          +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +a                                                                          +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_validation.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_validation.svg index c72c40b4a2..4bb28e0f53 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_validation.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_input_validation.svg @@ -19,137 +19,137 @@ font-weight: 700; } - .terminal-3009702123-matrix { + .terminal-1570722515-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-3009702123-title { + .terminal-1570722515-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-3009702123-r1 { fill: #e0e0e0 } -.terminal-3009702123-r2 { fill: #c5c8c6 } -.terminal-3009702123-r3 { fill: #121212 } -.terminal-3009702123-r4 { fill: #762b3d } -.terminal-3009702123-r5 { fill: #36794b } -.terminal-3009702123-r6 { fill: #b93c5b } -.terminal-3009702123-r7 { fill: #191919 } -.terminal-3009702123-r8 { fill: #737373 } + .terminal-1570722515-r1 { fill: #e0e0e0 } +.terminal-1570722515-r2 { fill: #c5c8c6 } +.terminal-1570722515-r3 { fill: #121212 } +.terminal-1570722515-r4 { fill: #762b3d } +.terminal-1570722515-r5 { fill: #36794b } +.terminal-1570722515-r6 { fill: #b93c5b } +.terminal-1570722515-r7 { fill: #191919 } +.terminal-1570722515-r8 { fill: #737373 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - InputApp + InputApp - + - - -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ --2                                                                     -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -3                                                                      -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ --2 -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -Enter a number between 1 and 5 -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - - + + +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +-2                                                                     +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +3                                                                      +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +-2 +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +Enter a number between 1 and 5 +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_layout_containers.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_layout_containers.svg index 4a2a93e807..d7a9d8825a 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_layout_containers.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_layout_containers.svg @@ -19,143 +19,143 @@ font-weight: 700; } - .terminal-2895197884-matrix { + .terminal-2364090908-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2895197884-title { + .terminal-2364090908-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2895197884-r1 { fill: #7ae998 } -.terminal-2895197884-r2 { fill: #e76580 } -.terminal-2895197884-r3 { fill: #121212 } -.terminal-2895197884-r4 { fill: #191919 } -.terminal-2895197884-r5 { fill: #c5c8c6 } -.terminal-2895197884-r6 { fill: #55c076;font-weight: bold } -.terminal-2895197884-r7 { fill: #f5e5e9;font-weight: bold } -.terminal-2895197884-r8 { fill: #e0e0e0 } -.terminal-2895197884-r9 { fill: #0a180e;font-weight: bold } -.terminal-2895197884-r10 { fill: #008139 } -.terminal-2895197884-r11 { fill: #780028 } -.terminal-2895197884-r12 { fill: #003054 } -.terminal-2895197884-r13 { fill: #000000 } + .terminal-2364090908-r1 { fill: #7ae998 } +.terminal-2364090908-r2 { fill: #e76580 } +.terminal-2364090908-r3 { fill: #121212 } +.terminal-2364090908-r4 { fill: #191919 } +.terminal-2364090908-r5 { fill: #c5c8c6 } +.terminal-2364090908-r6 { fill: #55c076;font-weight: bold } +.terminal-2364090908-r7 { fill: #f5e5e9;font-weight: bold } +.terminal-2364090908-r8 { fill: #e0e0e0 } +.terminal-2364090908-r9 { fill: #0a180e;font-weight: bold } +.terminal-2364090908-r10 { fill: #008139 } +.terminal-2364090908-r11 { fill: #780028 } +.terminal-2364090908-r12 { fill: #003054 } +.terminal-2364090908-r13 { fill: #000000 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - MyApp + MyApp - + - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - Accept  Decline  Accept  Decline  -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - - - - -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - Accept  Accept  -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - Decline  Decline  -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▆▆ -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -0                                 0 - -1000000                                 1000000                                + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + Accept  Decline  Accept  Decline  +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + Accept  Accept  +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + Decline  Decline  +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▆▆ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +0                                 0 + +1000000                                 1000000                                diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_markup_command_list.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_markup_command_list.svg index 3e2a84d61c..66eac747ca 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_markup_command_list.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_markup_command_list.svg @@ -19,141 +19,141 @@ font-weight: 700; } - .terminal-796303638-matrix { + .terminal-2832635806-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-796303638-title { + .terminal-2832635806-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-796303638-r1 { fill: #646464 } -.terminal-796303638-r2 { fill: #c5c8c6 } -.terminal-796303638-r3 { fill: #0178d4 } -.terminal-796303638-r4 { fill: #e0e0e0 } -.terminal-796303638-r5 { fill: #00ff00 } -.terminal-796303638-r6 { fill: #000000 } -.terminal-796303638-r7 { fill: #121212 } -.terminal-796303638-r8 { fill: #6d7479 } -.terminal-796303638-r9 { fill: #e0e0e0;font-weight: bold } -.terminal-796303638-r10 { fill: #98e024;font-weight: bold;text-decoration: underline; } -.terminal-796303638-r11 { fill: #a1a5a8 } -.terminal-796303638-r12 { fill: #f4005f;text-decoration: underline; } + .terminal-2832635806-r1 { fill: #646464 } +.terminal-2832635806-r2 { fill: #c5c8c6 } +.terminal-2832635806-r3 { fill: #0178d4 } +.terminal-2832635806-r4 { fill: #e0e0e0 } +.terminal-2832635806-r5 { fill: #00ff00 } +.terminal-2832635806-r6 { fill: #000000 } +.terminal-2832635806-r7 { fill: #121212 } +.terminal-2832635806-r8 { fill: #6d7479 } +.terminal-2832635806-r9 { fill: #e0e0e0;font-weight: bold } +.terminal-2832635806-r10 { fill: #98e024;font-weight: bold;text-decoration: underline; } +.terminal-2832635806-r11 { fill: #a1a5a8 } +.terminal-2832635806-r12 { fill: #f4005f;text-decoration: underline; } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - MyApp + MyApp - + - - - - -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - -🔎Search for commands… - - -  Hello World -Help text -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - - - - - - - + + + + +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + +🔎Search for commands… + + +  Hello World +Help text +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_masked_input.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_masked_input.svg index 60b0341821..342425934a 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_masked_input.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_masked_input.svg @@ -19,136 +19,136 @@ font-weight: 700; } - .terminal-3304533527-matrix { + .terminal-324016935-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-3304533527-title { + .terminal-324016935-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-3304533527-r1 { fill: #121212 } -.terminal-3304533527-r2 { fill: #b93c5b } -.terminal-3304533527-r3 { fill: #c5c8c6 } -.terminal-3304533527-r4 { fill: #e0e0e0 } -.terminal-3304533527-r5 { fill: #797979 } -.terminal-3304533527-r6 { fill: #191919 } -.terminal-3304533527-r7 { fill: #737373 } + .terminal-324016935-r1 { fill: #121212 } +.terminal-324016935-r2 { fill: #b93c5b } +.terminal-324016935-r3 { fill: #c5c8c6 } +.terminal-324016935-r4 { fill: #e0e0e0 } +.terminal-324016935-r5 { fill: #797979 } +.terminal-324016935-r6 { fill: #191919 } +.terminal-324016935-r7 { fill: #737373 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - TemplateApp + TemplateApp - + - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -ABC01-DE___-_____-_____ -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -YYYY-MM-DD -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - - - - - - - - - - - - + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +ABC01-DE___-_____-_____ +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +YYYY-MM-DD +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + + + + + + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_modal_dialog_bindings_input.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_modal_dialog_bindings_input.svg index ee2f5a5d5b..65aa707c03 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_modal_dialog_bindings_input.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_modal_dialog_bindings_input.svg @@ -19,140 +19,140 @@ font-weight: 700; } - .terminal-2884096318-matrix { + .terminal-918474262-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2884096318-title { + .terminal-918474262-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2884096318-r1 { fill: #e0e0e0 } -.terminal-2884096318-r2 { fill: #646464 } -.terminal-2884096318-r3 { fill: #c5c8c6 } -.terminal-2884096318-r4 { fill: #121212 } -.terminal-2884096318-r5 { fill: #191919 } -.terminal-2884096318-r6 { fill: #2d2d2d } -.terminal-2884096318-r7 { fill: #272727;font-weight: bold } -.terminal-2884096318-r8 { fill: #0d0d0d } -.terminal-2884096318-r9 { fill: #704d1c;font-weight: bold } -.terminal-2884096318-r10 { fill: #282b2e } + .terminal-918474262-r1 { fill: #e0e0e0 } +.terminal-918474262-r2 { fill: #646464 } +.terminal-918474262-r3 { fill: #c5c8c6 } +.terminal-918474262-r4 { fill: #121212 } +.terminal-918474262-r5 { fill: #191919 } +.terminal-918474262-r6 { fill: #2d2d2d } +.terminal-918474262-r7 { fill: #272727;font-weight: bold } +.terminal-918474262-r8 { fill: #0d0d0d } +.terminal-918474262-r9 { fill: #704d1c;font-weight: bold } +.terminal-918474262-r10 { fill: #282b2e } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - ModalApp + ModalApp - + - - Dialog                           ModalApp                            -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -hi!                                                                        -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - OK  -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - - - - - - - - - - - - ⏎ Open Dialog                                                      ^p palette + + Dialog                           ModalApp                            +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +hi!                                                                        +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + OK  +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + + + + + + + + ⏎ Open Dialog                                                      ^p palette diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_system_commands.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_system_commands.svg index dbb425da5e..d34346af86 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_system_commands.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_system_commands.svg @@ -19,164 +19,164 @@ font-weight: 700; } - .terminal-3076581726-matrix { + .terminal-196009958-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-3076581726-title { + .terminal-196009958-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-3076581726-r1 { fill: #121212 } -.terminal-3076581726-r2 { fill: #0b3a5f } -.terminal-3076581726-r3 { fill: #c5c8c6 } -.terminal-3076581726-r4 { fill: #e0e0e0 } -.terminal-3076581726-r5 { fill: #0178d4 } -.terminal-3076581726-r6 { fill: #00ff00 } -.terminal-3076581726-r7 { fill: #000000 } -.terminal-3076581726-r8 { fill: #6d7479 } -.terminal-3076581726-r9 { fill: #e0e0e0;font-weight: bold } -.terminal-3076581726-r10 { fill: #a1a5a8 } -.terminal-3076581726-r11 { fill: #646464 } + .terminal-196009958-r1 { fill: #121212 } +.terminal-196009958-r2 { fill: #0b3a5f } +.terminal-196009958-r3 { fill: #c5c8c6 } +.terminal-196009958-r4 { fill: #e0e0e0 } +.terminal-196009958-r5 { fill: #0178d4 } +.terminal-196009958-r6 { fill: #00ff00 } +.terminal-196009958-r7 { fill: #000000 } +.terminal-196009958-r8 { fill: #6d7479 } +.terminal-196009958-r9 { fill: #e0e0e0;font-weight: bold } +.terminal-196009958-r10 { fill: #a1a5a8 } +.terminal-196009958-r11 { fill: #646464 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - SimpleApp + SimpleApp - + - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - -🔎Search for commands… - - -  Change theme                                                                                       -Change the current theme -  Maximize                                                                                           -Maximize the focused widget -  Quit the application                                                                               -Quit the application as soon as possible -  Save screenshot                                                                                    -Save an SVG 'screenshot' of the current screen -  Show keys and help panel                                                                           -Show help for the focused widget and a summary of available keys -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - - - - - + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + +🔎Search for commands… + + +  Change theme                                                                                       +Change the current theme +  Maximize                                                                                           +Maximize the focused widget +  Quit the application                                                                               +Quit the application as soon as possible +  Save screenshot                                                                                    +Save an SVG 'screenshot' of the current screen +  Show keys and help panel                                                                           +Show help for the focused widget and a summary of available keys +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_textual_dev_easing_preview.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_textual_dev_easing_preview.svg index 3498ecdc0f..dc1e871e4e 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_textual_dev_easing_preview.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_textual_dev_easing_preview.svg @@ -19,146 +19,146 @@ font-weight: 700; } - .terminal-792837549-matrix { + .terminal-1734916741-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-792837549-title { + .terminal-1734916741-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-792837549-r1 { fill: #2d2d2d } -.terminal-792837549-r2 { fill: #121212 } -.terminal-792837549-r3 { fill: #c5c8c6 } -.terminal-792837549-r4 { fill: #272727;font-weight: bold } -.terminal-792837549-r5 { fill: #1b1b1b } -.terminal-792837549-r6 { fill: #e0e0e0 } -.terminal-792837549-r7 { fill: #0d0d0d } -.terminal-792837549-r8 { fill: #e0e0e0;font-weight: bold } -.terminal-792837549-r9 { fill: #000000 } -.terminal-792837549-r10 { fill: #1e1e1e } -.terminal-792837549-r11 { fill: #b93c5b } -.terminal-792837549-r12 { fill: #fea62b } -.terminal-792837549-r13 { fill: #211505;font-weight: bold } -.terminal-792837549-r14 { fill: #211505 } -.terminal-792837549-r15 { fill: #495259 } -.terminal-792837549-r16 { fill: #ffa62b;font-weight: bold } + .terminal-1734916741-r1 { fill: #2d2d2d } +.terminal-1734916741-r2 { fill: #121212 } +.terminal-1734916741-r3 { fill: #c5c8c6 } +.terminal-1734916741-r4 { fill: #272727;font-weight: bold } +.terminal-1734916741-r5 { fill: #1b1b1b } +.terminal-1734916741-r6 { fill: #e0e0e0 } +.terminal-1734916741-r7 { fill: #0d0d0d } +.terminal-1734916741-r8 { fill: #e0e0e0;font-weight: bold } +.terminal-1734916741-r9 { fill: #000000 } +.terminal-1734916741-r10 { fill: #1e1e1e } +.terminal-1734916741-r11 { fill: #b93c5b } +.terminal-1734916741-r12 { fill: #fea62b } +.terminal-1734916741-r13 { fill: #211505;font-weight: bold } +.terminal-1734916741-r14 { fill: #211505 } +.terminal-1734916741-r15 { fill: #495259 } +.terminal-1734916741-r16 { fill: #ffa62b;font-weight: bold } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - EasingApp + EasingApp - + - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - round ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁Animation Duration:1.0                        -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - out_sine  -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - out_quint  -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁Welcome to Textual! -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - out_quart I must not fear. -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁Fear is the  -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔mind-killer. - out_quad Fear is the  -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁little-death that  -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔brings total  - out_expo obliteration. -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁I will face my fear. -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔I will permit it to  - out_elastic pass over me and  -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁through me. -▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔And when it has gone  - out_cubic  -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁^p palette + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + round ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁Animation Duration:1.0                        +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + out_sine  +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + out_quint  +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁Welcome to Textual! +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + out_quart I must not fear. +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁Fear is the  +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔mind-killer. + out_quad Fear is the  +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁little-death that  +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔brings total  + out_expo obliteration. +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁I will face my fear. +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔I will permit it to  + out_elastic pass over me and  +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁through me. +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔And when it has gone  + out_cubic  +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁^p palette diff --git a/tests/snapshot_tests/snapshot_apps/input_suggestions.py b/tests/snapshot_tests/snapshot_apps/input_suggestions.py index 9955fa4175..f6d16ca9e6 100644 --- a/tests/snapshot_tests/snapshot_apps/input_suggestions.py +++ b/tests/snapshot_tests/snapshot_apps/input_suggestions.py @@ -15,7 +15,7 @@ class FruitsApp(App[None]): """ def compose(self) -> ComposeResult: - yield Input("straw", suggester=SuggestFromList(fruits)) + yield Input("straw", suggester=SuggestFromList(fruits), select_on_focus=False) yield Input("straw", suggester=SuggestFromList(fruits)) yield Input("p", suggester=SuggestFromList(fruits)) yield Input("b", suggester=SuggestFromList(fruits)) diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index caa74cb124..99d2e2523b 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -144,6 +144,96 @@ async def run_before(pilot): ) +def test_input_setting_value(snap_compare): + """Test that Inputs with different values are rendered correctly. + + The values of inputs should be (from top to bottom): "default", "set attribute in compose" + , "" (empty), a placeholder of 'Placeholder, no value', and "set in on_mount". + """ + + class InputApp(App[None]): + def compose(self) -> ComposeResult: + yield Input(value="default") + input2 = Input() + input2.value = "set attribute in compose" + yield input2 + yield Input() + yield Input(placeholder="Placeholder, no value") + yield Input(id="input3") + + def on_mount(self) -> None: + input3 = self.query_one("#input3", Input) + input3.value = "set in on_mount" + + assert snap_compare(InputApp()) + + +def test_input_cursor(snap_compare): + """The first input should say こんにちは. + The second input should say こんにちは, with a cursor on the final character (double width). + Note that this might render incorrectly in the SVG output - the letters may overlap.""" + + class InputApp(App[None]): + def compose(self) -> ComposeResult: + yield Input(value="こんにちは") + input = Input(value="こんにちは", select_on_focus=False) + input.focus() + input.action_cursor_left() + yield input + + assert snap_compare(InputApp()) + + +def test_input_scrolls_to_cursor(snap_compare): + """The input widget should scroll the cursor into view when it moves, + and this should account for different cell widths. + + Only the final two characters should be visible in the first input (ちは). + They might be overlapping in the SVG output. + + In the second input, we should only see numbers 5-9 inclusive, plus the cursor. + The number of cells to the right of the cursor should equal the number of cells + to the left of the number '5'. + """ + + class InputScrollingApp(App[None]): + CSS = "Input { width: 12; }" + + def compose(self) -> ComposeResult: + yield Input(id="input1") + yield Input(id="input2") + + assert snap_compare( + InputScrollingApp(), press=[*"こんにちは", "tab", *"0123456789"] + ) + + +def test_input_initial_scroll(snap_compare): + """When the input is smaller than its content, the start of the content should + be visible, not the end.""" + + class InputInitialScrollApp(App[None]): + AUTO_FOCUS = None + + def compose(self) -> ComposeResult: + yield Input(value="the quick brown fox jumps over the lazy dog") + + assert snap_compare(InputInitialScrollApp(), terminal_size=(20, 5)) + + +def test_input_selection(snap_compare): + """BCDEF should be visible, and DEF should be selected. The cursor should be + sitting above 'D'.""" + + class InputSelectionApp(App[None]): + CSS = "Input { width: 12; }" + + def compose(self) -> ComposeResult: + yield Input(id="input1") + + assert snap_compare(InputSelectionApp(), press=[*"ABCDEF", *("shift+left",) * 3]) + + def test_masked_input(snap_compare): async def run_before(pilot): pilot.app.query(Input).first().cursor_blink = False diff --git a/tests/test_masked_input.py b/tests/test_masked_input.py index 698d7f11c5..72b4d9dc09 100644 --- a/tests/test_masked_input.py +++ b/tests/test_masked_input.py @@ -18,7 +18,9 @@ def __init__(self, template: str, placeholder: str = ""): self.placeholder = placeholder def compose(self) -> ComposeResult: - yield MaskedInput(template=self.template, placeholder=self.placeholder) + yield MaskedInput( + template=self.template, placeholder=self.placeholder, select_on_focus=False + ) @on(MaskedInput.Changed) @on(MaskedInput.Submitted)