mirror of
https://github.com/rstudio/shiny.git
synced 2026-01-11 07:58:11 -05:00
Compare commits
3 Commits
schloerke-
...
feat/input
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d563a00eb | ||
|
|
d4bf6aaab9 | ||
|
|
49c5d29003 |
@@ -1,7 +1,7 @@
|
||||
Package: shiny
|
||||
Type: Package
|
||||
Title: Web Application Framework for R
|
||||
Version: 1.10.0.9000
|
||||
Version: 1.10.0.9001
|
||||
Authors@R: c(
|
||||
person("Winston", "Chang", role = c("aut", "cre"), email = "winston@posit.co", comment = c(ORCID = "0000-0002-1576-2126")),
|
||||
person("Joe", "Cheng", role = "aut", email = "joe@posit.co"),
|
||||
|
||||
20
NEWS.md
20
NEWS.md
@@ -1,6 +1,20 @@
|
||||
# shiny (development version)
|
||||
|
||||
## New features and improvements
|
||||
## New features
|
||||
|
||||
* `textInput()`, `textAreaInput()`, `numericInput()` and `passwordInput()` all gain an `updateOn` option. `updateOn = "change"` is the default and previous behavior, where the input value updates immediately whenever the value changes. With `updateOn = "blur"`, the input value will update only when the text input loses focus or when the user presses Enter (or Cmd/Ctrl + Enter for `textAreaInput()`). (#4183)
|
||||
|
||||
* `textAreaInput()` gains a `autoresize` option, which automatically resizes the text area to fit its content.
|
||||
|
||||
* The `callback` argument of Shiny.js' `InputBinding.subscribe()` method gains support for a value of `"event"`. This makes it possible for an input binding to use event priority when updating the value (i.e., send immediately and always resend, even if the value hasn't changed).
|
||||
|
||||
## Changes
|
||||
|
||||
* Shiny no longer suspends input changes when _any_ `<input type="submit">` or `<button type="submit">` is on the page. Instead, it now only suspends when a `submitButton()` is present. If you have reason for creating a submit button from custom HTML, add a CSS class of `shiny-submit-button` to the button.
|
||||
|
||||
## Improvements
|
||||
|
||||
* When auto-reload is enabled, Shiny now reloads the entire app when support files, like Shiny modules, additional script files, or web assets, change. To enable auto-reload, call `devmode(TRUE)` to enable Shiny's developer mode, or set `options(shiny.autoreload = TRUE)` to specifically enable auto-reload. You can choose which files are watched for changes with the `shiny.autoreload.pattern` option. (#4184)
|
||||
|
||||
* When busy indicators are enabled (i.e., `useBusyIndicators()`), Shiny now:
|
||||
* Shows a spinner on recalculating htmlwidgets that have previously rendered an error (including `req()` and `validate()`). (#4172)
|
||||
@@ -11,10 +25,6 @@
|
||||
|
||||
* Shiny's Typescript assets are now compiled to ES2021 instead of ES5. (#4066)
|
||||
|
||||
* `textInput()`, `textAreaInput()`, `numericInput()` and `passwordInput()` all gain an `updateOn` option. `updateOn = "change"` is the default and previous behavior, where the input value updates immediately whenever the value changes. With `updateOn = "blur"`, the input value will update only when the text input loses focus or when the user presses Enter (or Cmd/Ctrl + Enter for `textAreaInput()`). (#4183)
|
||||
|
||||
* When auto-reload is enabled, Shiny now reloads the entire app when support files, like Shiny modules, additional script files, or web assets, change. To enable auto-reload, call `devmode(TRUE)` to enable Shiny's developer mode, or set `options(shiny.autoreload = TRUE)` to specifically enable auto-reload. You can choose which files are watched for changes with the `shiny.autoreload.pattern` option. (#4184)
|
||||
|
||||
## Bug fixes
|
||||
|
||||
* Fixed a bug with modals where calling `removeModal()` too quickly after `showModal()` would fail to remove the modal if the remove modal message was received while the modal was in the process of being revealed. (#4173)
|
||||
|
||||
@@ -57,7 +57,7 @@ submitButton <- function(text = "Apply Changes", icon = NULL, width = NULL) {
|
||||
div(
|
||||
tags$button(
|
||||
type="submit",
|
||||
class="btn btn-primary",
|
||||
class="btn btn-primary submit-button",
|
||||
style = css(width = validateCssUnit(width)),
|
||||
list(icon, text)
|
||||
)
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#' @param resize Which directions the textarea box can be resized. Can be one of
|
||||
#' `"both"`, `"none"`, `"vertical"`, and `"horizontal"`. The default, `NULL`,
|
||||
#' will use the client browser's default setting for resizing textareas.
|
||||
#' @param autoresize If `TRUE`, the textarea will automatically resize to fit
|
||||
#' the input text.
|
||||
#' @return A textarea input control that can be added to a UI definition.
|
||||
#'
|
||||
#' @family input elements
|
||||
@@ -52,6 +54,7 @@ textAreaInput <- function(
|
||||
placeholder = NULL,
|
||||
resize = NULL,
|
||||
...,
|
||||
autoresize = FALSE,
|
||||
updateOn = c("change", "blur")
|
||||
) {
|
||||
rlang::check_dots_empty()
|
||||
@@ -63,22 +66,27 @@ textAreaInput <- function(
|
||||
resize <- match.arg(resize, c("both", "none", "vertical", "horizontal"))
|
||||
}
|
||||
|
||||
style <- css(
|
||||
# The width is specified on the parent div.
|
||||
width = if (!is.null(width)) "100%",
|
||||
height = validateCssUnit(height),
|
||||
resize = resize
|
||||
)
|
||||
classes <- c("shiny-input-textarea", "form-control")
|
||||
if (autoresize) {
|
||||
classes <- c(classes, "textarea-autoresize")
|
||||
if (is.null(rows)) {
|
||||
rows <- 1
|
||||
}
|
||||
}
|
||||
|
||||
div(
|
||||
class = "form-group shiny-input-container",
|
||||
style = css(width = validateCssUnit(width)),
|
||||
shinyInputLabel(inputId, label),
|
||||
style = if (!is.null(width)) paste0("width: ", validateCssUnit(width), ";"),
|
||||
tags$textarea(
|
||||
id = inputId,
|
||||
class = "shiny-input-textarea form-control",
|
||||
class = classes,
|
||||
placeholder = placeholder,
|
||||
style = style,
|
||||
style = css(
|
||||
width = if (!is.null(width)) "100%",
|
||||
height = validateCssUnit(height),
|
||||
resize = resize
|
||||
),
|
||||
rows = rows,
|
||||
cols = cols,
|
||||
`data-update-on` = updateOn,
|
||||
|
||||
@@ -2196,6 +2196,55 @@
|
||||
return (0, import_jquery20.default)(scope).find("textarea");
|
||||
}
|
||||
};
|
||||
function onDelegatedEvent(eventName, selector, callback) {
|
||||
document.addEventListener(eventName, (e4) => {
|
||||
const e22 = e4;
|
||||
if (e22.target.matches(selector)) {
|
||||
callback(e22.target);
|
||||
}
|
||||
});
|
||||
}
|
||||
var textAreaIntersectionObserver = null;
|
||||
function callUpdateHeightWhenTargetIsVisible(target) {
|
||||
if (textAreaIntersectionObserver === null) {
|
||||
textAreaIntersectionObserver = new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (!entry.isIntersecting) {
|
||||
return;
|
||||
}
|
||||
textAreaIntersectionObserver?.unobserve(entry.target);
|
||||
updateHeight(entry.target);
|
||||
});
|
||||
});
|
||||
}
|
||||
textAreaIntersectionObserver.observe(target);
|
||||
}
|
||||
function updateHeight(target) {
|
||||
if (target.scrollHeight > 0) {
|
||||
target.style.height = "auto";
|
||||
target.style.height = target.scrollHeight + "px";
|
||||
} else {
|
||||
callUpdateHeightWhenTargetIsVisible(target);
|
||||
}
|
||||
}
|
||||
onDelegatedEvent(
|
||||
"input",
|
||||
"textarea.textarea-autoresize",
|
||||
(target) => {
|
||||
updateHeight(target);
|
||||
}
|
||||
);
|
||||
function updateOnLoad() {
|
||||
if (document.readyState === "loading") {
|
||||
setTimeout(updateOnLoad, 10);
|
||||
return;
|
||||
}
|
||||
const textAreas = document.querySelectorAll(
|
||||
"textarea.textarea-autoresize"
|
||||
);
|
||||
textAreas.forEach(updateHeight);
|
||||
}
|
||||
updateOnLoad();
|
||||
|
||||
// srcts/src/bindings/input/index.ts
|
||||
function initInputBindings() {
|
||||
@@ -5560,19 +5609,14 @@
|
||||
function isJQuery(value) {
|
||||
return Boolean(value && value.jquery);
|
||||
}
|
||||
function valueChangeCallback(inputs, binding, el, allowDeferred) {
|
||||
function valueChangeCallback(inputs, binding, el, priority) {
|
||||
let id = binding.getId(el);
|
||||
if (id) {
|
||||
const value = binding.getValue(el);
|
||||
const type = binding.getType(el);
|
||||
if (type)
|
||||
id = id + ":" + type;
|
||||
const opts = {
|
||||
priority: allowDeferred ? "deferred" : "immediate",
|
||||
binding,
|
||||
el
|
||||
};
|
||||
inputs.setInput(id, value, opts);
|
||||
inputs.setInput(id, value, { priority, binding, el });
|
||||
}
|
||||
}
|
||||
var bindingsRegistry = (() => {
|
||||
@@ -5687,8 +5731,9 @@ ${duplicateIdMsg}`;
|
||||
const thisCallback = function() {
|
||||
const thisBinding = binding;
|
||||
const thisEl = el;
|
||||
return function(allowDeferred) {
|
||||
valueChangeCallback(inputs, thisBinding, thisEl, allowDeferred);
|
||||
return function(priority) {
|
||||
const normalizedPriority = typeof priority !== "boolean" ? priority : priority ? "deferred" : "immediate";
|
||||
valueChangeCallback(inputs, thisBinding, thisEl, normalizedPriority);
|
||||
};
|
||||
}();
|
||||
binding.subscribe(el, thisCallback);
|
||||
@@ -7190,10 +7235,10 @@ ${duplicateIdMsg}`;
|
||||
const inputsRate = new InputRateDecorator(inputsEvent);
|
||||
const inputsDefer = new InputDeferDecorator(inputsEvent);
|
||||
let target;
|
||||
if ((0, import_jquery39.default)('input[type="submit"], button[type="submit"]').length > 0) {
|
||||
if (document.querySelector(".submit-button")) {
|
||||
target = inputsDefer;
|
||||
(0, import_jquery39.default)('input[type="submit"], button[type="submit"]').each(function() {
|
||||
(0, import_jquery39.default)(this).click(function(event) {
|
||||
document.querySelectorAll(".submit-button").forEach(function(x2) {
|
||||
x2.addEventListener("click", function(event) {
|
||||
event.preventDefault();
|
||||
inputsDefer.submit();
|
||||
});
|
||||
|
||||
File diff suppressed because one or more lines are too long
2
inst/www/shared/shiny.min.css
vendored
2
inst/www/shared/shiny.min.css
vendored
File diff suppressed because one or more lines are too long
38
inst/www/shared/shiny.min.js
vendored
38
inst/www/shared/shiny.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -384,6 +384,14 @@ html.autoreload-enabled #shiny-disconnected-overlay.reloading {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Styling for inputTextArea(autoresize=TRUE) */
|
||||
.textarea-autoresize textarea.form-control {
|
||||
padding: 5px 8px;
|
||||
resize: none;
|
||||
overflow-y: hidden;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
|
||||
#shiny-notification-panel {
|
||||
position: fixed;
|
||||
|
||||
@@ -15,6 +15,7 @@ textAreaInput(
|
||||
placeholder = NULL,
|
||||
resize = NULL,
|
||||
...,
|
||||
autoresize = FALSE,
|
||||
updateOn = c("change", "blur")
|
||||
)
|
||||
}
|
||||
@@ -52,6 +53,9 @@ will use the client browser's default setting for resizing textareas.}
|
||||
\item{...}{Ignored, included to require named arguments and for future
|
||||
feature expansion.}
|
||||
|
||||
\item{autoresize}{If \code{TRUE}, the textarea will automatically resize to fit
|
||||
the input text.}
|
||||
|
||||
\item{updateOn}{A character vector specifying when the input should be
|
||||
updated. Options are \code{"change"} (default) and \code{"blur"}. Use \code{"change"} to
|
||||
update the input immediately whenever the value changes. Use \code{"blur"}to
|
||||
|
||||
6
srcts/extras/textarea-autoresize.css
Normal file
6
srcts/extras/textarea-autoresize.css
Normal file
@@ -0,0 +1,6 @@
|
||||
.textarea-autoresize textarea.form-control {
|
||||
padding: 5px 8px;
|
||||
resize: none;
|
||||
overflow-y: hidden;
|
||||
height: auto;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { EventPriority } from "../../inputPolicies/inputPolicy";
|
||||
import type { RatePolicyModes } from "../../inputPolicies/inputRateDecorator";
|
||||
import type { BindScope } from "../../shiny/bind";
|
||||
|
||||
@@ -26,10 +27,16 @@ class InputBinding {
|
||||
el; // unused var
|
||||
}
|
||||
|
||||
// The callback method takes one argument, whose value is boolean. If true,
|
||||
// allow deferred (debounce or throttle) sending depending on the value of
|
||||
// getRatePolicy. If false, send value immediately. Default behavior is `false`
|
||||
subscribe(el: HTMLElement, callback: (value: boolean) => void): void {
|
||||
// Historically, the callback value could only be boolean. In this case:
|
||||
// * false: send value immediately (i.e., priority = "immediate")
|
||||
// * true: send value later (i.e., priority = "deferred")
|
||||
// * The input rate policy is also consulted on whether to debounce or throttle
|
||||
// In recent versions, the value can also be "event", meaning that the
|
||||
// value should be sent regardless of whether it has changed.
|
||||
subscribe(
|
||||
el: HTMLElement,
|
||||
callback: (value: EventPriority | boolean) => void
|
||||
): void {
|
||||
// empty
|
||||
el; // unused var
|
||||
callback; // unused var
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import $ from "jquery";
|
||||
import { $escape, hasDefinedProperty, updateLabel } from "../../utils";
|
||||
|
||||
import type { EventPriority } from "../../inputPolicies/inputPolicy";
|
||||
import { InputBinding } from "./inputBinding";
|
||||
|
||||
// interface TextHTMLElement extends NameValueHTMLElement {
|
||||
@@ -49,7 +50,10 @@ class TextInputBindingBase extends InputBinding {
|
||||
value;
|
||||
}
|
||||
|
||||
subscribe(el: TextHTMLElement, callback: (x: boolean) => void): void {
|
||||
subscribe(
|
||||
el: TextHTMLElement,
|
||||
callback: (x: EventPriority | boolean) => void
|
||||
): void {
|
||||
const $el = $(el);
|
||||
const updateOn = $el.data("update-on") || "change";
|
||||
|
||||
|
||||
@@ -2,11 +2,96 @@ import $ from "jquery";
|
||||
|
||||
import { TextInputBinding } from "./text";
|
||||
|
||||
class TextareaInputBinding extends TextInputBinding {
|
||||
export class TextareaInputBinding extends TextInputBinding {
|
||||
find(scope: HTMLElement): JQuery<HTMLElement> {
|
||||
// Inputs now also have the .shiny-input-textarea class
|
||||
return $(scope).find("textarea");
|
||||
}
|
||||
}
|
||||
|
||||
export { TextareaInputBinding };
|
||||
/*************************************************************
|
||||
* Code below this point is for textAreaInput(autoresize=TRUE)
|
||||
************************************************************/
|
||||
|
||||
interface DOMEvent<T extends EventTarget> extends Event {
|
||||
readonly target: T;
|
||||
}
|
||||
|
||||
function onDelegatedEvent(
|
||||
eventName: string,
|
||||
selector: string,
|
||||
callback: (target: HTMLTextAreaElement) => void
|
||||
) {
|
||||
document.addEventListener(eventName, (e) => {
|
||||
const e2 = e as DOMEvent<HTMLTextAreaElement>;
|
||||
if (e2.target.matches(selector)) {
|
||||
callback(e2.target);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Use a single intersectionObserver as they are slow to create / use.
|
||||
let textAreaIntersectionObserver: IntersectionObserver | null = null;
|
||||
|
||||
function callUpdateHeightWhenTargetIsVisible(target: HTMLTextAreaElement) {
|
||||
if (textAreaIntersectionObserver === null) {
|
||||
// Create a single observer to watch for the textarea becoming visible
|
||||
textAreaIntersectionObserver = new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
// Quit if the entry is not visible
|
||||
if (!entry.isIntersecting) {
|
||||
return;
|
||||
}
|
||||
// If the entry is visible (even if it's just a single pixel)
|
||||
// Stop observing the target
|
||||
textAreaIntersectionObserver?.unobserve(entry.target);
|
||||
|
||||
// Update the height of the textarea
|
||||
updateHeight(entry.target as HTMLTextAreaElement);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
textAreaIntersectionObserver.observe(target);
|
||||
}
|
||||
|
||||
function updateHeight(target: HTMLTextAreaElement) {
|
||||
if (target.scrollHeight > 0) {
|
||||
// Automatically resize the textarea to fit its content.
|
||||
target.style.height = "auto";
|
||||
target.style.height = target.scrollHeight + "px";
|
||||
} else {
|
||||
// The textarea is not visible on the page, therefore it has a 0 scroll height.
|
||||
|
||||
// If we should autoresize the text area height, then we can wait for the textarea to
|
||||
// become visible and call `updateHeight` again. Hopefully the scroll height is no
|
||||
// longer 0
|
||||
callUpdateHeightWhenTargetIsVisible(target);
|
||||
}
|
||||
}
|
||||
|
||||
// Update on change
|
||||
onDelegatedEvent(
|
||||
"input",
|
||||
"textarea.textarea-autoresize",
|
||||
(target: HTMLTextAreaElement) => {
|
||||
updateHeight(target);
|
||||
}
|
||||
);
|
||||
|
||||
// Update on load
|
||||
function updateOnLoad() {
|
||||
if (document.readyState === "loading") {
|
||||
// Document still loading, wait 10ms to check again.
|
||||
setTimeout(updateOnLoad, 10);
|
||||
return;
|
||||
}
|
||||
|
||||
// document.readyState in ["interactive", "complete"];\
|
||||
const textAreas = document.querySelectorAll(
|
||||
"textarea.textarea-autoresize"
|
||||
) as NodeListOf<HTMLTextAreaElement>;
|
||||
textAreas.forEach(updateHeight);
|
||||
}
|
||||
|
||||
updateOnLoad();
|
||||
|
||||
@@ -8,6 +8,7 @@ import type {
|
||||
InputRateDecorator,
|
||||
InputValidateDecorator,
|
||||
} from "../inputPolicies";
|
||||
import type { InputPolicyOpts } from "../inputPolicies/inputPolicy";
|
||||
import { shinyAppBindOutput, shinyAppUnbindOutput } from "./initedMethods";
|
||||
import { sendImageSizeFns } from "./sendImageSize";
|
||||
|
||||
@@ -27,7 +28,7 @@ function valueChangeCallback(
|
||||
inputs: InputValidateDecorator,
|
||||
binding: InputBinding,
|
||||
el: HTMLElement,
|
||||
allowDeferred: boolean
|
||||
priority: InputPolicyOpts["priority"]
|
||||
) {
|
||||
let id = binding.getId(el);
|
||||
|
||||
@@ -37,17 +38,7 @@ function valueChangeCallback(
|
||||
|
||||
if (type) id = id + ":" + type;
|
||||
|
||||
const opts: {
|
||||
priority: "deferred" | "immediate";
|
||||
binding: typeof binding;
|
||||
el: typeof el;
|
||||
} = {
|
||||
priority: allowDeferred ? "deferred" : "immediate",
|
||||
binding: binding,
|
||||
el: el,
|
||||
};
|
||||
|
||||
inputs.setInput(id, value, opts);
|
||||
inputs.setInput(id, value, { priority, binding, el });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,8 +263,17 @@ function bindInputs(
|
||||
const thisBinding = binding;
|
||||
const thisEl = el;
|
||||
|
||||
return function (allowDeferred: boolean) {
|
||||
valueChangeCallback(inputs, thisBinding, thisEl, allowDeferred);
|
||||
// Historically speaking, this callback has only accepted a boolean value,
|
||||
// but in recent versions it can also accept a input priority.
|
||||
return function (priority: InputPolicyOpts["priority"] | boolean) {
|
||||
const normalizedPriority =
|
||||
typeof priority !== "boolean"
|
||||
? priority
|
||||
: priority
|
||||
? "deferred"
|
||||
: "immediate";
|
||||
|
||||
valueChangeCallback(inputs, thisBinding, thisEl, normalizedPriority);
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
@@ -177,12 +177,12 @@ class ShinyClass {
|
||||
|
||||
let target: InputPolicy;
|
||||
|
||||
if ($('input[type="submit"], button[type="submit"]').length > 0) {
|
||||
if (document.querySelector(".submit-button")) {
|
||||
// If there is a submit button on the page, use defer decorator
|
||||
target = inputsDefer;
|
||||
|
||||
$('input[type="submit"], button[type="submit"]').each(function () {
|
||||
$(this).click(function (event) {
|
||||
document.querySelectorAll(".submit-button").forEach(function (x) {
|
||||
x.addEventListener("click", function (event) {
|
||||
event.preventDefault();
|
||||
inputsDefer.submit();
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { EventPriority } from "../../inputPolicies/inputPolicy";
|
||||
import type { RatePolicyModes } from "../../inputPolicies/inputRateDecorator";
|
||||
import type { BindScope } from "../../shiny/bind";
|
||||
declare class InputBinding {
|
||||
@@ -6,7 +7,7 @@ declare class InputBinding {
|
||||
getId(el: HTMLElement): string;
|
||||
getType(el: HTMLElement): string | null;
|
||||
getValue(el: HTMLElement): any;
|
||||
subscribe(el: HTMLElement, callback: (value: boolean) => void): void;
|
||||
subscribe(el: HTMLElement, callback: (value: EventPriority | boolean) => void): void;
|
||||
unsubscribe(el: HTMLElement): void;
|
||||
receiveMessage(el: HTMLElement, data: unknown): Promise<void> | void;
|
||||
getState(el: HTMLElement): unknown;
|
||||
|
||||
3
srcts/types/src/bindings/input/text.d.ts
vendored
3
srcts/types/src/bindings/input/text.d.ts
vendored
@@ -1,3 +1,4 @@
|
||||
import type { EventPriority } from "../../inputPolicies/inputPolicy";
|
||||
import { InputBinding } from "./inputBinding";
|
||||
type TextHTMLElement = HTMLInputElement;
|
||||
type TextReceiveMessageData = {
|
||||
@@ -10,7 +11,7 @@ declare class TextInputBindingBase extends InputBinding {
|
||||
getId(el: TextHTMLElement): string;
|
||||
getValue(el: TextHTMLElement): unknown;
|
||||
setValue(el: TextHTMLElement, value: unknown): void;
|
||||
subscribe(el: TextHTMLElement, callback: (x: boolean) => void): void;
|
||||
subscribe(el: TextHTMLElement, callback: (x: EventPriority | boolean) => void): void;
|
||||
unsubscribe(el: TextHTMLElement): void;
|
||||
receiveMessage(el: TextHTMLElement, data: unknown): void;
|
||||
getState(el: TextHTMLElement): unknown;
|
||||
|
||||
3
srcts/types/src/bindings/input/textarea.d.ts
vendored
3
srcts/types/src/bindings/input/textarea.d.ts
vendored
@@ -1,5 +1,4 @@
|
||||
import { TextInputBinding } from "./text";
|
||||
declare class TextareaInputBinding extends TextInputBinding {
|
||||
export declare class TextareaInputBinding extends TextInputBinding {
|
||||
find(scope: HTMLElement): JQuery<HTMLElement>;
|
||||
}
|
||||
export { TextareaInputBinding };
|
||||
|
||||
18
srcts/types/src/bindings/input/textsubmit.d.ts
vendored
Normal file
18
srcts/types/src/bindings/input/textsubmit.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import type { EventPriority } from "../../inputPolicies/inputPolicy";
|
||||
import { InputBinding } from "./inputBinding";
|
||||
type TextHTMLElement = HTMLInputElement;
|
||||
type TextSubmitReceiveMessageData = {
|
||||
value?: string;
|
||||
placeholder?: string;
|
||||
submit?: boolean;
|
||||
focus?: boolean;
|
||||
};
|
||||
declare class TextSubmitInputBinding extends InputBinding {
|
||||
find(scope: HTMLElement): JQuery<HTMLElement>;
|
||||
getValue(el: TextHTMLElement): string;
|
||||
setValue(el: TextHTMLElement, value: string): void;
|
||||
subscribe(el: TextHTMLElement, callback: (x: EventPriority | boolean) => void): void;
|
||||
unsubscribe(el: HTMLElement): void;
|
||||
receiveMessage(el: TextHTMLElement, data: TextSubmitReceiveMessageData): void;
|
||||
}
|
||||
export { TextSubmitInputBinding };
|
||||
Reference in New Issue
Block a user