mirror of
https://github.com/rstudio/shiny.git
synced 2026-01-08 06:34:02 -05:00
feat: add shinyRemoveButton selectize.js option (for py-shiny) (#4276)
* fix: supply and retain default selectize.js plugins (for py-shiny) * `npm run build` (GitHub Actions) * Move more in a 'remove_button' attribute direction * `npm run build` (GitHub Actions) * Move to a JSON-only approach * `npm run build` (GitHub Actions) * Drop sticky update logic by always sending 'missing' value and resolving client-side * Cleanup * Don't mutate options; better typing pattern * `npm run build` (GitHub Actions) --------- Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
This commit is contained in:
@@ -2414,6 +2414,7 @@
|
||||
},
|
||||
JSON.parse(config.html())
|
||||
);
|
||||
options = this._addShinyRemoveButton(options, el.hasAttribute("multiple"));
|
||||
if (typeof config.data("nonempty") !== "undefined") {
|
||||
el.nonempty = true;
|
||||
options = import_jquery19.default.extend(options, {
|
||||
@@ -2450,6 +2451,34 @@
|
||||
}
|
||||
return control;
|
||||
}
|
||||
// Translate shinyRemoveButton option into selectize plugins
|
||||
_addShinyRemoveButton(options, multiple) {
|
||||
let removeButton = options.shinyRemoveButton;
|
||||
if (removeButton === void 0) {
|
||||
return options;
|
||||
}
|
||||
if (removeButton === "none") {
|
||||
removeButton = multiple ? "true" : "false";
|
||||
}
|
||||
if (removeButton === "false") {
|
||||
return options;
|
||||
}
|
||||
const plugins = [];
|
||||
if (removeButton === "both") {
|
||||
plugins.push("remove_button", "clear_button");
|
||||
} else if (removeButton === "true") {
|
||||
plugins.push(multiple ? "remove_button" : "clear_button");
|
||||
}
|
||||
return {
|
||||
...options,
|
||||
plugins: Array.from(
|
||||
/* @__PURE__ */ new Set([
|
||||
...Array.isArray(options.plugins) ? options.plugins : [],
|
||||
...plugins
|
||||
])
|
||||
)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// srcts/src/bindings/input/slider.ts
|
||||
|
||||
File diff suppressed because one or more lines are too long
2
inst/www/shared/shiny.min.js
vendored
2
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
@@ -13,9 +13,23 @@ type SelectInputReceiveMessageData = {
|
||||
value?: string;
|
||||
};
|
||||
|
||||
type SelectizeOptions = Selectize.IOptions<string, unknown>;
|
||||
type SelectizeInfo = Selectize.IApi<string, unknown> & {
|
||||
settings: SelectizeOptions;
|
||||
settings: Selectize.IOptions<string, unknown>;
|
||||
};
|
||||
|
||||
type SelectizeOptions = Selectize.IOptions<string, unknown> & {
|
||||
// Provide some stronger typing for the Selectize options
|
||||
labelField: "label";
|
||||
valueField: "value";
|
||||
searchField: ["label"];
|
||||
onItemRemove?: (value: string) => void;
|
||||
onDropdownClose?: () => void;
|
||||
};
|
||||
|
||||
// Adds a py-shiny specific "option" that makes the
|
||||
// input_selectize(remove_button) parameter possible
|
||||
type SelectizeShinyOptions = SelectizeOptions & {
|
||||
shinyRemoveButton?: "none" | "true" | "false" | "both";
|
||||
};
|
||||
|
||||
function getLabelNode(el: SelectHTMLElement): JQuery<HTMLElement> {
|
||||
@@ -244,13 +258,7 @@ class SelectInputBinding extends InputBinding {
|
||||
|
||||
if (config.length === 0) return undefined;
|
||||
|
||||
let options: SelectizeOptions & {
|
||||
labelField: "label";
|
||||
valueField: "value";
|
||||
searchField: ["label"];
|
||||
onItemRemove?: (value: string) => void;
|
||||
onDropdownClose?: () => void;
|
||||
} = $.extend(
|
||||
let options: SelectizeShinyOptions = $.extend(
|
||||
{
|
||||
labelField: "label",
|
||||
valueField: "value",
|
||||
@@ -259,6 +267,8 @@ class SelectInputBinding extends InputBinding {
|
||||
JSON.parse(config.html()),
|
||||
);
|
||||
|
||||
options = this._addShinyRemoveButton(options, el.hasAttribute("multiple"));
|
||||
|
||||
// selectize created from selectInput()
|
||||
if (typeof config.data("nonempty") !== "undefined") {
|
||||
el.nonempty = true;
|
||||
@@ -305,6 +315,44 @@ class SelectInputBinding extends InputBinding {
|
||||
|
||||
return control;
|
||||
}
|
||||
|
||||
// Translate shinyRemoveButton option into selectize plugins
|
||||
private _addShinyRemoveButton(
|
||||
options: SelectizeShinyOptions,
|
||||
multiple: boolean,
|
||||
): SelectizeOptions {
|
||||
let removeButton = options.shinyRemoveButton;
|
||||
if (removeButton === undefined) {
|
||||
return options;
|
||||
}
|
||||
|
||||
// None really means 'smart default'
|
||||
if (removeButton === "none") {
|
||||
removeButton = multiple ? "true" : "false";
|
||||
}
|
||||
|
||||
if (removeButton === "false") {
|
||||
return options;
|
||||
}
|
||||
|
||||
const plugins = [];
|
||||
if (removeButton === "both") {
|
||||
plugins.push("remove_button", "clear_button");
|
||||
} else if (removeButton === "true") {
|
||||
plugins.push(multiple ? "remove_button" : "clear_button");
|
||||
}
|
||||
|
||||
// Add plugins to existing plugins if not already present
|
||||
return {
|
||||
...options,
|
||||
plugins: Array.from(
|
||||
new Set([
|
||||
...(Array.isArray(options.plugins) ? options.plugins : []),
|
||||
...plugins,
|
||||
]),
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export { SelectInputBinding };
|
||||
|
||||
@@ -9,9 +9,8 @@ type SelectInputReceiveMessageData = {
|
||||
url?: string;
|
||||
value?: string;
|
||||
};
|
||||
type SelectizeOptions = Selectize.IOptions<string, unknown>;
|
||||
type SelectizeInfo = Selectize.IApi<string, unknown> & {
|
||||
settings: SelectizeOptions;
|
||||
settings: Selectize.IOptions<string, unknown>;
|
||||
};
|
||||
declare class SelectInputBinding extends InputBinding {
|
||||
find(scope: HTMLElement): JQuery<HTMLElement>;
|
||||
@@ -32,6 +31,7 @@ declare class SelectInputBinding extends InputBinding {
|
||||
unsubscribe(el: HTMLElement): void;
|
||||
initialize(el: SelectHTMLElement): void;
|
||||
protected _selectize(el: SelectHTMLElement, update?: boolean): SelectizeInfo | undefined;
|
||||
private _addShinyRemoveButton;
|
||||
}
|
||||
export { SelectInputBinding };
|
||||
export type { SelectInputReceiveMessageData };
|
||||
|
||||
Reference in New Issue
Block a user