Compare commits

...

7 Commits

Author SHA1 Message Date
Barret Schloerke
e1522af8cf Update build-docs-on-tag.yml 2025-10-01 15:55:09 -04:00
Barret Schloerke
abe4743a74 Update build-docs-on-tag.yml 2025-10-01 15:13:18 -04:00
Barret Schloerke
2af1fe8697 Use repository dispatch to reach the private repo 2025-10-01 15:06:47 -04:00
Barret Schloerke
93ee877838 Create build-docs-on-tag.yml 2025-10-01 14:38:16 -04:00
Winston Chang
b6e9e9d216 Update package.json for publishing (#4284)
* Update package.json for publishing

* Use custom readme file for npm

* Update repository URLs

* Script cleanup

* Use name @posit/shiny
2025-09-09 16:37:06 -05:00
Barret Schloerke
5ddb99a5b4 update docs (#4285) 2025-09-05 13:52:30 -04:00
Carson Sievert
f981ed6363 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>
2025-08-28 15:49:25 -05:00
15 changed files with 148 additions and 30 deletions

25
.github/workflows/build-docs-on-tag.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
name: Update website docs given new release tag
on:
push:
branches:
- build_docs
tags:
- "v*"
jobs:
trigger-build:
runs-on: ubuntu-latest
steps:
- name: Send repository dispatch event
uses: actions/github-script@v8
with:
github-token: ${{ secrets.SHINY_DEV_CENTER_GITHUB_TOKEN }}
script: |
await github.rest.repos.createDispatchEvent({
owner: 'rstudio',
repo: 'shiny-dev-center',
event_type: 'build-r-reference',
client_payload: {}
});

View File

@@ -126,7 +126,7 @@ Config/Needs/check: shinytest2
Config/testthat/edition: 3
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.2
RoxygenNote: 7.3.3
Collate:
'globals.R'
'app-state.R'

View File

@@ -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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -46,7 +46,7 @@ session to immediately unblock and carry on with other user interactions.
}
\examples{
\dontshow{if (rlang::is_interactive() && rlang::is_installed("mirai")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf}
\dontshow{if (rlang::is_interactive() && rlang::is_installed("mirai")) withAutoprint(\{ # examplesIf}
library(shiny)
library(bslib)
library(mirai)

View File

@@ -83,7 +83,7 @@ instead apply to the entire page, set \code{spinner_selector = 'html'} and
\code{fade_selector = 'html'}.
}
\examples{
\dontshow{if (rlang::is_interactive()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf}
\dontshow{if (rlang::is_interactive()) withAutoprint(\{ # examplesIf}
library(bslib)

View File

@@ -56,7 +56,7 @@ operations.
}
\examples{
\dontshow{if (interactive()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf}
\dontshow{if (interactive()) withAutoprint(\{ # examplesIf}
library(shiny)
ui <- fixedPage(

View File

@@ -38,7 +38,7 @@ Authors:
Other contributors:
\itemize{
\item Posit Software, PBC (03wc8by49) [copyright holder, funder]
\item Posit Software, PBC (\href{https://ror.org/03wc8by49}{ROR}) [copyright holder, funder]
\item jQuery Foundation (jQuery library and jQuery UI library) [copyright holder]
\item jQuery contributors (jQuery library; authors listed in inst/www/shared/jquery-AUTHORS.txt) [contributor, copyright holder]
\item jQuery UI contributors (jQuery UI library; authors listed in inst/www/shared/jqueryui/AUTHORS.txt) [contributor, copyright holder]

View File

@@ -35,7 +35,7 @@ automatically disabled when spinner(s) are active. When both \code{spinners} and
graying out of recalculating outputs).
}
\examples{
\dontshow{if (rlang::is_interactive()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf}
\dontshow{if (rlang::is_interactive()) withAutoprint(\{ # examplesIf}
library(bslib)

14
npm-README.md Normal file
View File

@@ -0,0 +1,14 @@
@posit/shiny
============
This npm package contains TypeScript type definitions for Shiny's client-side JavaScript libraries.
It does not include the Shiny framework itself, though that may change in the future.
[Shiny](https://github.com/rstudio/shiny) is a web application framework for both R and Python, developed by Posit PBC.
## Installation
```bash
npm install @posit/shiny
```

View File

@@ -1,17 +1,17 @@
{
"private": true,
"homepage": "https://shiny.rstudio.com",
"repository": "github:rstudio/shiny",
"name": "@types/rstudio-shiny",
"homepage": "https://shiny.posit.co",
"repository": {
"type": "git",
"url": "git+https://github.com/rstudio/shiny.git"
},
"name": "@posit/shiny",
"version": "1.11.1-alpha.9000",
"license": "GPL-3.0-only",
"main": "",
"browser": "",
"types": "srcts/types/extras/globalShiny.d.ts",
"files": [
"DESCRIPTION",
"LICENSE",
"NEWS.md",
"srcts/types/**/*.d.ts"
],
"engines": {
@@ -69,7 +69,9 @@
"build_types": "tsc -p tsconfig.json",
"coverage_detailed": "npx --yes type-check --detail",
"coverage": "type-coverage -p tsconfig.json --at-least 90",
"circular": "npx --yes dpdm --transform ./srcts/src/index.ts"
"circular": "npx --yes dpdm --transform ./srcts/src/index.ts",
"prepack": "cp README.md README-orig.md && cp npm-README.md README.md",
"postpack": "test -f README-orig.md && cp README-orig.md README.md && rm README-orig.md"
},
"prettier": {
"plugins": [

View File

@@ -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 };

View File

@@ -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 };