Compare commits

...

14 Commits

Author SHA1 Message Date
Garrick Aden-Buie
3654cc0882 feat(mock-session): Add removeInputs method 2025-09-23 15:49:42 -04:00
Garrick Aden-Buie
41f4558a3c feat(session): Add $removeInputs() method 2025-09-23 15:44:17 -04:00
Garrick Aden-Buie
f3264259b6 feat: give reactiveValues a remove attribute 2025-09-23 15:24:38 -04:00
Garrick Aden-Buie
5798efb992 feat(reactiveValues): Add $remove() method to remove a key from a reactive values object 2025-09-23 15:14:24 -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
Carson Sievert
6d6b0ea6f9 fix: add CSS workaround to hide all but the first selectize remove button (#4275)
* fix: add CSS workaround to hide all but the first selectize remove button

* Update news

* Apply suggestions from code review
2025-08-21 16:48:34 -05:00
Barret Schloerke
0e355ed25c preemptively run revdepcheck. 5 failures. 2025-08-18 09:10:19 -04:00
Barret Schloerke
80a9ff470c fix(scss): Remove updated scss files and restore R sass compilation (#4272)
* Revert changes in 8861645d99 from #4252

We compile from R sass. So we should be partial to R's compiler, no the latest in npm

* Restore original compile script (with message) that built using R-sass, not npm

* Add step in build command to update the sass output

* run new command
2025-08-14 16:03:48 -04:00
Barret Schloerke
ead0abcd62 bug(check): Update .Rbuildignore with new and removed files (#4270) 2025-08-04 23:17:45 -04:00
Barret Schloerke
7dcb54bc7e build(js): Migrate from yarn to npm (#4252) 2025-08-04 16:07:39 -04:00
Colin Gillespie
ae82850e1f docs: Update R supported versions (#4256) 2025-08-04 10:37:48 -04:00
Daniel Chen
0610d756a8 docs: update srcts/readme.md to shiny 1.11.1 (#4259) 2025-08-04 09:50:06 -04:00
180 changed files with 9095 additions and 12566 deletions

View File

@@ -21,19 +21,14 @@
^TODO-promises.md$
^manualtests$
^\.github$
^\.yarn$
^\.vscode$
^\.madgerc$
^\.prettierrc\.yml$
^jest\.config\.js$
^package\.json$
^tsconfig\.json$
^yarn\.lock$
^package-lock\.json$
^node_modules$
^coverage$
^.ignore$
^\.browserslistrc$
^\.eslintrc\.yml$
^\.yarnrc\.yml$
^eslint\.config\.mjs$
^_dev$
^.claude$

View File

@@ -1,8 +0,0 @@
# Browsers that we support
last 2 versions
not dead
> 0.2%
# > 1%
Firefox ESR
phantomjs 2.1
IE 11 # sorry

View File

@@ -1,110 +0,0 @@
root: true
env:
browser: true
es6: true
extends:
- 'eslint:recommended'
- 'plugin:@typescript-eslint/recommended'
- 'plugin:jest/recommended'
- 'plugin:prettier/recommended'
- 'plugin:jest-dom/recommended'
globals:
Atomics: readonly
SharedArrayBuffer: readonly
parser: '@typescript-eslint/parser'
parserOptions:
ecmaVersion: 2018
sourceType: module
project:
- './tsconfig.json'
ignorePatterns: # mirrors tsconfig.json's exclude
- '**/__tests__'
- '**/*.d.ts'
plugins:
- '@typescript-eslint'
- prettier
- jest-dom
- unicorn
rules:
"@typescript-eslint/explicit-function-return-type":
- off
"@typescript-eslint/no-explicit-any":
- off
"@typescript-eslint/explicit-module-boundary-types":
- error
default-case:
- error
linebreak-style:
- error
- unix
quotes:
- error
- double
- avoid-escape
semi:
- error
- always
dot-location:
- error
- property
camelcase:
# - error
- "off"
unicorn/filename-case:
- error
- case: camelCase
"@typescript-eslint/array-type":
- error
- default: array-simple
readonly: array-simple
"@typescript-eslint/consistent-indexed-object-style":
- error
- index-signature
"@typescript-eslint/sort-type-union-intersection-members":
- error
"@typescript-eslint/consistent-type-imports":
- error
"@typescript-eslint/no-floating-promises":
- error
"@typescript-eslint/naming-convention":
- error
- selector: default
format: [camelCase]
- selector: method
modifiers: [private]
format: [camelCase]
leadingUnderscore: require
- selector: method
modifiers: [protected]
format: [camelCase]
leadingUnderscore: require
- selector: variable
format: [camelCase]
trailingUnderscore: forbid
leadingUnderscore: forbid
- selector: parameter
format: [camelCase]
trailingUnderscore: allow
leadingUnderscore: forbid
- selector: [enum, enumMember]
format: [PascalCase]
- selector: typeLike
format: [PascalCase]
custom:
regex: "(t|T)ype$"
match: false

View File

@@ -5,8 +5,8 @@ echo "Updating package.json version to match DESCRIPTION Version"
Rscript ./tools/updatePackageJsonVersion.R
if [ -n "$(git status --porcelain package.json)" ]
then
echo "package.json has changed after running ./tools/updatePackageJsonVersion.R. Re-running 'yarn build'"
yarn build
echo "package.json has changed after running ./tools/updatePackageJsonVersion.R. Re-running 'npm run build'"
npm run build
git add ./inst package.json && git commit -m 'Sync package version (GitHub Actions)' || echo "No package version to commit"
else
echo "No package version difference detected; package.json is current."

View File

@@ -8,7 +8,7 @@ on:
pull_request:
branches: [main]
schedule:
- cron: '0 5 * * 1' # every monday
- cron: "0 5 * * 1" # every monday
name: Package checks
@@ -17,7 +17,5 @@ jobs:
uses: rstudio/shiny-workflows/.github/workflows/website.yaml@v1
routine:
uses: rstudio/shiny-workflows/.github/workflows/routine.yaml@v1
with:
node-version: "14.x"
R-CMD-check:
uses: rstudio/shiny-workflows/.github/workflows/R-CMD-check.yaml@v1

12
.gitignore vendored
View File

@@ -9,20 +9,16 @@
shinyapps/
README.html
.*.Rnb.cached
tools/yarn-error.log
/_dev/
.sass_cache_keys
# TypeScript / yarn
# TypeScript
/node_modules/
.cache
.yarn/*
!.yarn/releases
!.yarn/plugins
!.yarn/sdks
!.yarn/versions
.pnp.*
coverage/
madge.svg
# GHA remotes installation
.github/r-depends.rds
.claude/settings.local.json

View File

@@ -1,7 +1,5 @@
{
"search.exclude": {
"**/.yarn": true,
"**/.pnp.*": true
},
"prettier.prettierPath": "./node_modules/prettier",
"typescript.enablePromptUseWorkspaceTsdk": true,

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

@@ -1,10 +0,0 @@
nodeLinker: node-modules
plugins:
- path: .yarn/plugins/@yarnpkg/plugin-outdated.cjs
spec: "https://github.com/mskelton/yarn-plugin-outdated/raw/main/bundles/@yarnpkg/plugin-outdated.js"
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: "@yarnpkg/plugin-interactive-tools"
yarnPath: .yarn/releases/yarn-3.2.3.cjs
checksumBehavior: update

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

@@ -8,6 +8,8 @@
* `updateActionButton()`/`updateActionLink()` now correctly renders HTML content passed to the `label` argument. (#4249)
* Fixed an issue where `updateSelectizeInput(options = list(plugins="remove_button"))` could lead to multiple remove buttons. (#4275)
## Changes
* The return value of `actionButton()`/`actionLink()` changed slightly: `label` and `icon` are wrapped in an additional HTML container element. This allows for: 1. `updateActionButton()`/`updateActionLink()` to distinguish between the `label` and `icon` when making updates and 2. spacing between `label` and `icon` to be more easily customized via CSS.

View File

@@ -369,6 +369,29 @@ MockShinySession <- R6Class(
})
private$flush()
},
#' @description Removes inputs from the `session$inputs` object and flushes
#' the reactives.
#' @param inputIds Character vector of input ids to remove.
#' @examples
#' \dontrun{
#' session$setInputs(x=1, y=2)
#' session$removeInputs("x")
#' }
removeInputs = function(inputIds) {
is_clientdata <- grepl("^.clientdata_", inputIds)
if (any(is_clientdata)) {
abort(
"Cannot remove clientData inputs: ",
paste(inputIds[is_clientdata], collapse = ", ")
)
}
for (inputId in inputIds) {
private$.input$remove(inputId)
}
private$flush()
},
#' @description An internal method which shouldn't be used by others.
#' Schedules `callback` for execution after some number of `millis`

View File

@@ -398,8 +398,6 @@ ReactiveValues <- R6Class(
# invalidate all deps of `key`
domain <- getDefaultReactiveDomain()
hidden <- substr(key, 1, 1) == "."
key_exists <- .values$containsKey(key)
if (key_exists && !isTRUE(force) && .dedupe && identical(.values$get(key), value)) {
@@ -420,26 +418,15 @@ ReactiveValues <- R6Class(
.dependents$get(key)$invalidate()
}
# only invalidate if there are deps
if (!key_exists && isTRUE(.hasRetrieved$names)) {
rLog$valueChangeNames(.reactId, .values$keys(), domain)
.namesDeps$invalidate()
# invalidate names() or toList() if needed
if (!key_exists) {
private$invalidateNames(domain)
}
if (hidden) {
if (isTRUE(.hasRetrieved$asListAll)) {
rLog$valueChangeAsListAll(.reactId, .values$values(), domain)
.allValuesDeps$invalidate()
}
} else {
if (isTRUE(.hasRetrieved$asList)) {
react_vals <- .values$values()
react_vals <- react_vals[!grepl("^\\.", base::names(react_vals))]
# leave as is. both object would be registered to the listening object
rLog$valueChangeAsList(.reactId, react_vals, domain)
.valuesDeps$invalidate()
}
}
private$invalidateAsListAny(
all.names = substr(key, 1, 1) == ".",
domain = domain
)
invisible()
},
@@ -451,6 +438,21 @@ ReactiveValues <- R6Class(
})
},
remove = function(key) {
stopifnot(rlang::is_string(key))
if (!self$.values$containsKey(key)) {
return(invisible())
}
value <- self$.values$get(key)
self$.values$remove(key)
self$.nameOrder <- setdiff(self$.nameOrder, key)
private$invalidateNames()
private$invalidateAsListAny(all.names = substr(key, 1, 1) == ".")
invisible(value)
},
names = function() {
if (!isTRUE(.hasRetrieved$names)) {
domain <- getDefaultReactiveDomain()
@@ -529,7 +531,47 @@ ReactiveValues <- R6Class(
return(listValue)
}
),
private = list(
invalidateNames = function(domain = getDefaultReactiveDomain()) {
if (!isTRUE(self$.hasRetrieved$names)) {
return(invisible())
}
rLog$valueChangeNames(self$.reactId, self$.values$keys(), domain)
self$.namesDeps$invalidate()
},
invalidateAsListAny = function(
all.names,
domain = getDefaultReactiveDomain()
) {
if (isTRUE(all.names)) {
private$invalidateAsListAll(domain)
} else {
private$invalidateAsList(domain)
}
},
invalidateAsListAll = function(domain = getDefaultReactiveDomain()) {
if (!isTRUE(self$.hasRetrieved$asListAll)) {
return(invisible())
}
rLog$valueChangeAsListAll(self$.reactId, self$.values$values(), domain)
self$.allValuesDeps$invalidate()
},
invalidateAsList = function(domain = getDefaultReactiveDomain()) {
if (!isTRUE(self$.hasRetrieved$asList)) {
return(invisible())
}
react_vals <- self$.values$values()
react_vals <- react_vals[!grepl("^\\.", base::names(react_vals))]
# leave as is. both object would be registered to the listening object
rLog$valueChangeAsList(self$.reactId, react_vals, domain)
self$.valuesDeps$invalidate()
}
)
)
@@ -599,14 +641,15 @@ checkName <- function(x) {
# @param ns A namespace function (either `identity` or `NS(namespace)`)
.createReactiveValues <- function(values = NULL, readonly = FALSE,
ns = identity) {
structure(
list(
impl = values,
readonly = readonly,
ns = ns
),
class='reactivevalues'
class='reactivevalues',
remove = function(key) values$remove(key)
)
}

View File

@@ -2159,6 +2159,19 @@ ShinySession <- R6Class(
self$cycleStartAction(doManageInputs)
}
},
removeInputs = function(inputIds) {
is_clientdata <- grepl("^.clientdata_", inputIds)
if (any(is_clientdata)) {
abort(
"Cannot remove clientData inputs: ",
paste(inputIds[is_clientdata], collapse = ", ")
)
}
for (inputId in inputIds) {
private$.input$remove(inputId)
}
},
outputOptions = function(name, ...) {
# If no name supplied, return the list of options for all outputs
if (is.null(name))

View File

@@ -1,2 +1,2 @@
# Generated by tools/updateBootstrapDatepicker.R; do not edit by hand
version_bs_date_picker <- "1.9.0"
version_bs_date_picker <- "1.10.0"

View File

@@ -65,4 +65,4 @@ The shiny package as a whole is licensed under the GPLv3. See the [LICENSE](LICE
## R version support
Shiny is supported on the latest release version of R, as well as the previous four minor release versions of R. For example, if the latest release R version is 4.1, then that version is supported, as well as 4.0, 3.6, 3.5, and 3.4.
Shiny is supported on the latest release version of R, as well as the previous four minor release versions of R. For example, if the latest release R version is 4.3, then that version is supported, as well as 4.2, 4.1, 4.0, 3.6.

108
eslint.config.mjs Normal file
View File

@@ -0,0 +1,108 @@
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import prettier from "eslint-plugin-prettier";
import unicorn from "eslint-plugin-unicorn";
import globals from "globals";
import tsParser from "@typescript-eslint/parser";
import path from "node:path";
import { fileURLToPath } from "node:url";
import js from "@eslint/js";
import { FlatCompat } from "@eslint/eslintrc";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all
});
export default [{
ignores: ["**/*.d.ts"],
}, ...compat.extends(
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended",
), {
plugins: {
"@typescript-eslint": typescriptEslint,
prettier,
unicorn,
},
languageOptions: {
globals: {
...globals.browser,
Atomics: "readonly",
SharedArrayBuffer: "readonly",
},
parser: tsParser,
ecmaVersion: 2021,
sourceType: "module",
parserOptions: {
project: ["./tsconfig.json"],
},
},
rules: {
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/explicit-module-boundary-types": "error",
"default-case": ["error"],
"linebreak-style": ["error", "unix"],
quotes: ["error", "double", "avoid-escape"],
semi: ["error", "always"],
"dot-location": ["error", "property"],
camelcase: ["off"],
"unicorn/filename-case": ["error", {
case: "camelCase",
}],
"@typescript-eslint/array-type": ["error", {
default: "array-simple",
readonly: "array-simple",
}],
"@typescript-eslint/consistent-indexed-object-style": ["error", "index-signature"],
"@typescript-eslint/consistent-type-imports": "error",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/naming-convention": ["error", {
selector: "default",
format: ["camelCase"],
}, {
selector: "method",
modifiers: ["private"],
format: ["camelCase"],
leadingUnderscore: "require",
}, {
selector: "method",
modifiers: ["protected"],
format: ["camelCase"],
leadingUnderscore: "require",
}, {
selector: "variable",
format: ["camelCase"],
trailingUnderscore: "forbid",
leadingUnderscore: "forbid",
}, {
selector: "parameter",
format: ["camelCase"],
trailingUnderscore: "allow",
leadingUnderscore: "forbid",
}, {
selector: ["enum", "enumMember"],
format: ["PascalCase"],
}, {
selector: "typeLike",
format: ["PascalCase"],
custom: {
regex: "(t|T)ype$",
match: false,
},
}],
},
}];

View File

@@ -1,5 +1,5 @@
.datepicker {
border-radius: 0.25rem;
border-radius: 3px;
direction: ltr;
}
@@ -30,7 +30,7 @@
display: inline-block;
border-left: 7px solid transparent;
border-right: 7px solid transparent;
border-bottom: 7px solid rgba(0, 0, 0, 0.15);
border-bottom: 7px solid var(--bs-border-color-translucent);
border-top: 0;
border-bottom-color: rgba(0, 0, 0, 0.2);
position: absolute;
@@ -41,7 +41,7 @@
display: inline-block;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid #fff;
border-bottom: 6px solid var(--bs-body-bg);
border-top: 0;
position: absolute;
}
@@ -73,13 +73,13 @@
.datepicker-dropdown.datepicker-orient-top:before {
bottom: -7px;
border-bottom: 0;
border-top: 7px solid rgba(0, 0, 0, 0.15);
border-top: 7px solid var(--bs-border-color-translucent);
}
.datepicker-dropdown.datepicker-orient-top:after {
bottom: -6px;
border-bottom: 0;
border-top: 6px solid #fff;
border-top: 6px solid var(--bs-body-bg);
}
.datepicker table {
@@ -105,64 +105,64 @@
}
.datepicker table tr td.old, .datepicker table tr td.new {
color: #6c757d;
color: #707782;
}
.datepicker table tr td.day:hover, .datepicker table tr td.focused {
color: #000;
background: #e9e9ea;
background: #e8e9e9;
cursor: pointer;
}
.datepicker table tr td.disabled, .datepicker table tr td.disabled:hover {
background: none;
color: #6c757d;
color: #707782;
cursor: default;
}
.datepicker table tr td.highlighted {
color: #000;
background-color: #d1ecf1;
border-color: #83ccd9;
background-color: #cdf4fa;
border-color: #70e0f1;
border-radius: 0;
}
.datepicker table tr td.highlighted:focus, .datepicker table tr td.highlighted.focus {
color: #000;
background-color: #bcd4d9;
border-color: #6299a3;
background-color: #b9dce1;
border-color: #54a8b5;
}
.datepicker table tr td.highlighted:hover {
color: #000;
background-color: #697679;
border-color: #73b3bf;
background-color: #677a7d;
border-color: #63c5d4;
}
.datepicker table tr td.highlighted:active, .datepicker table tr td.highlighted.active {
color: #000;
background-color: #bcd4d9;
border-color: #73b3bf;
background-color: #b9dce1;
border-color: #63c5d4;
}
.datepicker table tr td.highlighted:active:hover, .datepicker table tr td.highlighted:active:focus, .datepicker table tr td.highlighted.focus:active, .datepicker table tr td.highlighted.active:hover, .datepicker table tr td.highlighted.active:focus, .datepicker table tr td.highlighted.active.focus {
.datepicker table tr td.highlighted:active:hover, .datepicker table tr td.highlighted:active:focus, .datepicker table tr td.highlighted:active.focus, .datepicker table tr td.highlighted.active:hover, .datepicker table tr td.highlighted.active:focus, .datepicker table tr td.highlighted.active.focus {
color: #000;
background-color: #adc4c8;
border-color: #6299a3;
background-color: #aacbd0;
border-color: #54a8b5;
}
.datepicker table tr td.highlighted.disabled:hover, .datepicker table tr td.highlighted.disabled:focus, .datepicker table tr td.highlighted.disabled.focus, .datepicker table tr td.highlighted[disabled]:hover, .datepicker table tr td.highlighted[disabled]:focus, .datepicker table tr td.highlighted.focus[disabled], fieldset[disabled] .datepicker table tr td.highlighted:hover, fieldset[disabled] .datepicker table tr td.highlighted:focus, fieldset[disabled] .datepicker table tr td.highlighted.focus {
background-color: #d1ecf1;
border-color: #83ccd9;
.datepicker table tr td.highlighted.disabled:hover, .datepicker table tr td.highlighted.disabled:focus, .datepicker table tr td.highlighted.disabled.focus, .datepicker table tr td.highlighted[disabled]:hover, .datepicker table tr td.highlighted[disabled]:focus, .datepicker table tr td.highlighted[disabled].focus, fieldset[disabled] .datepicker table tr td.highlighted:hover, fieldset[disabled] .datepicker table tr td.highlighted:focus, fieldset[disabled] .datepicker table tr td.highlighted.focus {
background-color: #cdf4fa;
border-color: #70e0f1;
}
.datepicker table tr td.highlighted.focused {
background: #aadce5;
background: #9feaf5;
}
.datepicker table tr td.highlighted.disabled, .datepicker table tr td.highlighted.disabled:active {
background: #d1ecf1;
color: #6c757d;
background: #cdf4fa;
color: #707782;
}
.datepicker table tr td.today {
@@ -189,13 +189,13 @@
border-color: #e0a12d;
}
.datepicker table tr td.today:active:hover, .datepicker table tr td.today:active:focus, .datepicker table tr td.today.focus:active, .datepicker table tr td.today.active:hover, .datepicker table tr td.today.active:focus, .datepicker table tr td.today.active.focus {
.datepicker table tr td.today:active:hover, .datepicker table tr td.today:active:focus, .datepicker table tr td.today:active.focus, .datepicker table tr td.today.active:hover, .datepicker table tr td.today.active:focus, .datepicker table tr td.today.active.focus {
color: #000;
background-color: #d4b67f;
border-color: #bf8926;
}
.datepicker table tr td.today.disabled:hover, .datepicker table tr td.today.disabled:focus, .datepicker table tr td.today.disabled.focus, .datepicker table tr td.today[disabled]:hover, .datepicker table tr td.today[disabled]:focus, .datepicker table tr td.today.focus[disabled], fieldset[disabled] .datepicker table tr td.today:hover, fieldset[disabled] .datepicker table tr td.today:focus, fieldset[disabled] .datepicker table tr td.today.focus {
.datepicker table tr td.today.disabled:hover, .datepicker table tr td.today.disabled:focus, .datepicker table tr td.today.disabled.focus, .datepicker table tr td.today[disabled]:hover, .datepicker table tr td.today[disabled]:focus, .datepicker table tr td.today[disabled].focus, fieldset[disabled] .datepicker table tr td.today:hover, fieldset[disabled] .datepicker table tr td.today:focus, fieldset[disabled] .datepicker table tr td.today.focus {
background-color: #ffdb99;
border-color: #ffb733;
}
@@ -206,96 +206,96 @@
.datepicker table tr td.today.disabled, .datepicker table tr td.today.disabled:active {
background: #ffdb99;
color: #6c757d;
color: #707782;
}
.datepicker table tr td.range {
color: #000;
background-color: #e9e9ea;
border-color: #b5b5b8;
background-color: #e8e9e9;
border-color: #b4b7b7;
border-radius: 0;
}
.datepicker table tr td.range:focus, .datepicker table tr td.range.focus {
color: #000;
background-color: #d2d2d3;
border-color: #88888a;
background-color: #d1d2d2;
border-color: #878989;
}
.datepicker table tr td.range:hover {
color: #000;
background-color: #757575;
border-color: #9f9fa2;
background-color: #747575;
border-color: #9ea1a1;
}
.datepicker table tr td.range:active, .datepicker table tr td.range.active {
color: #000;
background-color: #d2d2d3;
border-color: #9f9fa2;
background-color: #d1d2d2;
border-color: #9ea1a1;
}
.datepicker table tr td.range:active:hover, .datepicker table tr td.range:active:focus, .datepicker table tr td.range.focus:active, .datepicker table tr td.range.active:hover, .datepicker table tr td.range.active:focus, .datepicker table tr td.range.active.focus {
.datepicker table tr td.range:active:hover, .datepicker table tr td.range:active:focus, .datepicker table tr td.range:active.focus, .datepicker table tr td.range.active:hover, .datepicker table tr td.range.active:focus, .datepicker table tr td.range.active.focus {
color: #000;
background-color: #c1c1c2;
border-color: #88888a;
background-color: #c1c1c1;
border-color: #878989;
}
.datepicker table tr td.range.disabled:hover, .datepicker table tr td.range.disabled:focus, .datepicker table tr td.range.disabled.focus, .datepicker table tr td.range[disabled]:hover, .datepicker table tr td.range[disabled]:focus, .datepicker table tr td.range.focus[disabled], fieldset[disabled] .datepicker table tr td.range:hover, fieldset[disabled] .datepicker table tr td.range:focus, fieldset[disabled] .datepicker table tr td.range.focus {
background-color: #e9e9ea;
border-color: #b5b5b8;
.datepicker table tr td.range.disabled:hover, .datepicker table tr td.range.disabled:focus, .datepicker table tr td.range.disabled.focus, .datepicker table tr td.range[disabled]:hover, .datepicker table tr td.range[disabled]:focus, .datepicker table tr td.range[disabled].focus, fieldset[disabled] .datepicker table tr td.range:hover, fieldset[disabled] .datepicker table tr td.range:focus, fieldset[disabled] .datepicker table tr td.range.focus {
background-color: #e8e9e9;
border-color: #b4b7b7;
}
.datepicker table tr td.range.focused {
background: #cfcfd1;
background: #ced0d0;
}
.datepicker table tr td.range.disabled, .datepicker table tr td.range.disabled:active {
background: #e9e9ea;
color: #6c757d;
background: #e8e9e9;
color: #707782;
}
.datepicker table tr td.range.highlighted {
color: #000;
background-color: #ddebee;
border-color: #99c3cc;
background-color: #dbeff2;
border-color: #90ced7;
}
.datepicker table tr td.range.highlighted:focus, .datepicker table tr td.range.highlighted.focus {
color: #000;
background-color: #c7d4d6;
border-color: #739299;
background-color: #c5d7da;
border-color: #6c9aa1;
}
.datepicker table tr td.range.highlighted:hover {
color: #000;
background-color: #6f7677;
border-color: #87acb4;
background-color: #6e7879;
border-color: #7fb5bd;
}
.datepicker table tr td.range.highlighted:active, .datepicker table tr td.range.highlighted.active {
color: #000;
background-color: #c7d4d6;
border-color: #87acb4;
background-color: #c5d7da;
border-color: #7fb5bd;
}
.datepicker table tr td.range.highlighted:active:hover, .datepicker table tr td.range.highlighted:active:focus, .datepicker table tr td.range.highlighted.focus:active, .datepicker table tr td.range.highlighted.active:hover, .datepicker table tr td.range.highlighted.active:focus, .datepicker table tr td.range.highlighted.active.focus {
.datepicker table tr td.range.highlighted:active:hover, .datepicker table tr td.range.highlighted:active:focus, .datepicker table tr td.range.highlighted:active.focus, .datepicker table tr td.range.highlighted.active:hover, .datepicker table tr td.range.highlighted.active:focus, .datepicker table tr td.range.highlighted.active.focus {
color: #000;
background-color: #b7c3c6;
border-color: #739299;
background-color: #b6c6c9;
border-color: #6c9aa1;
}
.datepicker table tr td.range.highlighted.disabled:hover, .datepicker table tr td.range.highlighted.disabled:focus, .datepicker table tr td.range.highlighted.disabled.focus, .datepicker table tr td.range.highlighted[disabled]:hover, .datepicker table tr td.range.highlighted[disabled]:focus, .datepicker table tr td.range.highlighted.focus[disabled], fieldset[disabled] .datepicker table tr td.range.highlighted:hover, fieldset[disabled] .datepicker table tr td.range.highlighted:focus, fieldset[disabled] .datepicker table tr td.range.highlighted.focus {
background-color: #ddebee;
border-color: #99c3cc;
.datepicker table tr td.range.highlighted.disabled:hover, .datepicker table tr td.range.highlighted.disabled:focus, .datepicker table tr td.range.highlighted.disabled.focus, .datepicker table tr td.range.highlighted[disabled]:hover, .datepicker table tr td.range.highlighted[disabled]:focus, .datepicker table tr td.range.highlighted[disabled].focus, fieldset[disabled] .datepicker table tr td.range.highlighted:hover, fieldset[disabled] .datepicker table tr td.range.highlighted:focus, fieldset[disabled] .datepicker table tr td.range.highlighted.focus {
background-color: #dbeff2;
border-color: #90ced7;
}
.datepicker table tr td.range.highlighted.focused {
background: #bbd7dd;
background: #b6dee4;
}
.datepicker table tr td.range.highlighted.disabled, .datepicker table tr td.range.highlighted.disabled:active {
background: #ddebee;
color: #6c757d;
background: #dbeff2;
color: #707782;
}
.datepicker table tr td.range.today {
@@ -322,92 +322,92 @@
border-color: #d08d14;
}
.datepicker table tr td.range.today:active:hover, .datepicker table tr td.range.today:active:focus, .datepicker table tr td.range.today.focus:active, .datepicker table tr td.range.today.active:hover, .datepicker table tr td.range.today.active:focus, .datepicker table tr td.range.today.active.focus {
.datepicker table tr td.range.today:active:hover, .datepicker table tr td.range.today:active:focus, .datepicker table tr td.range.today:active.focus, .datepicker table tr td.range.today.active:hover, .datepicker table tr td.range.today.active:focus, .datepicker table tr td.range.today.active.focus {
color: #000;
background-color: #cba561;
border-color: #b17811;
}
.datepicker table tr td.range.today.disabled:hover, .datepicker table tr td.range.today.disabled:focus, .datepicker table tr td.range.today.disabled.focus, .datepicker table tr td.range.today[disabled]:hover, .datepicker table tr td.range.today[disabled]:focus, .datepicker table tr td.range.today.focus[disabled], fieldset[disabled] .datepicker table tr td.range.today:hover, fieldset[disabled] .datepicker table tr td.range.today:focus, fieldset[disabled] .datepicker table tr td.range.today.focus {
.datepicker table tr td.range.today.disabled:hover, .datepicker table tr td.range.today.disabled:focus, .datepicker table tr td.range.today.disabled.focus, .datepicker table tr td.range.today[disabled]:hover, .datepicker table tr td.range.today[disabled]:focus, .datepicker table tr td.range.today[disabled].focus, fieldset[disabled] .datepicker table tr td.range.today:hover, fieldset[disabled] .datepicker table tr td.range.today:focus, fieldset[disabled] .datepicker table tr td.range.today.focus {
background-color: #f4c775;
border-color: #eca117;
}
.datepicker table tr td.range.today.disabled, .datepicker table tr td.range.today.disabled:active {
background: #f4c775;
color: #6c757d;
color: #707782;
}
.datepicker table tr td.selected, .datepicker table tr td.selected.highlighted {
color: #fff;
background-color: #898b8d;
border-color: #6b6e71;
color: #000;
background-color: #878889;
border-color: #606060;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.datepicker table tr td.selected:focus, .datepicker table tr td.selected.focus, .datepicker table tr td.selected.highlighted:focus, .datepicker table tr td.selected.highlighted.focus {
color: #fff;
background-color: #959798;
border-color: #909295;
color: #000;
background-color: #7a7a7b;
border-color: #484848;
}
.datepicker table tr td.selected:hover, .datepicker table tr td.selected.highlighted:hover {
color: #fff;
background-color: #c4c5c6;
border-color: #7d7f82;
color: #000;
background-color: #444445;
border-color: #545454;
}
.datepicker table tr td.selected:active, .datepicker table tr td.selected.active, .datepicker table tr td.selected.highlighted:active, .datepicker table tr td.selected.highlighted.active {
color: #fff;
background-color: #959798;
border-color: #7d7f82;
color: #000;
background-color: #7a7a7b;
border-color: #545454;
}
.datepicker table tr td.selected:active:hover, .datepicker table tr td.selected:active:focus, .datepicker table tr td.selected.focus:active, .datepicker table tr td.selected.active:hover, .datepicker table tr td.selected.active:focus, .datepicker table tr td.selected.active.focus, .datepicker table tr td.selected.highlighted:active:hover, .datepicker table tr td.selected.highlighted:active:focus, .datepicker table tr td.selected.highlighted.focus:active, .datepicker table tr td.selected.highlighted.active:hover, .datepicker table tr td.selected.highlighted.active:focus, .datepicker table tr td.selected.highlighted.active.focus {
color: #fff;
background-color: #9d9fa0;
border-color: #909295;
.datepicker table tr td.selected:active:hover, .datepicker table tr td.selected:active:focus, .datepicker table tr td.selected:active.focus, .datepicker table tr td.selected.active:hover, .datepicker table tr td.selected.active:focus, .datepicker table tr td.selected.active.focus, .datepicker table tr td.selected.highlighted:active:hover, .datepicker table tr td.selected.highlighted:active:focus, .datepicker table tr td.selected.highlighted:active.focus, .datepicker table tr td.selected.highlighted.active:hover, .datepicker table tr td.selected.highlighted.active:focus, .datepicker table tr td.selected.highlighted.active.focus {
color: #000;
background-color: #707172;
border-color: #484848;
}
.datepicker table tr td.selected.disabled:hover, .datepicker table tr td.selected.disabled:focus, .datepicker table tr td.selected.disabled.focus, .datepicker table tr td.selected[disabled]:hover, .datepicker table tr td.selected[disabled]:focus, .datepicker table tr td.selected.focus[disabled], fieldset[disabled] .datepicker table tr td.selected:hover, fieldset[disabled] .datepicker table tr td.selected:focus, fieldset[disabled] .datepicker table tr td.selected.focus, .datepicker table tr td.selected.highlighted.disabled:hover, .datepicker table tr td.selected.highlighted.disabled:focus, .datepicker table tr td.selected.highlighted.disabled.focus, .datepicker table tr td.selected.highlighted[disabled]:hover, .datepicker table tr td.selected.highlighted[disabled]:focus, .datepicker table tr td.selected.highlighted.focus[disabled], fieldset[disabled] .datepicker table tr td.selected.highlighted:hover, fieldset[disabled] .datepicker table tr td.selected.highlighted:focus, fieldset[disabled] .datepicker table tr td.selected.highlighted.focus {
background-color: #898b8d;
border-color: #6b6e71;
.datepicker table tr td.selected.disabled:hover, .datepicker table tr td.selected.disabled:focus, .datepicker table tr td.selected.disabled.focus, .datepicker table tr td.selected[disabled]:hover, .datepicker table tr td.selected[disabled]:focus, .datepicker table tr td.selected[disabled].focus, fieldset[disabled] .datepicker table tr td.selected:hover, fieldset[disabled] .datepicker table tr td.selected:focus, fieldset[disabled] .datepicker table tr td.selected.focus, .datepicker table tr td.selected.highlighted.disabled:hover, .datepicker table tr td.selected.highlighted.disabled:focus, .datepicker table tr td.selected.highlighted.disabled.focus, .datepicker table tr td.selected.highlighted[disabled]:hover, .datepicker table tr td.selected.highlighted[disabled]:focus, .datepicker table tr td.selected.highlighted[disabled].focus, fieldset[disabled] .datepicker table tr td.selected.highlighted:hover, fieldset[disabled] .datepicker table tr td.selected.highlighted:focus, fieldset[disabled] .datepicker table tr td.selected.highlighted.focus {
background-color: #878889;
border-color: #606060;
}
.datepicker table tr td.active, .datepicker table tr td.active.highlighted {
color: #fff;
background-color: #007bff;
border-color: #0277f4;
color: #ffffff;
background-color: #007bc2;
border-color: #0176ba;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.datepicker table tr td.active:focus, .datepicker table tr td.active.focus, .datepicker table tr td.active.highlighted:focus, .datepicker table tr td.active.highlighted.focus {
color: #fff;
background-color: #1a88ff;
border-color: #4199f7;
color: #ffffff;
background-color: #1a88c8;
border-color: #4198cb;
}
.datepicker table tr td.active:hover, .datepicker table tr td.active.highlighted:hover {
color: #fff;
background-color: #80bdff;
border-color: #2087f5;
color: #ffffff;
background-color: #80bde1;
border-color: #1f86c2;
}
.datepicker table tr td.active:active, .datepicker table tr td.active.active, .datepicker table tr td.active.highlighted:active, .datepicker table tr td.active.highlighted.active {
color: #fff;
background-color: #1a88ff;
border-color: #2087f5;
color: #ffffff;
background-color: #1a88c8;
border-color: #1f86c2;
}
.datepicker table tr td.active:active:hover, .datepicker table tr td.active:active:focus, .datepicker table tr td.active.focus:active, .datepicker table tr td.active.active:hover, .datepicker table tr td.active.active:focus, .datepicker table tr td.active.active.focus, .datepicker table tr td.active.highlighted:active:hover, .datepicker table tr td.active.highlighted:active:focus, .datepicker table tr td.active.highlighted.focus:active, .datepicker table tr td.active.highlighted.active:hover, .datepicker table tr td.active.highlighted.active:focus, .datepicker table tr td.active.highlighted.active.focus {
color: #fff;
background-color: #2b91ff;
border-color: #4199f7;
.datepicker table tr td.active:active:hover, .datepicker table tr td.active:active:focus, .datepicker table tr td.active:active.focus, .datepicker table tr td.active.active:hover, .datepicker table tr td.active.active:focus, .datepicker table tr td.active.active.focus, .datepicker table tr td.active.highlighted:active:hover, .datepicker table tr td.active.highlighted:active:focus, .datepicker table tr td.active.highlighted:active.focus, .datepicker table tr td.active.highlighted.active:hover, .datepicker table tr td.active.highlighted.active:focus, .datepicker table tr td.active.highlighted.active.focus {
color: #ffffff;
background-color: #2b91cc;
border-color: #4198cb;
}
.datepicker table tr td.active.disabled:hover, .datepicker table tr td.active.disabled:focus, .datepicker table tr td.active.disabled.focus, .datepicker table tr td.active[disabled]:hover, .datepicker table tr td.active[disabled]:focus, .datepicker table tr td.active.focus[disabled], fieldset[disabled] .datepicker table tr td.active:hover, fieldset[disabled] .datepicker table tr td.active:focus, fieldset[disabled] .datepicker table tr td.active.focus, .datepicker table tr td.active.highlighted.disabled:hover, .datepicker table tr td.active.highlighted.disabled:focus, .datepicker table tr td.active.highlighted.disabled.focus, .datepicker table tr td.active.highlighted[disabled]:hover, .datepicker table tr td.active.highlighted[disabled]:focus, .datepicker table tr td.active.highlighted.focus[disabled], fieldset[disabled] .datepicker table tr td.active.highlighted:hover, fieldset[disabled] .datepicker table tr td.active.highlighted:focus, fieldset[disabled] .datepicker table tr td.active.highlighted.focus {
background-color: #007bff;
border-color: #0277f4;
.datepicker table tr td.active.disabled:hover, .datepicker table tr td.active.disabled:focus, .datepicker table tr td.active.disabled.focus, .datepicker table tr td.active[disabled]:hover, .datepicker table tr td.active[disabled]:focus, .datepicker table tr td.active[disabled].focus, fieldset[disabled] .datepicker table tr td.active:hover, fieldset[disabled] .datepicker table tr td.active:focus, fieldset[disabled] .datepicker table tr td.active.focus, .datepicker table tr td.active.highlighted.disabled:hover, .datepicker table tr td.active.highlighted.disabled:focus, .datepicker table tr td.active.highlighted.disabled.focus, .datepicker table tr td.active.highlighted[disabled]:hover, .datepicker table tr td.active.highlighted[disabled]:focus, .datepicker table tr td.active.highlighted[disabled].focus, fieldset[disabled] .datepicker table tr td.active.highlighted:hover, fieldset[disabled] .datepicker table tr td.active.highlighted:focus, fieldset[disabled] .datepicker table tr td.active.highlighted.focus {
background-color: #007bc2;
border-color: #0176ba;
}
.datepicker table tr td span {
@@ -423,53 +423,53 @@
.datepicker table tr td span:hover, .datepicker table tr td span.focused {
color: #000;
background: #e9e9ea;
background: #e8e9e9;
}
.datepicker table tr td span.disabled, .datepicker table tr td span.disabled:hover {
background: none;
color: #6c757d;
color: #707782;
cursor: default;
}
.datepicker table tr td span.active, .datepicker table tr td span.active:hover, .datepicker table tr td span.active.disabled, .datepicker table tr td span.active.disabled:hover {
color: #fff;
background-color: #007bff;
border-color: #0277f4;
color: #ffffff;
background-color: #007bc2;
border-color: #0176ba;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.datepicker table tr td span.active:focus, .datepicker table tr td span.active.focus, .datepicker table tr td span.active:hover:focus, .datepicker table tr td span.active.focus:hover, .datepicker table tr td span.active.disabled:focus, .datepicker table tr td span.active.disabled.focus, .datepicker table tr td span.active.disabled:hover:focus, .datepicker table tr td span.active.disabled.focus:hover {
color: #fff;
background-color: #1a88ff;
border-color: #4199f7;
.datepicker table tr td span.active:focus, .datepicker table tr td span.active.focus, .datepicker table tr td span.active:hover:focus, .datepicker table tr td span.active:hover.focus, .datepicker table tr td span.active.disabled:focus, .datepicker table tr td span.active.disabled.focus, .datepicker table tr td span.active.disabled:hover:focus, .datepicker table tr td span.active.disabled:hover.focus {
color: #ffffff;
background-color: #1a88c8;
border-color: #4198cb;
}
.datepicker table tr td span.active:hover, .datepicker table tr td span.active:hover:hover, .datepicker table tr td span.active.disabled:hover, .datepicker table tr td span.active.disabled:hover:hover {
color: #fff;
background-color: #80bdff;
border-color: #2087f5;
color: #ffffff;
background-color: #80bde1;
border-color: #1f86c2;
}
.datepicker table tr td span.active:active, .datepicker table tr td span.active.active, .datepicker table tr td span.active:hover:active, .datepicker table tr td span.active.active:hover, .datepicker table tr td span.active.disabled:active, .datepicker table tr td span.active.disabled.active, .datepicker table tr td span.active.disabled:hover:active, .datepicker table tr td span.active.disabled.active:hover {
color: #fff;
background-color: #1a88ff;
border-color: #2087f5;
.datepicker table tr td span.active:active, .datepicker table tr td span.active.active, .datepicker table tr td span.active:hover:active, .datepicker table tr td span.active:hover.active, .datepicker table tr td span.active.disabled:active, .datepicker table tr td span.active.disabled.active, .datepicker table tr td span.active.disabled:hover:active, .datepicker table tr td span.active.disabled:hover.active {
color: #ffffff;
background-color: #1a88c8;
border-color: #1f86c2;
}
.datepicker table tr td span.active:active:hover, .datepicker table tr td span.active:active:focus, .datepicker table tr td span.active.focus:active, .datepicker table tr td span.active.active:hover, .datepicker table tr td span.active.active:focus, .datepicker table tr td span.active.active.focus, .datepicker table tr td span.active:hover:active:hover, .datepicker table tr td span.active:hover:active:focus, .datepicker table tr td span.active.focus:hover:active, .datepicker table tr td span.active.active:hover:hover, .datepicker table tr td span.active.active:hover:focus, .datepicker table tr td span.active.active.focus:hover, .datepicker table tr td span.active.disabled:active:hover, .datepicker table tr td span.active.disabled:active:focus, .datepicker table tr td span.active.disabled.focus:active, .datepicker table tr td span.active.disabled.active:hover, .datepicker table tr td span.active.disabled.active:focus, .datepicker table tr td span.active.disabled.active.focus, .datepicker table tr td span.active.disabled:hover:active:hover, .datepicker table tr td span.active.disabled:hover:active:focus, .datepicker table tr td span.active.disabled.focus:hover:active, .datepicker table tr td span.active.disabled.active:hover:hover, .datepicker table tr td span.active.disabled.active:hover:focus, .datepicker table tr td span.active.disabled.active.focus:hover {
color: #fff;
background-color: #2b91ff;
border-color: #4199f7;
.datepicker table tr td span.active:active:hover, .datepicker table tr td span.active:active:focus, .datepicker table tr td span.active:active.focus, .datepicker table tr td span.active.active:hover, .datepicker table tr td span.active.active:focus, .datepicker table tr td span.active.active.focus, .datepicker table tr td span.active:hover:active:hover, .datepicker table tr td span.active:hover:active:focus, .datepicker table tr td span.active:hover:active.focus, .datepicker table tr td span.active:hover.active:hover, .datepicker table tr td span.active:hover.active:focus, .datepicker table tr td span.active:hover.active.focus, .datepicker table tr td span.active.disabled:active:hover, .datepicker table tr td span.active.disabled:active:focus, .datepicker table tr td span.active.disabled:active.focus, .datepicker table tr td span.active.disabled.active:hover, .datepicker table tr td span.active.disabled.active:focus, .datepicker table tr td span.active.disabled.active.focus, .datepicker table tr td span.active.disabled:hover:active:hover, .datepicker table tr td span.active.disabled:hover:active:focus, .datepicker table tr td span.active.disabled:hover:active.focus, .datepicker table tr td span.active.disabled:hover.active:hover, .datepicker table tr td span.active.disabled:hover.active:focus, .datepicker table tr td span.active.disabled:hover.active.focus {
color: #ffffff;
background-color: #2b91cc;
border-color: #4198cb;
}
.datepicker table tr td span.active.disabled:hover, .datepicker table tr td span.active.disabled:focus, .datepicker table tr td span.active.disabled.focus, .datepicker table tr td span.active[disabled]:hover, .datepicker table tr td span.active[disabled]:focus, .datepicker table tr td span.active.focus[disabled], fieldset[disabled] .datepicker table tr td span.active:hover, fieldset[disabled] .datepicker table tr td span.active:focus, fieldset[disabled] .datepicker table tr td span.active.focus, .datepicker table tr td span.active.disabled:hover:hover, .datepicker table tr td span.active.disabled:hover:focus, .datepicker table tr td span.active.disabled.focus:hover, .datepicker table tr td span.active[disabled]:hover:hover, .datepicker table tr td span.active[disabled]:hover:focus, .datepicker table tr td span.active.focus[disabled]:hover, fieldset[disabled] .datepicker table tr td span.active:hover:hover, fieldset[disabled] .datepicker table tr td span.active:hover:focus, fieldset[disabled] .datepicker table tr td span.active.focus:hover, .datepicker table tr td span.active.disabled.disabled:hover, .datepicker table tr td span.active.disabled.disabled:focus, .datepicker table tr td span.active.disabled.disabled.focus, .datepicker table tr td span.active.disabled[disabled]:hover, .datepicker table tr td span.active.disabled[disabled]:focus, .datepicker table tr td span.active.disabled.focus[disabled], fieldset[disabled] .datepicker table tr td span.active.disabled:hover, fieldset[disabled] .datepicker table tr td span.active.disabled:focus, fieldset[disabled] .datepicker table tr td span.active.disabled.focus, .datepicker table tr td span.active.disabled.disabled:hover:hover, .datepicker table tr td span.active.disabled.disabled:hover:focus, .datepicker table tr td span.active.disabled.disabled.focus:hover, .datepicker table tr td span.active.disabled[disabled]:hover:hover, .datepicker table tr td span.active.disabled[disabled]:hover:focus, .datepicker table tr td span.active.disabled.focus[disabled]:hover, fieldset[disabled] .datepicker table tr td span.active.disabled:hover:hover, fieldset[disabled] .datepicker table tr td span.active.disabled:hover:focus, fieldset[disabled] .datepicker table tr td span.active.disabled.focus:hover {
background-color: #007bff;
border-color: #0277f4;
.datepicker table tr td span.active.disabled:hover, .datepicker table tr td span.active.disabled:focus, .datepicker table tr td span.active.disabled.focus, .datepicker table tr td span.active[disabled]:hover, .datepicker table tr td span.active[disabled]:focus, .datepicker table tr td span.active[disabled].focus, fieldset[disabled] .datepicker table tr td span.active:hover, fieldset[disabled] .datepicker table tr td span.active:focus, fieldset[disabled] .datepicker table tr td span.active.focus, .datepicker table tr td span.active:hover.disabled:hover, .datepicker table tr td span.active:hover.disabled:focus, .datepicker table tr td span.active:hover.disabled.focus, .datepicker table tr td span.active:hover[disabled]:hover, .datepicker table tr td span.active:hover[disabled]:focus, .datepicker table tr td span.active:hover[disabled].focus, fieldset[disabled] .datepicker table tr td span.active:hover:hover, fieldset[disabled] .datepicker table tr td span.active:hover:focus, fieldset[disabled] .datepicker table tr td span.active:hover.focus, .datepicker table tr td span.active.disabled.disabled:hover, .datepicker table tr td span.active.disabled.disabled:focus, .datepicker table tr td span.active.disabled.disabled.focus, .datepicker table tr td span.active.disabled[disabled]:hover, .datepicker table tr td span.active.disabled[disabled]:focus, .datepicker table tr td span.active.disabled[disabled].focus, fieldset[disabled] .datepicker table tr td span.active.disabled:hover, fieldset[disabled] .datepicker table tr td span.active.disabled:focus, fieldset[disabled] .datepicker table tr td span.active.disabled.focus, .datepicker table tr td span.active.disabled:hover.disabled:hover, .datepicker table tr td span.active.disabled:hover.disabled:focus, .datepicker table tr td span.active.disabled:hover.disabled.focus, .datepicker table tr td span.active.disabled:hover[disabled]:hover, .datepicker table tr td span.active.disabled:hover[disabled]:focus, .datepicker table tr td span.active.disabled:hover[disabled].focus, fieldset[disabled] .datepicker table tr td span.active.disabled:hover:hover, fieldset[disabled] .datepicker table tr td span.active.disabled:hover:focus, fieldset[disabled] .datepicker table tr td span.active.disabled:hover.focus {
background-color: #007bc2;
border-color: #0176ba;
}
.datepicker table tr td span.old, .datepicker table tr td span.new {
color: #6c757d;
color: #707782;
}
.datepicker .datepicker-switch {
@@ -488,7 +488,7 @@
.datepicker .next:hover,
.datepicker tfoot tr th:hover {
color: #000;
background: #e9e9ea;
background: #e8e9e9;
}
.datepicker .prev.disabled, .datepicker .next.disabled {

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,7 @@
/*!
* Datepicker for Bootstrap v1.9.0 (https://github.com/uxsolutions/bootstrap-datepicker)
* Datepicker for Bootstrap v1.10.0 (https://github.com/uxsolutions/bootstrap-datepicker)
*
* Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* Licensed under the Apache License v2.0 (https://www.apache.org/licenses/LICENSE-2.0)
*/
(function(factory){
@@ -61,7 +61,7 @@
replace: function(new_array){
if (!new_array)
return;
if (!$.isArray(new_array))
if (!Array.isArray(new_array))
new_array = [new_array];
this.clear();
this.push.apply(this, new_array);
@@ -103,9 +103,15 @@
this.isInput = this.element.is('input');
this.inputField = this.isInput ? this.element : this.element.find('input');
this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .input-group-append, .input-group-prepend, .btn') : false;
if (this.component && this.component.length === 0)
if (this.component && this.component.length === 0){
this.component = false;
this.isInline = !this.component && this.element.is('div');
}
if (this.o.isInline === null){
this.isInline = !this.component && !this.isInput;
} else {
this.isInline = this.o.isInline;
}
this.picker = $(DPGlobal.template);
@@ -176,7 +182,7 @@
},
_resolveDaysOfWeek: function(daysOfWeek){
if (!$.isArray(daysOfWeek))
if (!Array.isArray(daysOfWeek))
daysOfWeek = daysOfWeek.split(/[,\s]*/);
return $.map(daysOfWeek, Number);
},
@@ -263,7 +269,7 @@
o.daysOfWeekHighlighted = this._resolveDaysOfWeek(o.daysOfWeekHighlighted||[]);
o.datesDisabled = o.datesDisabled||[];
if (!$.isArray(o.datesDisabled)) {
if (!Array.isArray(o.datesDisabled)) {
o.datesDisabled = o.datesDisabled.split(',');
}
o.datesDisabled = $.map(o.datesDisabled, function(d){
@@ -570,16 +576,15 @@
clearDates: function(){
this.inputField.val('');
this.update();
this._trigger('changeDate');
this.update();
if (this.o.autoclose) {
this.hide();
}
},
setDates: function(){
var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
var args = Array.isArray(arguments[0]) ? arguments[0] : arguments;
this.update.apply(this, args);
this._trigger('changeDate');
this.setValue();
@@ -587,7 +592,7 @@
},
setUTCDates: function(){
var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
var args = Array.isArray(arguments[0]) ? arguments[0] : arguments;
this.setDates.apply(this, $.map(args, this._utc_to_local));
return this;
},
@@ -1039,7 +1044,7 @@
//Check if uniqueSort exists (supported by jquery >=1.12 and >=2.2)
//Fallback to unique function for older jquery versions
if ($.isFunction($.uniqueSort)) {
if (typeof $.uniqueSort === "function") {
clsName = $.uniqueSort(clsName);
} else {
clsName = $.unique(clsName);
@@ -1571,12 +1576,12 @@
if (new_date < this.dates[j]){
// Date being moved earlier/left
while (j >= 0 && new_date < this.dates[j]){
while (j >= 0 && new_date < this.dates[j] && (this.pickers[j].element.val() || "").length > 0) {
this.pickers[j--].setUTCDate(new_date);
}
} else if (new_date > this.dates[k]){
// Date being moved later/right
while (k < l && new_date > this.dates[k]){
while (k < l && new_date > this.dates[k] && (this.pickers[k].element.val() || "").length > 0) {
this.pickers[k++].setUTCDate(new_date);
}
}
@@ -1690,6 +1695,7 @@
endDate: Infinity,
forceParse: true,
format: 'mm/dd/yyyy',
isInline: null,
keepEmptyValues: false,
keyboardNavigation: true,
language: 'en',
@@ -2007,7 +2013,7 @@
/* DATEPICKER VERSION
* =================== */
$.fn.datepicker.version = '1.9.0';
$.fn.datepicker.version = '1.10.0';
$.fn.datepicker.deprecated = function(msg){
var console = window.console;

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates["ar-DZ"]={days:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد"],daysShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت","أحد"],daysMin:["ح","ن","ث","ع","خ","ج","س","ح"],months:["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthsShort:["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],today:"هذا اليوم",rtl:!0,monthsTitle:"أشهر",clear:"إزالة",format:"yyyy/mm/dd",weekStart:0}}(jQuery);

View File

@@ -1 +1 @@
!function(a){a.fn.datepicker.dates.ca={days:["Diumenge","Dilluns","Dimarts","Dimecres","Dijous","Divendres","Dissabte"],daysShort:["Diu","Dil","Dmt","Dmc","Dij","Div","Dis"],daysMin:["dg","dl","dt","dc","dj","dv","ds"],months:["Gener","Febrer","Març","Abril","Maig","Juny","Juliol","Agost","Setembre","Octubre","Novembre","Desembre"],monthsShort:["Gen","Feb","Mar","Abr","Mai","Jun","Jul","Ago","Set","Oct","Nov","Des"],today:"Avui",monthsTitle:"Mesos",clear:"Esborrar",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
!function(a){a.fn.datepicker.dates.ca={days:["diumenge","dilluns","dimarts","dimecres","dijous","divendres","dissabte"],daysShort:["dg.","dl.","dt.","dc.","dj.","dv.","ds."],daysMin:["dg","dl","dt","dc","dj","dv","ds"],months:["gener","febrer","març","abril","maig","juny","juliol","agost","setembre","octubre","novembre","desembre"],monthsShort:["gen.","febr.","març","abr.","maig","juny","jul.","ag.","set.","oct.","nov.","des."],today:"Avui",monthsTitle:"Mesos",clear:"Esborra",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);

View File

@@ -1 +1 @@
!function(a){a.fn.datepicker.dates.de={days:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["Son","Mon","Die","Mit","Don","Fre","Sam"],daysMin:["So","Mo","Di","Mi","Do","Fr","Sa"],months:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",monthsTitle:"Monate",clear:"Löschen",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
!function(a){a.fn.datepicker.dates.de={days:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["So","Mo","Di","Mi","Do","Fr","Sa"],daysMin:["So","Mo","Di","Mi","Do","Fr","Sa"],months:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",monthsTitle:"Monate",clear:"Löschen",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates["en-US"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:0,format:"m/d/yyyy"}}(jQuery);

View File

@@ -1 +1 @@
!function(a){a.fn.datepicker.dates.fi={days:["sunnuntai","maanantai","tiistai","keskiviikko","torstai","perjantai","lauantai"],daysShort:["sun","maa","tii","kes","tor","per","lau"],daysMin:["su","ma","ti","ke","to","pe","la"],months:["tammikuu","helmikuu","maaliskuu","huhtikuu","toukokuu","kesäkuu","heinäkuu","elokuu","syyskuu","lokakuu","marraskuu","joulukuu"],monthsShort:["tam","hel","maa","huh","tou","kes","hei","elo","syy","lok","mar","jou"],today:"tänään",clear:"Tyhjennä",weekStart:1,format:"d.m.yyyy"}}(jQuery);
!function(a){a.fn.datepicker.dates.fi={days:["sunnuntai","maanantai","tiistai","keskiviikko","torstai","perjantai","lauantai"],daysShort:["sun","maa","tii","kes","tor","per","lau"],daysMin:["su","ma","ti","ke","to","pe","la"],months:["tammikuu","helmikuu","maaliskuu","huhtikuu","toukokuu","kesäkuu","heinäkuu","elokuu","syyskuu","lokakuu","marraskuu","joulukuu"],monthsShort:["tammi","helmi","maalis","huhti","touko","kesä","hei","elo","syys","loka","marras","joulu"],today:"tänään",clear:"Tyhjennä",weekStart:1,format:"d.m.yyyy"}}(jQuery);

View File

@@ -1 +1 @@
!function(a){a.fn.datepicker.dates.id={days:["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],daysShort:["Mgu","Sen","Sel","Rab","Kam","Jum","Sab"],daysMin:["Mg","Sn","Sl","Ra","Ka","Ju","Sa"],months:["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Ags","Sep","Okt","Nov","Des"],today:"Hari Ini",clear:"Kosongkan"}}(jQuery);
!function(a){a.fn.datepicker.dates.id={days:["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],daysShort:["Min","Sen","Sel","Rab","Kam","Jum","Sab"],daysMin:["Mg","Sn","Sl","Rb","Km","Jm","Sb"],months:["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agt","Sep","Okt","Nov","Des"],today:"Hari Ini",monthsTitle:"Bulan",clear:"Kosongkan",weekStart:0,format:"dd-mm-yyyy"}}(jQuery);

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.mar={days:["रविवार","सोमवार","मंगळवार","बुधवार","गुरुवार","शुक्रवार","शनिवार"],daysShort:["रवि","सोम","मंगळ","बुध","गुरु","शुक्र","शनि"],daysMin:["र","सो","मं","बु","गु","शु","श"],months:["जानेवारी","फेब्रुवारी","मार्च","एप्रिल","मे","जून","जुलै","ऑगस्ट","सप्टेंबर","ऑक्टोबर","नोव्हेंबर","डिसेंबर"],monthsShort:["जाने.","फेब्रु.","मार्च","एप्रिल","मे","जून","जुलै","ऑगस्ट","सप्टें.","ऑक्टो.","नोव्हें.","डिसें."],today:"आज",monthsTitle:"महीने",clear:"हटवा",weekStart:1,format:"dd / mm / yyyy"}}(jQuery);

View File

@@ -1 +1 @@
!function(a){a.fn.datepicker.dates.uk={days:["Неділя","Понеділок","Вівторок","Середа","Четвер","П'ятниця","Субота"],daysShort:["Нед","Пнд","Втр","Срд","Чтв","Птн","Суб"],daysMin:["Нд","Пн","Вт","Ср","Чт","Пт","Сб"],months:["Cічень","Лютий","Березень","Квітень","Травень","Червень","Липень","Серпень","Вересень","Жовтень","Листопад","Грудень"],monthsShort:["Січ","Лют","Бер","Кві","Тра","Чер","Лип","Сер","Вер","Жов","Лис","Гру"],today:"Сьогодні",clear:"Очистити",format:"dd.mm.yyyy",weekStart:1}}(jQuery);
!function(a){a.fn.datepicker.dates.uk={days:["Неділя","Понеділок","Вівторок","Середа","Четвер","П'ятниця","Субота"],daysShort:["Нед","Пнд","Втр","Срд","Чтв","Птн","Суб"],daysMin:["Нд","Пн","Вт","Ср","Чт","Пт","Сб"],months:["Січень","Лютий","Березень","Квітень","Травень","Червень","Липень","Серпень","Вересень","Жовтень","Листопад","Грудень"],monthsShort:["Січ","Лют","Бер","Кві","Тра","Чер","Лип","Сер","Вер","Жов","Лис","Гру"],today:"Сьогодні",clear:"Очистити",format:"dd.mm.yyyy",weekStart:1}}(jQuery);

View File

@@ -1 +1 @@
!function(a){a.fn.datepicker.dates["zh-TW"]={days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],daysShort:["週日","週一","週二","週三","週四","週五","週六"],daysMin:["日","一","二","三","四","五","六"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],today:"今天",format:"yyyymmdd",weekStart:1,clear:"清除"}}(jQuery);
!function(a){a.fn.datepicker.dates["zh-TW"]={days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],daysShort:["週日","週一","週二","週三","週四","週五","週六"],daysMin:["日","一","二","三","四","五","六"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],today:"今天",monthsTitle:"月份",format:"yyyy/mm/dd",weekStart:0,titleFormat:"yyyy年mm月",clear:"清除"}}(jQuery);

File diff suppressed because one or more lines are too long

View File

@@ -31,7 +31,6 @@ Michael Bensoussan <mickey@seesmic.com>
Louis-Rémi Babé <lrbabe@gmail.com>
Robert Katić <robert.katic@gmail.com>
Damian Janowski <damian.janowski@gmail.com>
Anton Kovalyov <anton@kovalyov.net>
Dušan B. Jovanovic <dbjdbj@gmail.com>
Earle Castledine <mrspeaker@gmail.com>
Rich Dougherty <rich@rd.gen.nz>
@@ -69,11 +68,11 @@ temp01 <temp01irc@gmail.com>
Colin Snover <github.com@zetafleet.com>
Jared Grippe <jared@deadlyicon.com>
Ryan W Tenney <ryan@10e.us>
Alex Sexton <AlexSexton@gmail.com>
Pinhook <contact@pinhooklabs.com>
Ron Otten <r.j.g.otten@gmail.com>
Jephte Clain <Jephte.Clain@univ-reunion.fr>
Anton Matzneller <obhvsbypqghgc@gmail.com>
Alex Sexton <AlexSexton@gmail.com>
Dan Heberden <danheberden@gmail.com>
Henri Wiechers <hwiechers@gmail.com>
Russell Holbrook <russell.holbrook@patch.com>
@@ -87,9 +86,10 @@ Sylvester Keil <sylvester@keil.or.at>
Brandon Sterne <bsterne@mozilla.com>
Mathias Bynens <mathias@qiwi.be>
Lee Carpenter <elcarpie@gmail.com>
Timmy Willison <4timmywil@gmail.com>
Timmy Willison <timmywil@users.noreply.github.com>
Corey Frang <gnarf37@gmail.com>
Digitalxero <digitalxero>
Anton Kovalyov <anton@kovalyov.net>
David Murdoch <david@davidmurdoch.com>
Josh Varner <josh.varner@gmail.com>
Charles McNulty <cmcnulty@kznf.com>
@@ -111,7 +111,7 @@ Mike Sherov <mike.sherov@gmail.com>
Greg Hazel <ghazel@gmail.com>
Schalk Neethling <schalk@ossreleasefeed.com>
Denis Knauf <Denis.Knauf@gmail.com>
Timo Tijhof <krinklemail@gmail.com>
Timo Tijhof <krinkle@fastmail.com>
Steen Nielsen <swinedk@gmail.com>
Anton Ryzhov <anton@ryzhov.me>
Shi Chuan <shichuanr@gmail.com>
@@ -151,7 +151,6 @@ Chris Faulkner <thefaulkner@gmail.com>
Marcel Greter <marcel.greter@ocbnet.ch>
Elijah Manor <elijah.manor@gmail.com>
Daniel Chatfield <chatfielddaniel@gmail.com>
Daniel Gálvez <dgalvez@editablething.com>
Nikita Govorov <nikita.govorov@gmail.com>
Wesley Walser <waw325@gmail.com>
Mike Pennisi <mike@mikepennisi.com>
@@ -162,9 +161,7 @@ Dave Riddle <david@joyvuu.com>
Callum Macrae <callum@lynxphp.com>
Jonathan Sampson <jjdsampson@gmail.com>
Benjamin Truyman <bentruyman@gmail.com>
Jay Merrifield <fracmak@gmail.com>
James Huston <james@jameshuston.net>
Sai Lung Wong <sai.wong@huffingtonpost.com>
Erick Ruiz de Chávez <erickrdch@gmail.com>
David Bonner <dbonner@cogolabs.com>
Allen J Schmidt Jr <cobrasoft@gmail.com>
@@ -174,8 +171,11 @@ Ismail Khair <ismail.khair@gmail.com>
Carl Danley <carldanley@gmail.com>
Mike Petrovich <michael.c.petrovich@gmail.com>
Greg Lavallee <greglavallee@wapolabs.com>
Daniel Gálvez <dgalvez@editablething.com>
Sai Lung Wong <sai.wong@huffingtonpost.com>
Tom H Fuertes <TomFuertes@gmail.com>
Roland Eckl <eckl.roland@googlemail.com>
Jay Merrifield <fracmak@gmail.com>
Yiming He <yiminghe@gmail.com>
David Fox <dfoxinator@gmail.com>
Bennett Sorbo <bsorbo@gmail.com>
@@ -192,9 +192,9 @@ Diego Tres <diegotres@gmail.com>
Jean Boussier <jean.boussier@gmail.com>
Andrew Plummer <plummer.andrew@gmail.com>
Mark Raddatz <mraddatz@gmail.com>
Pascal Borreli <pascal@borreli.com>
Isaac Z. Schlueter <i@izs.me>
Karl Sieburg <ksieburg@yahoo.com>
Pascal Borreli <pascal@borreli.com>
Nguyen Phuc Lam <ruado1987@gmail.com>
Dmitry Gusev <dmitry.gusev@gmail.com>
Steven Benner <admin@stevenbenner.com>
@@ -202,7 +202,6 @@ Li Xudong <istonelee@gmail.com>
Michał Gołębiowski-Owczarek <m.goleb@gmail.com>
Renato Oliveira dos Santos <ros3@cin.ufpe.br>
Frederic Junod <frederic.junod@camptocamp.com>
Tom H Fuertes <tomfuertes@gmail.com>
Mitch Foley <mitch@thefoley.net>
ros3cin <ros3@cin.ufpe.br>
Kyle Robinson Young <kyle@dontkry.com>
@@ -250,7 +249,6 @@ Dan Hart <danhart@notonthehighstreet.com>
Nazar Mokrynskyi <nazar@mokrynskyi.com>
Benjamin Tan <demoneaux@gmail.com>
Amit Merchant <bullredeyes@gmail.com>
Jason Bedard <jason+github@jbedard.ca>
Veaceslav Grimalschi <grimalschi@yandex.ru>
Richard McDaniel <rm0026@uah.edu>
Arthur Verschaeve <contact@arthurverschaeve.be>
@@ -273,12 +271,12 @@ Jon Hester <jon.d.hester@gmail.com>
Colin Frick <colin@bash.li>
Winston Howes <winstonhowes@gmail.com>
Alexander O'Mara <me@alexomara.com>
Chris Rebert <github@rebertia.com>
Bastian Buchholz <buchholz.bastian@googlemail.com>
Mu Haibao <mhbseal@163.com>
Calvin Metcalf <calvin.metcalf@gmail.com>
Arthur Stolyar <nekr.fabula@gmail.com>
Gabriel Schulhof <gabriel.schulhof@intel.com>
Chris Rebert <github@rebertia.com>
Gilad Peleg <giladp007@gmail.com>
Julian Alexander Murillo <julian.alexander.murillo@gmail.com>
Kevin Kirsche <Kev.Kirsche+GitHub@gmail.com>
@@ -297,15 +295,14 @@ Christian Grete <webmaster@christiangrete.com>
Tom von Clef <thomas.vonclef@gmail.com>
Liza Ramo <liza.h.ramo@gmail.com>
Joelle Fleurantin <joasqueeniebee@gmail.com>
Steve Mao <maochenyan@gmail.com>
Jon Dufresne <jon.dufresne@gmail.com>
Jae Sung Park <alberto.park@gmail.com>
Josh Soref <apache@soref.com>
Saptak Sengupta <saptak013@gmail.com>
Henry Wong <henryw4k@gmail.com>
Jun Sun <klsforever@gmail.com>
Martijn W. van der Lee <martijn@vanderlee.com>
Devin Wilson <dwilson6.github@gmail.com>
Steve Mao <maochenyan@gmail.com>
Damian Senn <jquery@topaxi.codes>
Zack Hall <zackhall@outlook.com>
Vitaliy Terziev <vitaliyterziev@gmail.com>
@@ -336,6 +333,7 @@ Jordan Beland <jordan.beland@gmail.com>
Henry Zhu <hi@henryzoo.com>
Nilton Cesar <niltoncms@gmail.com>
basil.belokon <basil.belokon@gmail.com>
Saptak Sengupta <saptak013@gmail.com>
Andrey Meshkov <ay.meshkov@gmail.com>
tmybr11 <tomas.perone@gmail.com>
Luis Emilio Velasco Sanchez <emibloque@gmail.com>
@@ -344,14 +342,34 @@ Bert Zhang <enbo@users.noreply.github.com>
Sébastien Règne <regseb@users.noreply.github.com>
wartmanm <3869625+wartmanm@users.noreply.github.com>
Siddharth Dungarwal <sd5869@gmail.com>
abnud1 <ahmad13932013@hotmail.com>
Andrei Fangli <andrei_fangli@outlook.com>
Marja Hölttä <marja.holtta@gmail.com>
abnud1 <ahmad13932013@hotmail.com>
buddh4 <mail@jharrer.de>
Hoang <dangkyokhoang@gmail.com>
Sean Robinson <sean.robinson@scottsdalecc.edu>
Wonseop Kim <wonseop.kim@samsung.com>
Pat O'Callaghan <patocallaghan@gmail.com>
JuanMa Ruiz <ruizjuanma@gmail.com>
Ahmed.S.ElAfifi <ahmed.s.elafifi@gmail.com>
Sean Robinson <sean.robinson@scottsdalecc.edu>
Christian Oliff <christianoliff@pm.me>
Christian Wenz <christian@wenz.org>
Jonathan <vanillajonathan@users.noreply.github.com>
Ed Sanders <ejsanders@gmail.com>
Pierre Grimaud <grimaud.pierre@gmail.com>
Beatriz Rezener <beatrizrezener@users.noreply.github.com>
Necmettin Karakaya <necmettin.karakaya@gmail.com>
Wonhyoung Park <wh05.park@samsung.com>
Dallas Fraser <dallas.fraser.waterloo@gmail.com>
高灰 <www@zeroplace.cn>
fecore1 <89127124+fecore1@users.noreply.github.com>
ygj6 <7699524+ygj6@users.noreply.github.com>
Bruno PIERRE <brunopierre4@yahoo.fr>
Simon Legner <Simon.Legner@gmail.com>
Baoshuo Ren <i@baoshuo.ren>
Anders Kaseorg <andersk@mit.edu>
Alex <aleksandrosansan@gmail.com>
Gabriela Gutierrez <gabigutierrez@google.com>
Dimitri Papadopoulos Orfanos <3234522+DimitriPapadopoulos@users.noreply.github.com>
J.Son <x@x-wx.com>
Liam James <liam@minimaximize.com>

File diff suppressed because one or more lines are too long

View File

@@ -2,6 +2,6 @@
"version": 3,
"sources": ["../../../srcts/extras/shiny-autoreload.ts"],
"sourcesContent": ["/* eslint-disable unicorn/filename-case */\n\ndocument.documentElement.classList.add(\"autoreload-enabled\");\n\nconst protocol = window.location.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n// Add trailing slash to path, if necessary, before appending \"autoreload\"\nconst defaultPath =\n window.location.pathname.replace(/\\/?$/, \"/\") + \"autoreload/\";\nconst defaultUrl = `${protocol}//${window.location.host}${defaultPath}`;\n\n// By default, use the defaultUrl. But if there's a data-ws-url attribute on our\n// <script> tag, use that instead.\nconst wsUrl = document.currentScript?.dataset?.wsUrl || defaultUrl;\n\n/**\n * Connects to an autoreload URL and waits for the server to tell us what to do.\n *\n * @param url The ws:// or wss:// URL to connect to.\n * @returns true if the server requests a reload, or false if the connection was\n * successfully established but then closed without the server requesting a\n * reload\n * @throws A nondescript error if the connection fails to be established.\n */\nasync function autoreload(url: string): Promise<boolean> {\n const ws = new WebSocket(url);\n\n let success = false;\n\n return new Promise((resolve, reject) => {\n ws.onopen = () => {\n success = true;\n };\n\n ws.onerror = (err) => {\n reject(err);\n };\n\n ws.onclose = () => {\n if (!success) {\n reject(new Error(\"WebSocket connection failed\"));\n } else {\n resolve(false);\n }\n };\n\n ws.onmessage = function (event) {\n if (event.data === \"autoreload\") {\n resolve(true);\n }\n };\n });\n}\n\nasync function sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function initialize() {\n while (true) {\n try {\n if (await autoreload(wsUrl)) {\n window.location.reload();\n return;\n }\n } catch (err) {\n // It's possible for the autoreload() call to throw. If it does, that\n // means we tried but failed to connect to the autoreload socket. This\n // probably means that the entire `shiny run --reload` process was\n // restarted. As of today, the autoreload websocket port number is\n // randomly chosen for each `shiny run --reload` process, so it's\n // impossible for us to recover.\n console.debug(\"Giving up on autoreload\");\n return;\n }\n // If we get here, the connection to the autoreload server was\n // successful but then got broken. Wait for a second, and then\n // try to re-establish the connection.\n await sleep(1000);\n }\n}\n\ninitialize().catch((err) => {\n console.error(err);\n});\n\nexport {};\n"],
"mappings": ";mBAEA,SAAS,gBAAgB,UAAU,IAAI,oBAAoB,EAE3D,IAAMA,EAAW,OAAO,SAAS,WAAa,SAAW,OAAS,MAE5DC,EACJ,OAAO,SAAS,SAAS,QAAQ,OAAQ,GAAG,EAAI,cAC5CC,EAAa,GAAGF,MAAa,OAAO,SAAS,OAAOC,IAIpDE,EAAQ,SAAS,eAAe,SAAS,OAASD,EAWxD,eAAeE,EAAWC,EAA+B,CACvD,IAAMC,EAAK,IAAI,UAAUD,CAAG,EAExBE,EAAU,GAEd,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,CACtCH,EAAG,OAAS,IAAM,CAChBC,EAAU,EACZ,EAEAD,EAAG,QAAWI,GAAQ,CACpBD,EAAOC,CAAG,CACZ,EAEAJ,EAAG,QAAU,IAAM,CACZC,EAGHC,EAAQ,EAAK,EAFbC,EAAO,IAAI,MAAM,6BAA6B,CAAC,CAInD,EAEAH,EAAG,UAAY,SAAUK,EAAO,CAC1BA,EAAM,OAAS,cACjBH,EAAQ,EAAI,CAEhB,CACF,CAAC,CACH,CAEA,eAAeI,EAAMC,EAAY,CAC/B,OAAO,IAAI,QAASL,GAAY,WAAWA,EAASK,CAAE,CAAC,CACzD,CAEA,eAAeC,GAAa,CAC1B,OAAa,CACX,GAAI,CACF,GAAI,MAAMV,EAAWD,CAAK,EAAG,CAC3B,OAAO,SAAS,OAAO,EACvB,MACF,CACF,MAAE,CAOA,QAAQ,MAAM,yBAAyB,EACvC,MACF,CAIA,MAAMS,EAAM,GAAI,CAClB,CACF,CAEAE,EAAW,EAAE,MAAOJ,GAAQ,CAC1B,QAAQ,MAAMA,CAAG,CACnB,CAAC",
"mappings": ";mBAEA,SAAS,gBAAgB,UAAU,IAAI,oBAAoB,EAE3D,IAAMA,EAAW,OAAO,SAAS,WAAa,SAAW,OAAS,MAE5DC,EACJ,OAAO,SAAS,SAAS,QAAQ,OAAQ,GAAG,EAAI,cAC5CC,EAAa,GAAGF,CAAQ,KAAK,OAAO,SAAS,IAAI,GAAGC,CAAW,GAI/DE,EAAQ,SAAS,eAAe,SAAS,OAASD,EAWxD,eAAeE,EAAWC,EAA+B,CACvD,IAAMC,EAAK,IAAI,UAAUD,CAAG,EAExBE,EAAU,GAEd,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,CACtCH,EAAG,OAAS,IAAM,CAChBC,EAAU,EACZ,EAEAD,EAAG,QAAWI,GAAQ,CACpBD,EAAOC,CAAG,CACZ,EAEAJ,EAAG,QAAU,IAAM,CACZC,EAGHC,EAAQ,EAAK,EAFbC,EAAO,IAAI,MAAM,6BAA6B,CAAC,CAInD,EAEAH,EAAG,UAAY,SAAUK,EAAO,CAC1BA,EAAM,OAAS,cACjBH,EAAQ,EAAI,CAEhB,CACF,CAAC,CACH,CAEA,eAAeI,EAAMC,EAAY,CAC/B,OAAO,IAAI,QAASL,GAAY,WAAWA,EAASK,CAAE,CAAC,CACzD,CAEA,eAAeC,GAAa,CAC1B,OAAa,CACX,GAAI,CACF,GAAI,MAAMV,EAAWD,CAAK,EAAG,CAC3B,OAAO,SAAS,OAAO,EACvB,MACF,CACF,MAAc,CAOZ,QAAQ,MAAM,yBAAyB,EACvC,MACF,CAIA,MAAMS,EAAM,GAAI,CAClB,CACF,CAEAE,EAAW,EAAE,MAAOJ,GAAQ,CAC1B,QAAQ,MAAMA,CAAG,CACnB,CAAC",
"names": ["protocol", "defaultPath", "defaultUrl", "wsUrl", "autoreload", "url", "ws", "success", "resolve", "reject", "err", "event", "sleep", "ms", "initialize"]
}

View File

@@ -1,3 +1,3 @@
/*! shiny 1.11.1.9000 | (c) 2012-2025 Posit Software, PBC. | License: GPL-3 | file LICENSE */
"use strict";(()=>{var f=400;function c(e,i){let t=0;if(e.nodeType===3){let n=e.nodeValue.replace(/\n/g,"").length;if(n>=i)return{element:e,offset:i};t+=n}else if(e.nodeType===1&&e.firstChild){let n=c(e.firstChild,i);if(n.element!==null)return n;t+=n.offset}return e.nextSibling?c(e.nextSibling,i-t):{element:null,offset:t}}function r(e,i,t){let n=0;for(let s=0;s<e.childNodes.length;s++){let l=e.childNodes[s];if(l.nodeType===3){let o=/\n/g,d;for(;(d=o.exec(l.nodeValue))!==null;)if(n++,n===i)return c(l,d.index+t+1)}else if(l.nodeType===1){let o=r(l,i-n,t);if(o.element!==null)return o;n+=o.offset}}return{element:null,offset:n}}function w(e,i){if(!document.createRange)return;let t=document.getElementById("srcref_"+e);if(!t){t=document.createElement("span"),t.id="srcref_"+e;let n=e,s=document.getElementById(i.replace(/\./g,"_")+"_code");if(!s)return;let l=r(s,n[0],n[4]),o=r(s,n[2],n[5]);if(l.element===null||o.element===null)return;let d=document.createRange();l.element.parentNode.nodeName==="SPAN"&&l.element!==o.element?d.setStartBefore(l.element.parentNode):d.setStart(l.element,l.offset),o.element.parentNode.nodeName==="SPAN"&&l.element!==o.element?d.setEndAfter(o.element.parentNode):d.setEnd(o.element,o.offset),d.surroundContents(t)}$(t).stop(!0,!0).effect("highlight",null,1600)}Shiny&&Shiny.addCustomMessageHandler("showcase-src",function(e){e.srcref&&e.srcfile&&w(e.srcref,e.srcfile)});var a=!1,m=function(e,i){let t=i?f:1,n=e?document.getElementById("showcase-sxs-code"):document.getElementById("showcase-code-inline"),s=e?document.getElementById("showcase-code-inline"):document.getElementById("showcase-sxs-code");if(document.getElementById("showcase-app-metadata")===null){let o=$("#showcase-well");e?o.fadeOut(t):o.fadeIn(t)}$(n).hide(),$(s).fadeOut(t,function(){let o=document.getElementById("showcase-code-tabs");s.removeChild(o),n.appendChild(o),e?h():document.getElementById("showcase-code-content").removeAttribute("style"),$(n).fadeIn(t),e||(document.getElementById("showcase-app-container").removeAttribute("style"),i&&$(document.body).animate({scrollTop:$(n).offset().top}));let d=document.getElementById("readme-md");d!==null&&(d.parentElement.removeChild(d),e?(s.appendChild(d),$(s).fadeIn(t)):document.getElementById("showcase-app-metadata").appendChild(d)),document.getElementById("showcase-code-position-toggle").innerHTML=e?'<i class="fa fa-level-down"></i> show below':'<i class="fa fa-level-up"></i> show with app'}),e&&$(document.body).animate({scrollTop:0},t),a=e,u(e&&i),$(window).trigger("resize")};function u(e){let t=960,n=1,s=document.getElementById("showcase-app-code").offsetWidth;s/2>960?t=s/2:s*.66>960?t=960:(t=s*.66,n=t/960);let l=document.getElementById("showcase-app-container");$(l).animate({width:t+"px",zoom:n*100+"%"},e?f:0)}var g=function(){m(!a,!0)},p=function(){document.body.offsetWidth>1350&&m(!0,!1)};function h(){document.getElementById("showcase-code-content").style.height=$(window).height()+"px"}function y(){let e=document.getElementById("showcase-markdown-content");if(e!==null){let i=e.innerText||e.innerHTML,t=window.Showdown.converter;document.getElementById("readme-md").innerHTML=new t().makeHtml(i)}}$(window).resize(function(){a&&(u(!1),h())});window.toggleCodePosition=g;$(window).on("load",p);$(window).on("load",y);window.hljs&&window.hljs.initHighlightingOnLoad();})();
"use strict";(()=>{var m=400;function c(e,l){let t=0;if(e.nodeType===3){let n=e.nodeValue?.replace(/\n/g,"").length??0;if(n>=l)return{element:e,offset:l};t+=n}else if(e.nodeType===1&&e.firstChild){let n=c(e.firstChild,l);if(n.element!==null)return n;t+=n.offset}return e.nextSibling?c(e.nextSibling,l-t):{element:null,offset:t}}function r(e,l,t){let n=0;for(let s=0;s<e.childNodes.length;s++){let i=e.childNodes[s];if(i.nodeType===3){let o=/\n/g,d;for(;(d=o.exec(i.nodeValue))!==null;)if(n++,n===l)return c(i,d.index+t+1)}else if(i.nodeType===1){let o=r(i,l-n,t);if(o.element!==null)return o;n+=o.offset}}return{element:null,offset:n}}function p(e,l){if(!document.createRange)return;let t=document.getElementById("srcref_"+e);if(!t){t=document.createElement("span"),t.id="srcref_"+e;let n=e,s=document.getElementById(l.replace(/\./g,"_")+"_code");if(!s)return;let i=r(s,n[0],n[4]),o=r(s,n[2],n[5]);if(i.element===null||o.element===null)return;let d=document.createRange();i.element.parentNode?.nodeName==="SPAN"&&i.element!==o.element?d.setStartBefore(i.element.parentNode):d.setStart(i.element,i.offset),o.element.parentNode?.nodeName==="SPAN"&&i.element!==o.element?d.setEndAfter(o.element.parentNode):d.setEnd(o.element,o.offset),d.surroundContents(t)}$(t).stop(!0,!0).effect("highlight",null,1600)}window.Shiny&&window.Shiny.addCustomMessageHandler("showcase-src",function(e){e.srcref&&e.srcfile&&p(e.srcref,e.srcfile)});var a=!1,u=function(e,l){let t=l?m:1,n=e?document.getElementById("showcase-sxs-code"):document.getElementById("showcase-code-inline"),s=e?document.getElementById("showcase-code-inline"):document.getElementById("showcase-sxs-code");if(document.getElementById("showcase-app-metadata")===null){let o=$("#showcase-well");e?o.fadeOut(t):o.fadeIn(t)}if(n===null||s===null){console.warn("Could not find the host elements for the code tabs. This is likely a bug in the showcase app.");return}$(n).hide(),$(s).fadeOut(t,function(){let o=document.getElementById("showcase-code-tabs");if(o===null){console.warn("Could not find the code tabs element. This is likely a bug in the showcase app.");return}if(s.removeChild(o),n.appendChild(o),e?w():document.getElementById("showcase-code-content")?.removeAttribute("style"),$(n).fadeIn(t),!e&&(document.getElementById("showcase-app-container")?.removeAttribute("style"),l)){let f=$(n).offset()?.top;f!==void 0&&$(document.body).animate({scrollTop:f})}let d=document.getElementById("readme-md");d!==null&&(d.parentElement?.removeChild(d),e?(s.appendChild(d),$(s).fadeIn(t)):document.getElementById("showcase-app-metadata")?.appendChild(d)),document.getElementById("showcase-code-position-toggle").innerHTML=e?'<i class="fa fa-level-down"></i> show below':'<i class="fa fa-level-up"></i> show with app'}),e&&$(document.body).animate({scrollTop:0},t),a=e,h(e&&l),$(window).trigger("resize")};function h(e){let t=960,n=1,s=document.getElementById("showcase-app-code").offsetWidth;s/2>960?t=s/2:s*.66>960?t=960:(t=s*.66,n=t/960),$("#showcase-app-container").animate({width:t+"px",zoom:n*100+"%"},e?m:0)}var g=function(){u(!a,!0)},y=function(){document.body.offsetWidth>1350&&u(!0,!1)};function w(){document.getElementById("showcase-code-content").style.height=$(window).height()+"px"}function E(){let e=document.getElementById("showcase-markdown-content");if(e!==null){let l=e.innerText||e.innerHTML,t=window.Showdown.converter;document.getElementById("readme-md").innerHTML=new t().makeHtml(l)}}$(window).resize(function(){a&&(h(!1),w())});window.toggleCodePosition=g;$(window).on("load",y);$(window).on("load",E);window.hljs&&window.hljs.initHighlightingOnLoad();})();
//# sourceMappingURL=shiny-showcase.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

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

File diff suppressed because one or more lines are too long

View File

@@ -480,6 +480,13 @@ textarea.textarea-autoresize.form-control {
cursor: not-allowed;
}
// Selectize's remove_button plugin has a bug that can lead to multiple remove
// buttons being displayed when options get updated. This prevents that from
// happening (see #4274 for reprex)
.shiny-input-select .selectize-input > .item > .remove:not(:first-child) {
display: none;
}
/* Hidden tabPanels */
.nav-hidden {
/* override anything bootstrap sets for `.nav` */

View File

@@ -1,4 +0,0 @@
module.exports = {
preset: "ts-jest",
testEnvironment: "jsdom",
};

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

@@ -28,6 +28,15 @@ of \code{\link[=testServer]{testServer()}}.
\dontrun{
session$setInputs(x=1, y=2)
}
## ------------------------------------------------
## Method `MockShinySession$removeInputs`
## ------------------------------------------------
\dontrun{
session$setInputs(x=1, y=2)
session$removeInputs("x")
}
}
\section{Public fields}{
\if{html}{\out{<div class="r6-fields">}}
@@ -95,6 +104,7 @@ user. Always \code{NULL} for a \code{MockShinySesion}.}
\item \href{#method-MockShinySession-cycleStartAction}{\code{MockShinySession$cycleStartAction()}}
\item \href{#method-MockShinySession-fileUrl}{\code{MockShinySession$fileUrl()}}
\item \href{#method-MockShinySession-setInputs}{\code{MockShinySession$setInputs()}}
\item \href{#method-MockShinySession-removeInputs}{\code{MockShinySession$removeInputs()}}
\item \href{#method-MockShinySession-.scheduleTask}{\code{MockShinySession$.scheduleTask()}}
\item \href{#method-MockShinySession-elapse}{\code{MockShinySession$elapse()}}
\item \href{#method-MockShinySession-.now}{\code{MockShinySession$.now()}}
@@ -279,6 +289,35 @@ session$setInputs(x=1, y=2)
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-removeInputs"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-removeInputs}{}}}
\subsection{Method \code{removeInputs()}}{
Removes inputs from the \code{session$inputs} object and flushes
the reactives.
\subsection{Usage}{
\if{html}{\out{<div class="r">}}\preformatted{MockShinySession$removeInputs(inputIds)}\if{html}{\out{</div>}}
}
\subsection{Arguments}{
\if{html}{\out{<div class="arguments">}}
\describe{
\item{\code{inputIds}}{Character vector of input ids to remove.}
}
\if{html}{\out{</div>}}
}
\subsection{Examples}{
\if{html}{\out{<div class="r example copy">}}
\preformatted{\dontrun{
session$setInputs(x=1, y=2)
session$removeInputs("x")
}
}
\if{html}{\out{</div>}}
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-.scheduleTask"></a>}}

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

6336
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,94 +1,77 @@
{
"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": {
"node": ">= 14",
"yarn": ">= 1.22"
"node": ">= 18",
"npm": ">= 10"
},
"dependencies": {
"@types/bootstrap": "3.4.0",
"@types/bootstrap-datepicker": "0.0.14",
"@types/datatables.net": "^1.10.19",
"@types/bootstrap": "5.2.x",
"@types/bootstrap-datepicker": "1.10.0",
"@types/datatables.net": "1.10.x",
"@types/ion-rangeslider": "2.3.0",
"@types/jquery": "3.5.32",
"@types/selectize": "0.12.34",
"lit": "^3.0.0"
"@types/selectize": "0.12.x",
"lit": "3.2.x"
},
"devDependencies": {
"@deanc/esbuild-plugin-postcss": "^1.0.2",
"@selectize/selectize": "https://github.com/selectize/selectize.js.git#e3f2e0b4aa251375bc21b5fcd8ca7d374a921f08",
"@testing-library/dom": "^7.31.0",
"@testing-library/jest-dom": "^5.12.0",
"@testing-library/user-event": "^13.1.9",
"@types/highlightjs": "^9.12.1",
"@types/jest": "^26.0.23",
"@types/highlightjs": "9.x",
"@types/jqueryui": "1.12.24",
"@types/lodash": "^4.14.170",
"@types/node": "^18.14.2",
"@types/showdown": "^1.9.3",
"@typescript-eslint/eslint-plugin": "^5.38.1",
"@typescript-eslint/parser": "^5.38.1",
"autoprefixer": "^10.2.6",
"browserslist": "^4.19.1",
"caniuse-lite": "^1.0.30001312",
"core-js": "^3.13.0",
"esbuild": "^0.15.10",
"esbuild-plugin-globals": "^0.1.1",
"esbuild-plugin-sass": "^1.0.1",
"eslint": "^8.24.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-jest": "^27.0.4",
"eslint-plugin-jest-dom": "^4.0.2",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-unicorn": "^43.0.2",
"fs-readdir-recursive": "^1.1.0",
"jest": "^26.6.3",
"@types/lodash": "4.x",
"@types/node": "18.x",
"@types/showdown": "1.x",
"@typescript-eslint/eslint-plugin": "8.x",
"@typescript-eslint/parser": "8.x",
"autoprefixer": "10.x",
"bootstrap-datepicker": "1.10.0",
"esbuild": ">=0.20.0",
"esbuild-plugin-globals": "0.1.x",
"esbuild-sass-plugin": "3.x",
"eslint": "9.x",
"eslint-config-prettier": "10.x",
"eslint-plugin-prettier": "5.x",
"eslint-plugin-unicorn": "56.x",
"fs-readdir-recursive": "1.x",
"jquery": "3.7.1",
"lodash": "^4.17.21",
"madge": "^4.0.2",
"node-gyp": "^8.1.0",
"phantomjs-prebuilt": "^2.1.16",
"postcss": "^8.3.5",
"prettier": "^2.7.1",
"prettier-plugin-organize-imports": "^3.2.4",
"readcontrol": "^1.0.0",
"replace": "^1.2.1",
"ts-jest": "^26",
"ts-node": "^10.9.1",
"type-coverage": "^2.22.0",
"typescript": "^4.8.4",
"util-inspect": "https://github.com/deecewan/browser-util-inspect#c0b4350df4378ffd743e8c36dd3898ce3992823e"
"lodash": "4.x",
"postcss": "8.x",
"postcss-preset-env": "10.2.x",
"prettier": "3.x",
"prettier-plugin-organize-imports": "4.x",
"readcontrol": "1.x",
"tsx": "4.x",
"type-coverage": "2.29.x",
"typescript": "5.8.x"
},
"scripts": {
"prepare": "node --eval \"1+1; // help yarn users not install the whole repo; https://github.com/yarnpkg/yarn/issues/2822#issuecomment-847360267\"",
"watch": "yarn run build_shiny --watch",
"build": "yarn run build_shiny && yarn run bundle_extras && yarn run bundle_external_libs",
"build_shiny": "yarn run checks && yarn run bundle_shiny",
"bundle_shiny": "ts-node srcts/build/shiny.ts",
"bundle_external_libs": "ts-node srcts/build/external_libs.ts",
"bundle_extras": "ts-node srcts/build/extras.ts",
"test": "jest --coverage",
"test_phantom": "echo '\n\t!! Must manually stop phantomjs test !!\n\n' && yarn bundle_shiny && phantomjs --debug=yes ../inst/www/shared/shiny.js",
"checks": "yarn run lint && yarn run build_types && yarn run coverage && yarn run circular",
"lint": "node --eval \"console.log('linting code...')\" && eslint --fix --ext .ts srcts/src",
"watch": "npm run bundle_shiny -- --watch",
"build": "npm run build_shiny && npm run bundle_extras && npm run bundle_external_libs",
"build_shiny": "npm run checks && npm run bundle_shiny",
"bundle_shiny": "tsx srcts/build/shiny.ts",
"bundle_external_libs": "tsx srcts/build/external_libs.ts",
"bundle_extras": "tsx srcts/build/extras.ts",
"checks": "npm run lint && npm run build_types && npm run coverage && npm run circular",
"lint": "node --eval \"console.log('linting code...')\" && eslint 'srcts/src/**/*.ts' --fix",
"build_types": "tsc -p tsconfig.json",
"coverage_detailed": "yarn type-check --detail",
"coverage_detailed": "npx --yes type-check --detail",
"coverage": "type-coverage -p tsconfig.json --at-least 90",
"circular": "madge --circular --extensions ts srcts/src",
"circular_image": "madge --circular --extensions ts --image madge.svg srcts/src"
"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

@@ -1,28 +1,29 @@
# Revdeps
## Failed to check (22)
## Failed to check (12)
|package |version |error |warning |note |
|:--------------------|:-------|:-----|:-------|:----|
|bigPint |? | | | |
|bioCancer |? | | | |
|EBImage |? | | | |
|FAfA |0.3 |1 | | |
|EMMAgeo |? | | | |
|FAfA |? | | | |
|fio |0.1.6 |1 | | |
|GeneNetworkBuilder |? | | | |
|gradientPickerD3 |? | | | |
|InterCellar |? | | | |
|LACE |? | | | |
|GDINA |? | | | |
|GSVA |? | | | |
|lavaan.shiny |1.2 |1 | | |
|LDABiplots |? | | | |
|LDAShiny |? | | | |
|loon.shiny |? | | | |
|MatrixQCvis |? | | | |
|metricsgraphics |? | | | |
|modchart |? | | | |
|omicsViewer |? | | | |
|RSP |0.4 |1 | | |
|Prostar |? | | | |
|rstanarm |2.32.1 |1 | | |
|sphereML |0.1.1 |1 | | |
|StatTeacherAssistant |? | | | |
|TestAnaAPP |1.1.2 |1 | | |
## New problems (5)
|package |version |error |warning |note |
|:-------------|:-------|:------|:-------|:------|
|[omicsTools](problems.md#omicstools)|1.0.5 |__+1__ | | |
|[PopED](problems.md#poped)|0.7.0 | | |__+1__ |
|[shinyGovstyle](problems.md#shinygovstyle)|0.1.0 |__+1__ | | |
|[ShinyLink](problems.md#shinylink)|0.2.2 |__+1__ | | |
|[shinySbm](problems.md#shinysbm)|0.1.5 |__+1__ | |1 |

View File

@@ -1,19 +1,37 @@
## revdepcheck results
We checked 1344 reverse dependencies (1330 from CRAN + 14 from Bioconductor), comparing R CMD check results across CRAN and dev versions of this package.
We checked 1349 reverse dependencies (1345 from CRAN + 4 from Bioconductor), comparing R CMD check results across CRAN and dev versions of this package.
* We saw 0 new problems
* We saw 5 new problems
* We failed to check 8 packages
Issues with CRAN packages are summarised below.
### New problems
(This reports the first line of each new failure)
* omicsTools
checking tests ... ERROR
* PopED
checking installed package size ... NOTE
* shinyGovstyle
checking tests ... ERROR
* ShinyLink
checking tests ... ERROR
* shinySbm
checking tests ... ERROR
### Failed to check
* FAfA (NA)
* fio (NA)
* GDINA (NA)
* lavaan.shiny (NA)
* loon.shiny (NA)
* RSP (NA)
* rstanarm (NA)
* sphereML (NA)
* TestAnaAPP (NA)

View File

@@ -1 +1,212 @@
*Wow, no problems at all. :)*
# omicsTools
<details>
* Version: 1.0.5
* GitHub: https://github.com/YaoxiangLi/omicsTools
* Source code: https://github.com/cran/omicsTools
* Date/Publication: 2023-07-03 16:20:02 UTC
* Number of recursive dependencies: 87
Run `revdepcheck::cloud_details(, "omicsTools")` for more info
</details>
## Newly broken
* checking tests ... ERROR
```
Running spelling.R
Running testthat.R
Running the tests in tests/testthat.R failed.
Complete output:
> # This file is part of the standard setup for testthat.
> # It is recommended that you do not modify it.
> #
> # Where should you do additional test configuration?
> # Learn more about the roles of various files in:
> # * https://r-pkgs.org/tests.html
...
lines(actual) vs lines(expected)
- "<button id=\"go_filter\" type=\"button\" class=\"btn btn-default action-button\" style=\"display: none;\">"
- " <span class=\"action-label\">go</span>"
- "</button>"
+ "<button id=\"go_filter\" type=\"button\" class=\"btn btn-default action-button\" style=\"display: none;\">go</button>"
[ FAIL 2 | WARN 0 | SKIP 1 | PASS 94 ]
Error: Test failures
Execution halted
```
# PopED
<details>
* Version: 0.7.0
* GitHub: https://github.com/andrewhooker/PopED
* Source code: https://github.com/cran/PopED
* Date/Publication: 2024-10-07 19:30:02 UTC
* Number of recursive dependencies: 139
Run `revdepcheck::cloud_details(, "PopED")` for more info
</details>
## Newly broken
* checking installed package size ... NOTE
```
installed size is 5.5Mb
sub-directories of 1Mb or more:
R 1.5Mb
doc 1.4Mb
test 1.1Mb
```
# shinyGovstyle
<details>
* Version: 0.1.0
* GitHub: https://github.com/moj-analytical-services/shinyGovstyle
* Source code: https://github.com/cran/shinyGovstyle
* Date/Publication: 2024-09-12 14:40:02 UTC
* Number of recursive dependencies: 48
Run `revdepcheck::cloud_details(, "shinyGovstyle")` for more info
</details>
## Newly broken
* checking tests ... ERROR
```
Running testthat.R
Running the tests in tests/testthat.R failed.
Complete output:
> library(testthat)
> library(shinyGovstyle)
>
> test_check("shinyGovstyle")
[ FAIL 1 | WARN 0 | SKIP 0 | PASS 125 ]
══ Failed tests ════════════════════════════════════════════════════════════════
── Failure ('test-backlink_Input.R:4:3'): backlink works ───────────────────────
backlink_check$children[[1]][[2]] not identical to "Back".
target is NULL, current is character
[ FAIL 1 | WARN 0 | SKIP 0 | PASS 125 ]
Error: Test failures
Execution halted
```
# ShinyLink
<details>
* Version: 0.2.2
* GitHub: NA
* Source code: https://github.com/cran/ShinyLink
* Date/Publication: 2023-01-18 11:40:05 UTC
* Number of recursive dependencies: 129
Run `revdepcheck::cloud_details(, "ShinyLink")` for more info
</details>
## Newly broken
* checking tests ... ERROR
```
Running spelling.R
Running testthat.R
Running the tests in tests/testthat.R failed.
Complete output:
> # This file is part of the standard setup for testthat.
> # It is recommended that you do not modify it.
> #
> # Where should you do additional test configuration?
> # Learn more about the roles of various files in:
> # * https://r-pkgs.org/tests.html
...
lines(actual) vs lines(expected)
- "<button id=\"go_filter\" type=\"button\" class=\"btn btn-default action-button\" style=\"display: none;\">"
- " <span class=\"action-label\">go</span>"
- "</button>"
+ "<button id=\"go_filter\" type=\"button\" class=\"btn btn-default action-button\" style=\"display: none;\">go</button>"
[ FAIL 2 | WARN 0 | SKIP 1 | PASS 145 ]
Error: Test failures
Execution halted
```
# shinySbm
<details>
* Version: 0.1.5
* GitHub: https://github.com/Jo-Theo/shinySbm
* Source code: https://github.com/cran/shinySbm
* Date/Publication: 2023-09-07 21:50:02 UTC
* Number of recursive dependencies: 134
Run `revdepcheck::cloud_details(, "shinySbm")` for more info
</details>
## Newly broken
* checking tests ... ERROR
```
Running spelling.R
Running testthat.R
Running the tests in tests/testthat.R failed.
Complete output:
> # This file is part of the standard setup for testthat.
> # It is recommended that you do not modify it.
> #
> # Where should you do additional test configuration?
> # Learn more about the roles of various files in:
> # * https://r-pkgs.org/tests.html
...
lines(actual) vs lines(expected)
- "<button id=\"go_filter\" type=\"button\" class=\"btn btn-default action-button\" style=\"display: none;\">"
- " <span class=\"action-label\">go</span>"
- "</button>"
+ "<button id=\"go_filter\" type=\"button\" class=\"btn btn-default action-button\" style=\"display: none;\">go</button>"
[ FAIL 2 | WARN 0 | SKIP 1 | PASS 141 ]
Error: Test failures
Execution halted
```
## In both
* checking Rd files ... NOTE
```
checkRd: (-1) FungusTreeNetwork.Rd:15-21: Lost braces in \itemize; meant \describe ?
checkRd: (-1) FungusTreeNetwork.Rd:22-28: Lost braces in \itemize; meant \describe ?
checkRd: (-1) FungusTreeNetwork.Rd:33-34: Lost braces in \itemize; meant \describe ?
checkRd: (-1) FungusTreeNetwork.Rd:33: Lost braces; missing escapes or markup?
33 | \item{tree_tree}{Results of \code{estimateSimpleSBM} for {sbm}
| ^
checkRd: (-1) FungusTreeNetwork.Rd:35-36: Lost braces in \itemize; meant \describe ?
checkRd: (-1) FungusTreeNetwork.Rd:35: Lost braces; missing escapes or markup?
35 | \item{fungus_tree}{Results of \code{estimateBipartiteSBM} for {sbm}
| ^
...
checkRd: (-1) visSbm.default.Rd:25: Lost braces in \itemize; meant \describe ?
checkRd: (-1) visSbm.default.Rd:26: Lost braces in \itemize; meant \describe ?
checkRd: (-1) visSbm.default.Rd:43-44: Lost braces in \itemize; meant \describe ?
checkRd: (-1) visSbm.default.Rd:45: Lost braces in \itemize; meant \describe ?
checkRd: (-1) visSbm.default.Rd:46: Lost braces in \itemize; meant \describe ?
checkRd: (-1) visSbm.default.Rd:47: Lost braces in \itemize; meant \describe ?
checkRd: (-1) visSbm.default.Rd:48: Lost braces in \itemize; meant \describe ?
checkRd: (-1) visSbm.default.Rd:49: Lost braces in \itemize; meant \describe ?
checkRd: (-1) visSbm.default.Rd:50: Lost braces in \itemize; meant \describe ?
checkRd: (-1) visSbm.default.Rd:51: Lost braces in \itemize; meant \describe ?
```

View File

@@ -1,14 +1,12 @@
# Using Shiny TypeScript Definitions
When developing TypeScript projects that use `window.Shiny`, we recommend installing the Shiny TypeScript definitions to your package. To install the latest stable definitions, run one of the following (depending on if you're using `npm` or `yarn`):
When developing TypeScript projects that use `window.Shiny`, we recommend installing the Shiny TypeScript definitions to your package. To install the latest stable definitions, run:
```bash
npm install https://github.com/rstudio/shiny\#v1.10.0 --save-dev
# or
yarn add https://github.com/rstudio/shiny\#v1.10.0 --dev
npm install https://github.com/rstudio/shiny\#v1.11.0 --save-dev
```
, matching the GitHub tag to your current the Shiny CRAN release (ex: `v1.10.0`). If you are asked to select a version of `@types/jquery`, please select the closest matching version.
, matching the GitHub tag to your current the Shiny CRAN release (ex: `v1.11.0`). If you are asked to select a version of `@types/jquery`, please select the closest matching version.
This will provide a global type definition of `window.Shiny`. In your code, you can access the Shiny object via `window.Shiny` or just `Shiny`. However, note that if you are using TypeScript, it will be OK with `window.Shiny` but it will flag uses of `Shiny` (without the `window.` prefix), because TypeScript won't know that it's a global variable. We consider it better practice to use `window.Shiny` instead of `Shiny`, but if you want TypeScript to know that `Shiny` is available as a global variable, you can add the following to a TypeScript file in your code base.
@@ -28,31 +26,36 @@ When loading your compiled file, it should be loaded after `shiny.js` is loaded.
All files will be described as if the working directory is the root folder of `rstudio/shiny`, not relative to this `README.md` file.
## First-time setup
Shiny's TypeScript build tools use Node.js, along with [yarn](https://yarnpkg.com/) v2 to manage the JavaScript packages.
Shiny's TypeScript build tools use Node.js and `npm`.
Installation of Node.js differs across platforms, see [the official Node.js website](https://nodejs.org/) for instructions on downloading and installing. We presume that you have Node.js installed on your machine before continuing.
Install yarn using the [official instructions](https://yarnpkg.com/en/docs/install).
Install npm using the [official instructions](https://docs.npmjs.com/getting-started/installing-node).
You can test that Node.js and yarn are installed properly by running the following commands:
You can test that Node.js and `npm` are installed properly by running the following commands:
```bash
node --version
yarn --version
npm --version
```
Once both are installed, run the following in the root repo directory to install the packages :
```bash
# Sitting in `rstudio/shiny` repo
yarn install
npm install
```
### Yarn v2
### Reproducible builds
This repo uses Yarn v2. If you have the latest yarn installed from brew (v1.x), Yarn will pick up on the fact that this repo is a Yarn v2 (`berry`) repo.
To ensure that the same versions of packages are used between users, install the package lock dependencies by running:
For compatibility with `esbuild`, the `./node_modules` is still maintained.
```bash
npm ci
```
This command will install the exact versions of packages specified in the `package-lock.json` file, ensuring that all developers are using the same versions of dependencies.
## Updating Node
@@ -69,26 +72,22 @@ npx n ls
```
## Adding packages
If in the future you want to upgrade or add a package, run:
```bash
yarn add --dev [packagename]
npm install --save-dev [packagename]
```
This will automatically add the package to the dependencies in `package.json`, and it will also update the `yarn.lock` to reflect that change. If someone other than yourself does this, simply run `yarn` to update your local packages to match the new `package.json`.
This will automatically add the package to the dependencies in `package.json`, and it will also update the `package-lock.json` to reflect that change. If someone other than yourself does this, simply run `npm ci` to update your local packages to match the new `package.json`.
## Upgrading packages
Periodically, it's good to upgrade the packages to a recent version. There's two ways of doing this, depending on your intention:
1. Use `yarn up` to upgrade all dependencies to their latest version based on the version range specified in the package.json file (the `yarn.lock` file will be recreated as well. Yarn packages use [semantic versioning](https://yarnpkg.com/en/docs/dependency-versions), i.e. each version is writen with a maximum of 3 dot-separated numbers such that: `major.minor.patch`. For example in the version `3.1.4`, 3 is the major version number, 1 is the minor version number and 4 is the patch version number. Here are the most used operators (these appear before the version number):
1. Use `npm outdated` to see outdated dependencies based on the version range specified in the `package.json` file. Npm packages use [semantic versioning](https://docs.npmjs.com/about-semantic-versioning), i.e. each version is writen with a maximum of 3 dot-separated numbers such that: `major.minor.patch`. For example in the version `3.1.4`, 3 is the major version number, 1 is the minor version number and 4 is the patch version number. Please use an `x` to denote where packages can automatically bump their version. For example, `3.1.x` will accept any patch version for `3.1`. Or `3.x` to accept any v3 minor version.
- `~` is for upgrades that keep the minor version the same (assuming that was specified);
- `^` is for upgrades that keep the major version the same (more or less -- more specifically, it allow changes that do not modify the first non-zero digit in the version, either the 3 in 3.1.4 or the 4 in 0.4.2.). This is the default operator added to the package.json when you run `yarn add [package-name]`.
2. Use `yarn up [package]` to upgrade a single named package to the version specified by the latest tag (potentially upgrading the package across major versions).
3. To see all outdated packages, run `yarn outdated`
2. Use `npm update [package]` to upgrade a single named package to the version specified by the latest tag (potentially upgrading the package across major versions).
# TypeScript
@@ -148,25 +147,16 @@ The JavaScript community likes to build many small, effective packages that do m
All config files are located in the root folder to avoid opening two separate VS Code projects.
* `.browserslistrc`
* Used with `browserslist` and `core-js` to determine which polyfills should be incorporated.
* `.eslintrc.yml`
* Used with `eslint` and `prettier` to determine how the TypeScript files should be formatted and which lint failures should cause warnings, errors, or be ignored.
* `.madgerc`
* Package used to determine if circular dependencies are found. `type` only imports are ignored as they are not included in the final bundle.
* `.prettierrc.yml`
* Used by `prettier` to know how to adjust code when a file is saved in VSCode or within `eslint`'s linting process.
* `yarnrc.yml`
* Notifies `yarn` to use `yarn` v2, install `./node_modules` folder for `esbuild`, and any CLI plugins.
* `jest.config.js`
* Used to configure [`jest` testing](https://jestjs.io/)
* `package.json`
* Contains useful scripts that can be run by `yarn` via `yarn run SCRIPTNAME`.
* Contains useful scripts that can be run by `npm` via `npm run SCRIPTNAME`.
* The scripts described below are inteded for developer use. All other scripts are means to an end.
* `yarn run watch` - Watch `srcts/src` for changes and rebuild the JavaScript files.
* `yarn run build` - Build `shiny.js` and `shiny.min.js` in `inst/www/shared`. Both files will have a corresponding sourcemap
* `yarn run lint` - Fix all TypeScript lints using [`eslint`](https://eslint.org/) and [`prettier`](https://prettier.io/)
* `yarn run test` - Run all TypeScript tests
* `npm run watch` - Watch `srcts/src` for changes and rebuild the JavaScript files.
* `npm run build` - Build `shiny.js` and `shiny.min.js` in `inst/www/shared`. Both files will have a corresponding sourcemap
* `npm run lint` - Fix all TypeScript lints using [`eslint`](https://eslint.org/) and [`prettier`](https://prettier.io/)
* `tsconfig.json` -
* TypeScript config file
* Notable options set:
@@ -181,13 +171,13 @@ All config files are located in the root folder to avoid opening two separate VS
To run all build tasks, run:
```bash
yarn build
npm run build
```
It's also useful to have `esbuild` watch for updated files and immediately re-build `shiny.js` as necessary during development. This is done with:
```bash
yarn watch
npm run watch
```
Both JavaScript files will produce a sourcemap (`**.js.map`) that the browser will understand. This will help you debug Shiny's JavaScript code within the browser and point back to the original TypeScript files.
@@ -200,40 +190,8 @@ Both JavaScript files will produce a sourcemap (`**.js.map`) that the browser wi
On push to the `main` branch or push to a Pull Request to the `main` branch, a GitHub Action will be run to make sure the bundled JavaScript code is up to date. If the source code does not compile to the exact same file, it will be committed an pushed back to the outdated branch. (This makes it so the full build tools are not necessary for small tweaks and comments. 🎉)
<!-- #### Auto build and browser refresh
An alternative to `yarn watch` is to use `entr` to trigger `grunt` when sources change. `entr` can be installed with `brew install entr` on a Mac, or on Linux using your distribution's package manager. Using this technique, it's possible to both automatically rebuild sources and reload Chrome at the same time:
*macOS*:
```bash
find ../srcts/ | entr bash -c './node_modules/grunt/bin/grunt && osascript -e "tell application \"Google Chrome\" to reload active tab of window 1"'
```
*Linux*:
For this to work you must first install `xdotool` using your distribution's package manager.
```bash
find ../srcts/ | entr bash -c './node_modules/grunt/bin/grunt && xdotool search --onlyvisible --class Chrome windowfocus key ctrl+r'
``` -->
# Updating dependencies
### `@types/jquery`
As of v3.5.5, `@types/jquery` produces a globally available constant of `$` and `jQuery`. This is problematic as TypeScript is there to enforce that all variables are accounted for. Declaring that these two variables exist globally removes the requirement to import `$` (or `jQuery`). This is bad for Shiny as the `$` would not be enforced to the "within package" `$`.
To overcome this, a patch is used to remove the globally defined `$` (and `Symbol`) variable declarations. Yarn v2 has a [`patch` protocol](https://yarnpkg.com/features/protocols#patch) that allows a local patch to be applied to the publically available `@types/jquery` package upon installation.
If in the future where the variables are not globally declared anymore, the patch may be removed and `@types/jquery` can be imported directly.
A global module plugin is used by `esbuild` to swap out a real `jquery` module to just return `window.jQuery`. This allows for tests and core code to behave the same way.
### `core-js`
To update the version of `core-js`:
* Check if there is a newer version available by running `yarn outdated core-js`. (If there's no output, then you have the latest version.)
* Run `yarn add --dev core-js --exact`.
### External libraries
@@ -245,3 +203,4 @@ Shiny already has a handful of html dependencies that should NOT be bundled with
* `bootstrap-datepicker` / `@types/bootstrap-datepicker`
* `ion-rangeslider` / `@types/ion-rangeslider`
* `selectize` / `@types/selectize`
* `strftime`

View File

@@ -1,11 +1,5 @@
import type {
BuildFailure,
BuildIncremental,
BuildOptions,
BuildResult,
WatchMode,
} from "esbuild";
import { build as esbuildBuild } from "esbuild";
import type { BuildOptions } from "esbuild";
import esbuild from "esbuild";
import { basename } from "path";
import process from "process";
@@ -29,9 +23,7 @@ const banner = {
css: bannerTxt,
};
async function build(
opts: BuildOptions
): Promise<BuildIncremental | BuildResult> {
async function build(opts: BuildOptions): Promise<void> {
const outFileNames = opts.outfile
? [basename(opts.outfile)]
: (opts.entryPoints as string[]).map((entry) => basename(entry));
@@ -48,7 +40,7 @@ async function build(
}
}
const onRebuild = function (error: BuildFailure | null) {
const onRebuild = function (error: any | null) {
if (error) {
console.error(printNames.join(", "), "watch build failed:\n", error);
} else {
@@ -59,29 +51,26 @@ async function build(
return;
};
let incremental = false;
let watch: WatchMode | false = false;
if (process.argv.length >= 3 && process.argv[2] == "--watch") {
incremental = true;
watch = {
onRebuild: onRebuild,
};
}
const watch = process.argv.length >= 3 && process.argv[2] == "--watch";
outFileNames.map((outFileName) => {
console.log("Building " + outFileName);
});
return esbuildBuild({
incremental: incremental,
watch: watch,
const ctx = await esbuild.context({
target: "es2021",
preserveSymlinks: true,
...opts,
}).then((x) => {
onRebuild(null);
return x;
});
if (watch) {
await ctx.watch();
onRebuild(null);
} else {
await ctx.rebuild();
onRebuild(null);
await ctx.dispose();
}
}
export { outDir, build, shinyDesc, banner };
export { banner, build, outDir, shinyDesc };

View File

@@ -1,11 +1,11 @@
// This build script must be executed from the root repo directory via
// ```
// yarn build
// npm run build
// ```
import { build, outDir } from "./_build";
import { readdir, unlink, writeFile } from "fs/promises";
import globalsPlugin from "esbuild-plugin-globals";
import { readdir, unlink, writeFile } from "fs/promises";
import { build, outDir } from "./_build";
const opts = {
bundle: false,

View File

@@ -1,63 +1,78 @@
// This build script must be executed from the root repo directory via
// ```
// yarn build
// npm run build
// ```
// - TypeScript -----------------------------------------------------------
import { banner, build, outDir } from "./_build";
build({
bundle: true,
sourcemap: true,
minify: true,
plugins: [],
banner: banner,
entryPoints: [
"srcts/extras/shiny-autoreload.ts",
"srcts/extras/shiny-showcase.ts",
"srcts/extras/shiny-testmode.ts",
],
outdir: outDir,
});
// - Sass -----------------------------------------------------------
import autoprefixer from "autoprefixer";
import sassPlugin from "esbuild-plugin-sass";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore; Type definitions are not found. This occurs when `strict: true` in tsconfig.json
import postCssPlugin from "@deanc/esbuild-plugin-postcss";
import { exec } from "child_process";
import { sassPlugin } from "esbuild-sass-plugin";
import postcss from "postcss";
import postcssPresetEnv from "postcss-preset-env";
import { promisify } from "util";
import { banner, build, outDir } from "./_build.js";
const execAsync = promisify(exec);
const sassOpts = {
minify: true,
banner: banner,
plugins: [
sassPlugin(),
postCssPlugin({
plugins: [autoprefixer],
sassPlugin({
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async transform(source: string, resolveDir: string) {
const { css } = await postcss([
autoprefixer,
postcssPresetEnv({ stage: 0 }),
]).process(source, { from: undefined });
return css;
},
}),
],
};
build({
...sassOpts,
entryPoints: ["srcts/extras/shiny-showcase.scss"],
outfile: outDir + "shiny-showcase.css",
});
build({
...sassOpts,
entryPoints: [
// Must keep shiny.scss within `inst` to be able to use as htmldependency
outDir + "shiny_scss/shiny.scss",
],
outfile: outDir + "shiny.min.css",
});
build({
...sassOpts,
entryPoints: ["srcts/extras/busy-indicators/busy-indicators.scss"],
outfile: outDir + "busy-indicators/busy-indicators.css",
plugins: [sassPlugin()],
bundle: false,
metafile: true,
async function main(): Promise<void> {
await Promise.all([
// - TypeScript -----------------------------------------------------------
// TypeScript builds
build({
bundle: true,
sourcemap: true,
minify: true,
plugins: [],
banner: banner,
entryPoints: [
"srcts/extras/shiny-autoreload.ts",
"srcts/extras/shiny-showcase.ts",
"srcts/extras/shiny-testmode.ts",
],
outdir: outDir,
}),
// Shiny sass MUST be built using `Rscript tools/updateShinyCss.R`
execAsync("Rscript tools/updateShinyCss.R").then(({ stdout, stderr }) => {
if (stdout) console.log(stdout);
if (stderr) console.error(stderr);
}),
// Sass builds
build({
...sassOpts,
entryPoints: ["srcts/extras/shiny-showcase.scss"],
outfile: outDir + "shiny-showcase.css",
}),
build({
...sassOpts,
entryPoints: ["srcts/extras/busy-indicators/busy-indicators.scss"],
outfile: outDir + "busy-indicators/busy-indicators.css",
plugins: [sassPlugin()],
bundle: false,
metafile: true,
}),
]);
}
main().catch((err) => {
console.error("Error:\n" + err);
process.exit(1);
});

View File

@@ -1,6 +1,6 @@
// This build script must be executed from the root repo directory via
// ```
// yarn build
// npm run build
// ```
import type { BuildOptions } from "esbuild";
@@ -29,6 +29,7 @@ const opts: BuildOptions = {
// Make sure all ts files contain jquery import statements before building
verifyJqueryImport("srcts/src")
.then(() => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
Promise.all([
build({
...opts,

View File

@@ -15,11 +15,14 @@ const animateMs = 400;
// If the given count is bigger than the number of characters contained by
// the node and its siblings, returns a null node and the number of
// characters found.
function findTextColPoint(node: Node, col: number) {
function findTextColPoint(
node: Node,
col: number,
): { element: Node | null; offset: number } {
let cols = 0;
if (node.nodeType === 3) {
const nchar = node.nodeValue.replace(/\n/g, "").length;
const nchar = node.nodeValue?.replace(/\n/g, "").length ?? 0;
if (nchar >= col) {
return { element: node, offset: col };
@@ -44,7 +47,11 @@ function findTextColPoint(node: Node, col: number) {
//
// If the given line and column are not found, returns a null element and
// the number of lines found.
function findTextPoint(el: Node, line: number, col: number) {
function findTextPoint(
el: Node,
line: number,
col: number,
): { element: Node | null; offset: number } {
let newlines = 0;
for (let childId = 0; childId < el.childNodes.length; childId++) {
@@ -56,7 +63,7 @@ function findTextPoint(el: Node, line: number, col: number) {
const newlinere = /\n/g;
let match: ReturnType<RegExp["exec"]>;
while ((match = newlinere.exec(child.nodeValue)) !== null) {
while ((match = newlinere.exec(child.nodeValue!)) !== null) {
newlines++;
// Found the desired line, now find the column.
if (newlines === line) {
@@ -82,7 +89,7 @@ function findTextPoint(el: Node, line: number, col: number) {
// refs.
function highlightSrcref(
srcref: ShowcaseSrcMessage["srcref"],
srcfile: ShowcaseSrcMessage["srcfile"]
srcfile: ShowcaseSrcMessage["srcfile"],
) {
// Check to see if the browser supports text ranges (IE8 doesn't)
if (!document.createRange) return;
@@ -112,7 +119,7 @@ function highlightSrcref(
// the SPANs.
if (
start.element.parentNode.nodeName === "SPAN" &&
start.element.parentNode?.nodeName === "SPAN" &&
start.element !== end.element
) {
range.setStartBefore(start.element.parentNode);
@@ -120,7 +127,7 @@ function highlightSrcref(
range.setStart(start.element, start.offset);
}
if (
end.element.parentNode.nodeName === "SPAN" &&
end.element.parentNode?.nodeName === "SPAN" &&
start.element !== end.element
) {
range.setEndAfter(end.element.parentNode);
@@ -136,14 +143,14 @@ function highlightSrcref(
// If this is the main Shiny window, wire up our custom message handler.
// TODO-barret, this should work
if (Shiny) {
Shiny.addCustomMessageHandler(
if (window.Shiny) {
window.Shiny.addCustomMessageHandler(
"showcase-src",
function (message: ShowcaseSrcMessage) {
if (message.srcref && message.srcfile) {
highlightSrcref(message.srcref, message.srcfile);
}
}
},
);
}
@@ -174,10 +181,24 @@ const setCodePosition = function (above: boolean, animate: boolean) {
}
// hide the new element before doing anything to it
if (newHostElement === null || currentHostElement === null) {
console.warn(
"Could not find the host elements for the code tabs. " +
"This is likely a bug in the showcase app.",
);
return;
}
$(newHostElement).hide();
$(currentHostElement).fadeOut(animateCodeMs, function () {
const tabs = document.getElementById("showcase-code-tabs");
if (tabs === null) {
console.warn(
"Could not find the code tabs element. This is likely a bug in the showcase app.",
);
return;
}
currentHostElement.removeChild(tabs);
newHostElement.appendChild(tabs);
@@ -185,7 +206,9 @@ const setCodePosition = function (above: boolean, animate: boolean) {
if (above) {
setCodeHeightFromDocHeight();
} else {
document.getElementById("showcase-code-content").removeAttribute("style");
document
.getElementById("showcase-code-content")
?.removeAttribute("style");
}
$(newHostElement).fadeIn(animateCodeMs);
@@ -194,27 +217,29 @@ const setCodePosition = function (above: boolean, animate: boolean) {
// scroll smoothly down to the code's new home
document
.getElementById("showcase-app-container")
.removeAttribute("style");
if (animate)
$(document.body).animate({
scrollTop: $(newHostElement).offset().top,
});
?.removeAttribute("style");
if (animate) {
const top = $(newHostElement).offset()?.top;
if (top !== undefined) {
$(document.body).animate({ scrollTop: top });
}
}
}
// if there's a readme, move it either alongside the code or beneath
// the app
const readme = document.getElementById("readme-md");
if (readme !== null) {
readme.parentElement.removeChild(readme);
readme.parentElement?.removeChild(readme);
if (above) {
currentHostElement.appendChild(readme);
$(currentHostElement).fadeIn(animateCodeMs);
} else
document.getElementById("showcase-app-metadata").appendChild(readme);
document.getElementById("showcase-app-metadata")?.appendChild(readme);
}
// change the text on the toggle button to reflect the new state
document.getElementById("showcase-code-position-toggle").innerHTML = above
document.getElementById("showcase-code-position-toggle")!.innerHTML = above
? '<i class="fa fa-level-down"></i> show below'
: '<i class="fa fa-level-up"></i> show with app';
});
@@ -230,7 +255,7 @@ function setAppCodeSxsWidths(animate: boolean) {
const appTargetWidth = 960;
let appWidth = appTargetWidth;
let zoom = 1.0;
const totalWidth = document.getElementById("showcase-app-code").offsetWidth;
const totalWidth = document.getElementById("showcase-app-code")!.offsetWidth;
if (totalWidth / 2 > appTargetWidth) {
// If the app can use only half the available space and still meet its
@@ -246,14 +271,12 @@ function setAppCodeSxsWidths(animate: boolean) {
appWidth = totalWidth * 0.66;
zoom = appWidth / appTargetWidth;
}
const app = document.getElementById("showcase-app-container");
$(app).animate(
$("#showcase-app-container").animate(
{
width: appWidth + "px",
zoom: zoom * 100 + "%",
},
animate ? animateMs : 0
animate ? animateMs : 0,
);
}
@@ -272,7 +295,7 @@ const setInitialCodePosition = function () {
// make the code scrollable to about the height of the browser, less space
// for the tabs
function setCodeHeightFromDocHeight() {
document.getElementById("showcase-code-content").style.height =
document.getElementById("showcase-code-content")!.style.height =
$(window).height() + "px";
}
@@ -288,7 +311,7 @@ function renderMarkdown() {
const showdownConverter = (window as any).Showdown
.converter as showdown.ConverterStatic;
document.getElementById("readme-md").innerHTML =
document.getElementById("readme-md")!.innerHTML =
new showdownConverter().makeHtml(content);
}
}

View File

@@ -11,7 +11,7 @@ type ActionButtonReceiveMessageData = {
};
class ActionButtonInputBinding extends InputBinding {
find(scope: HTMLElement): JQuery<HTMLElement> {
find(scope: HTMLElement): JQuery {
return $(scope).find(".action-button");
}
getValue(el: HTMLElement): number {
@@ -22,7 +22,7 @@ class ActionButtonInputBinding extends InputBinding {
}
getType(el: HTMLElement): string {
return "shiny.action";
el;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
subscribe(el: HTMLElement, callback: (x: boolean) => void): void {
$(el).on(
@@ -35,7 +35,7 @@ class ActionButtonInputBinding extends InputBinding {
$el.data("val", val + 1);
callback(false);
}
},
);
}
getState(el: HTMLElement): { value: number } {
@@ -43,11 +43,11 @@ class ActionButtonInputBinding extends InputBinding {
}
async receiveMessage(
el: HTMLElement,
data: ActionButtonReceiveMessageData
data: ActionButtonReceiveMessageData,
): Promise<void> {
if (hasDefinedProperty(data, "icon")) {
let iconContainer = el.querySelector<HTMLElement>(
":scope > .action-icon"
":scope > .action-icon",
);
// If no container exists yet, create one
if (!iconContainer) {
@@ -55,19 +55,19 @@ class ActionButtonInputBinding extends InputBinding {
iconContainer.className = "action-icon";
el.prepend(iconContainer);
}
await renderContent(iconContainer, data.icon);
await renderContent(iconContainer, data.icon!);
}
if (hasDefinedProperty(data, "label")) {
let labelContainer = el.querySelector<HTMLElement>(
":scope > .action-label"
":scope > .action-label",
);
if (!labelContainer) {
labelContainer = document.createElement("span");
labelContainer.className = "action-label";
el.appendChild(labelContainer);
}
await renderContent(labelContainer, data.label);
await renderContent(labelContainer, data.label!);
}
if (hasDefinedProperty(data, "disabled")) {
@@ -77,6 +77,7 @@ class ActionButtonInputBinding extends InputBinding {
el.removeAttribute("disabled");
}
}
return;
}
unsubscribe(el: HTMLElement): void {

View File

@@ -39,17 +39,17 @@ class CheckboxInputBinding extends InputBinding {
}
async receiveMessage(
el: CheckedHTMLElement,
data: CheckboxReceiveMessageData
data: CheckboxReceiveMessageData,
): Promise<void> {
if (hasDefinedProperty(data, "value")) {
el.checked = data.value;
el.checked = data.value!;
}
// checkboxInput()'s label works different from other
// input labels...the label container should always exist
if (hasDefinedProperty(data, "label")) {
const labelSpan = $(el).parent().find("span");
await renderContent(labelSpan, data.label);
await renderContent(labelSpan, data.label!);
}
$(el).trigger("change");
@@ -57,4 +57,4 @@ class CheckboxInputBinding extends InputBinding {
}
export { CheckboxInputBinding };
export type { CheckedHTMLElement, CheckboxReceiveMessageData };
export type { CheckboxReceiveMessageData, CheckedHTMLElement };

View File

@@ -77,7 +77,7 @@ class CheckboxGroupInputBinding extends InputBinding {
$escape(el.id) +
'"][value="' +
$escape(value[i]) +
'"]'
'"]',
).prop("checked", true);
}
// Else assume it's a single value
@@ -87,7 +87,7 @@ class CheckboxGroupInputBinding extends InputBinding {
$escape(el.id) +
'"][value="' +
$escape(value) +
'"]'
'"]',
).prop("checked", true);
}
}
@@ -97,7 +97,7 @@ class CheckboxGroupInputBinding extends InputBinding {
options: ValueLabelObject[];
} {
const $objs = $(
'input:checkbox[name="' + $escape(el.id) + '"]'
'input:checkbox[name="' + $escape(el.id) + '"]',
) as JQuery<CheckboxGroupHTMLElement>;
// Store options in an array of objects, each with with value and label
@@ -115,7 +115,7 @@ class CheckboxGroupInputBinding extends InputBinding {
}
async receiveMessage(
el: CheckboxGroupHTMLElement,
data: CheckboxGroupReceiveMessageData
data: CheckboxGroupReceiveMessageData,
): Promise<void> {
const $el = $(el);
@@ -125,11 +125,11 @@ class CheckboxGroupInputBinding extends InputBinding {
$el.find("div.shiny-options-group").remove();
// Backward compatibility: for HTML generated by shinybootstrap2 package
$el.find("label.checkbox").remove();
$el.append(data.options);
$el.append(data.options!);
}
if (hasDefinedProperty(data, "value")) {
this.setValue(el, data.value);
this.setValue(el, data.value!);
}
await updateLabel(data.label, getLabelNode(el));
@@ -138,7 +138,7 @@ class CheckboxGroupInputBinding extends InputBinding {
}
subscribe(
el: CheckboxGroupHTMLElement,
callback: (x: boolean) => void
callback: (x: boolean) => void,
): void {
$(el).on("change.checkboxGroupInputBinding", function () {
callback(false);

View File

@@ -15,10 +15,10 @@ declare global {
bsDatepicker(methodName: "getUTCDate"): Date;
// Infinity is not allowed as a literal return type. Using `1e9999` as a placeholder that resolves to Infinity
// https://github.com/microsoft/TypeScript/issues/32277
// eslint-disable-next-line @typescript-eslint/no-loss-of-precision
bsDatepicker(methodName: "getStartDate"): Date | -1e9999;
// eslint-disable-next-line @typescript-eslint/no-loss-of-precision
bsDatepicker(methodName: "getEndDate"): Date | 1e9999;
bsDatepicker(methodName: "getStartDate"): Date | -1e9999; // eslint-disable-line no-loss-of-precision
bsDatepicker(methodName: "getEndDate"): Date | 1e9999; // eslint-disable-line no-loss-of-precision
bsDatepicker(methodName: string): void;
bsDatepicker(methodName: string, params: Date | null): void;
}
@@ -37,7 +37,7 @@ class DateInputBindingBase extends InputBinding {
}
getType(el: HTMLElement): string {
return "shiny.date";
el;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
subscribe(el: HTMLElement, callback: (x: boolean) => void): void {
// Don't update when in the middle of typing; listening on keyup or input
@@ -50,7 +50,7 @@ class DateInputBindingBase extends InputBinding {
// Send immediately when clicked
// Or if typing, when enter pressed or focus lost
callback(false);
}
},
);
}
unsubscribe(el: HTMLElement): void {
@@ -66,8 +66,8 @@ class DateInputBindingBase extends InputBinding {
setValue(el: HTMLElement, data: unknown): void {
throw "not implemented";
el;
data;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
data; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
initialize(el: HTMLElement): void {
const $input = $(el).find("input");
@@ -294,20 +294,20 @@ class DateInputBinding extends DateInputBindingBase {
}
async receiveMessage(
el: HTMLElement,
data: DateReceiveMessageData
data: DateReceiveMessageData,
): Promise<void> {
const $input = $(el).find("input");
await updateLabel(data.label, this._getLabelNode(el));
if (hasDefinedProperty(data, "min")) this._setMin($input[0], data.min);
if (hasDefinedProperty(data, "min")) this._setMin($input[0], data.min!);
if (hasDefinedProperty(data, "max")) this._setMax($input[0], data.max);
if (hasDefinedProperty(data, "max")) this._setMax($input[0], data.max!);
// Must set value only after min and max have been set. If new value is
// outside the bounds of the previous min/max, then the result will be a
// blank input.
if (hasDefinedProperty(data, "value")) this.setValue(el, data.value);
if (hasDefinedProperty(data, "value")) this.setValue(el, data.value!);
$(el).trigger("change");
}

View File

@@ -108,7 +108,7 @@ class DateRangeInputBinding extends DateInputBindingBase {
}
async receiveMessage(
el: HTMLElement,
data: DateRangeReceiveMessageData
data: DateRangeReceiveMessageData,
): Promise<void> {
const $el = $(el);
const $inputs = $el.find("input");
@@ -118,20 +118,20 @@ class DateRangeInputBinding extends DateInputBindingBase {
await updateLabel(data.label, getLabelNode(el));
if (hasDefinedProperty(data, "min")) {
this._setMin($startinput[0], data.min);
this._setMin($endinput[0], data.min);
this._setMin($startinput[0], data.min!);
this._setMin($endinput[0], data.min!);
}
if (hasDefinedProperty(data, "max")) {
this._setMax($startinput[0], data.max);
this._setMax($endinput[0], data.max);
this._setMax($startinput[0], data.max!);
this._setMax($endinput[0], data.max!);
}
// Must set value only after min and max have been set. If new value is
// outside the bounds of the previous min/max, then the result will be a
// blank input.
if (hasDefinedProperty(data, "value")) {
this.setValue(el, data.value);
this.setValue(el, data.value!);
}
$el.trigger("change");
@@ -174,7 +174,7 @@ class DateRangeInputBinding extends DateInputBindingBase {
// Send immediately when clicked
// Or if typing, when enter pressed or focus lost
callback(false);
}
},
);
}
unsubscribe(el: HTMLElement): void {

View File

@@ -88,6 +88,7 @@ function canSetFiles(fileList: FileList): boolean {
testEl.files = fileList;
} catch (e) {
return false;
e; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
return true;
}
@@ -99,7 +100,7 @@ function handleDrop(e: JQuery.DragEventBase, el: HTMLInputElement): void {
// 1. The FileList object isn't supported by this browser, and
// there's nothing else we can try. (< IE 10)
console.log(
"Dropping files is not supported on this browser. (no FileList)"
"Dropping files is not supported on this browser. (no FileList)",
);
} else if (!canSetFiles(files)) {
// 2. The browser doesn't support assigning a type=file input's .files
@@ -146,7 +147,7 @@ function abortCurrentUpload($el: JQuery<EventTarget>) {
function uploadDroppedFilesIE10Plus(
el: HTMLInputElement,
files: FileList
files: FileList,
): void {
const $el = $(el);
@@ -158,7 +159,7 @@ function uploadDroppedFilesIE10Plus(
// Start the new upload and put the uploader in 'currentUploader'.
$el.data(
"currentUploader",
new FileUploader(shinyShinyApp(), fileInputBindingGetId(el), files, el)
new FileUploader(shinyShinyApp(), fileInputBindingGetId(el), files, el),
);
}
@@ -178,7 +179,7 @@ function uploadFiles(evt: JQuery.DragEvent): void {
// Start the new upload and put the uploader in 'currentUploader'.
$el.data(
"currentUploader",
new FileUploader(shinyShinyApp(), id, files, evt.target)
new FileUploader(shinyShinyApp(), id, files, evt.target),
);
}
@@ -237,17 +238,18 @@ class FileInputBinding extends InputBinding {
}
setValue(el: HTMLElement, value: void): void {
// Not implemented
el;
value;
return;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
value; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
getType(el: HTMLElement): string {
// This will be used only when restoring a file from a saved state.
return "shiny.file";
el;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
subscribe(el: HTMLInputElement, callback: (x: boolean) => void): void {
callback;
callback; // eslint-disable-line @typescript-eslint/no-unused-expressions
$(el).on("change.fileInputBinding", uploadFiles);
// Here we try to set up the necessary events for Drag and Drop ("DnD").
@@ -257,8 +259,9 @@ class FileInputBinding extends InputBinding {
enableDraghover($zone).on({
"draghover:enter.draghover": (e) => {
e;
$zone.addClass(zoneOver);
return;
e; // eslint-disable-line @typescript-eslint/no-unused-expressions
},
"draghover:leave.draghover": (e) => {
$zone.removeClass(zoneOver);
@@ -267,8 +270,9 @@ class FileInputBinding extends InputBinding {
e.stopPropagation();
},
"draghover:drop.draghover": (e, dropEvent) => {
e;
handleDrop(dropEvent, el);
return;
e; // eslint-disable-line @typescript-eslint/no-unused-expressions
},
});
}

View File

@@ -31,7 +31,7 @@ function initInputBindings(): {
inputBindings.register(new CheckboxInputBinding(), "shiny.checkboxInput");
inputBindings.register(
new CheckboxGroupInputBinding(),
"shiny.checkboxGroupInput"
"shiny.checkboxGroupInput",
);
inputBindings.register(new RadioInputBinding(), "shiny.radioInput");
inputBindings.register(new SliderInputBinding(), "shiny.sliderInput");
@@ -40,11 +40,11 @@ function initInputBindings(): {
inputBindings.register(new SelectInputBinding(), "shiny.selectInput");
inputBindings.register(
new ActionButtonInputBinding(),
"shiny.actionButtonInput"
"shiny.actionButtonInput",
);
inputBindings.register(
new BootstrapTabInputBinding(),
"shiny.bootstrapTabInput"
"shiny.bootstrapTabInput",
);
const fileInputBinding = new FileInputBinding();

View File

@@ -24,7 +24,7 @@ class InputBinding {
// descendants of scope that match this binding
find(scope: BindScope): JQuery<HTMLElement> {
throw "Not implemented";
scope; // unused var
scope; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
getId(el: HTMLElement): string {
@@ -35,21 +35,23 @@ class InputBinding {
// to deserialize the JSON correctly
getType(el: HTMLElement): string | null {
return null;
el; // unused var
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
getValue(el: HTMLElement): any {
throw "Not implemented";
el; // unused var
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
subscribe(el: HTMLElement, callback: InputSubscribeCallback): void {
// empty
el; // unused var
callback; // unused var
return;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
callback; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
unsubscribe(el: HTMLElement): void {
// empty
el; // unused var
return;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
// This is used for receiving messages that tell the input object to do
@@ -59,19 +61,19 @@ class InputBinding {
// trigger a change event.
receiveMessage(el: HTMLElement, data: unknown): Promise<void> | void {
throw "Not implemented";
el; // unused var
data; // unused var
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
data; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
getState(el: HTMLElement): unknown {
throw "Not implemented";
el; // unused var
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
getRatePolicy(
el: HTMLElement
el: HTMLElement,
): { policy: RatePolicyModes; delay: number } | null {
return null;
el; // unused var
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
// Some input objects need initialization before being bound. This is
@@ -81,13 +83,15 @@ class InputBinding {
// This is called before the input is bound.
initialize(el: HTMLElement): void {
//empty
el;
return;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
// This is called after unbinding the output.
dispose(el: HTMLElement): void {
//empty
el;
return;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
}

View File

@@ -25,7 +25,7 @@ class NumberInputBinding extends TextInputBindingBase {
}
getValue(
el: NumberHTMLElement
el: NumberHTMLElement,
): string[] | number | string | null | undefined {
const numberVal = $(el).val();
@@ -49,11 +49,11 @@ class NumberInputBinding extends TextInputBindingBase {
}
getType(el: NumberHTMLElement): string {
return "shiny.number";
el;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
async receiveMessage(
el: NumberHTMLElement,
data: NumberReceiveMessageData
data: NumberReceiveMessageData,
): Promise<void> {
// Setting values to `""` will remove the attribute value from the DOM element.
// The attr key will still remain, but there is not value... ex: `<input id="foo" type="number" min max/>`

View File

@@ -10,7 +10,7 @@ class PasswordInputBinding extends TextInputBinding {
getType(el: HTMLElement): string {
return "shiny.password";
el;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
}

View File

@@ -52,11 +52,11 @@ class RadioInputBinding extends InputBinding {
return $(scope).find(".shiny-input-radiogroup");
}
getValue(
el: RadioHTMLElement
el: RadioHTMLElement,
): string[] | number | string | null | undefined {
// Select the radio objects that have name equal to the grouping div's id
const checkedItems = $(
'input:radio[name="' + $escape(el.id) + '"]:checked'
'input:radio[name="' + $escape(el.id) + '"]:checked',
);
if (checkedItems.length === 0) {
@@ -77,7 +77,7 @@ class RadioInputBinding extends InputBinding {
$escape(el.id) +
'"][value="' +
$escape(value) +
'"]'
'"]',
).prop("checked", true);
}
}
@@ -87,7 +87,7 @@ class RadioInputBinding extends InputBinding {
options: ValueLabelObject[];
} {
const $objs = $(
'input:radio[name="' + $escape(el.id) + '"]'
'input:radio[name="' + $escape(el.id) + '"]',
) as JQuery<RadioHTMLElement>;
// Store options in an array of objects, each with with value and label
@@ -105,7 +105,7 @@ class RadioInputBinding extends InputBinding {
}
async receiveMessage(
el: RadioHTMLElement,
data: RadioReceiveMessageData
data: RadioReceiveMessageData,
): Promise<void> {
const $el = $(el);
// This will replace all the options
@@ -122,7 +122,7 @@ class RadioInputBinding extends InputBinding {
}
if (hasDefinedProperty(data, "value")) {
this.setValue(el, data.value);
this.setValue(el, data.value!);
}
await updateLabel(data.label, getLabelNode(el));

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> {
@@ -30,7 +44,7 @@ function getLabelNode(el: SelectHTMLElement): JQuery<HTMLElement> {
.find('label[for="' + escapedId + '"]');
}
// Return true if it's a selectize input, false if it's a regular select input.
// eslint-disable-next-line camelcase
function isSelectize(el: HTMLElement): boolean {
const config = $(el)
.parent()
@@ -85,7 +99,7 @@ class SelectInputBinding extends InputBinding {
} {
// Store options in an array of objects, each with with value and label
const options: Array<{ value: string; label: string }> = new Array(
el.length
el.length,
);
for (let i = 0; i < el.length; i++) {
@@ -104,7 +118,7 @@ class SelectInputBinding extends InputBinding {
}
async receiveMessage(
el: SelectHTMLElement,
data: SelectInputReceiveMessageData
data: SelectInputReceiveMessageData,
): Promise<void> {
const $el = $(el);
@@ -116,7 +130,7 @@ class SelectInputBinding extends InputBinding {
// selectize will restore the original select
selectize?.destroy();
// Clear existing options and add each new one
$el.empty().append(data.options);
$el.empty().append(data.options!);
this._selectize(el);
}
@@ -125,7 +139,7 @@ class SelectInputBinding extends InputBinding {
$el
.parent()
.find('script[data-for="' + $escape(el.id) + '"]')
.replaceWith(data.config);
.replaceWith(data.config!);
this._selectize(el, true);
}
@@ -154,7 +168,6 @@ class SelectInputBinding extends InputBinding {
selectize.settings.load = function (query: string, callback: CallbackFn) {
const settings = selectize.settings;
/* eslint-disable-next-line @typescript-eslint/no-floating-promises */
$.ajax({
url: data.url,
data: {
@@ -202,6 +215,7 @@ class SelectInputBinding extends InputBinding {
selectize.settings.load.apply(selectize, ["", callback]);
});
} else if (hasDefinedProperty(data, "value")) {
// @ts-expect-error; data.value is currently a never type
this.setValue(el, data.value);
}
@@ -221,7 +235,7 @@ class SelectInputBinding extends InputBinding {
return;
}
callback(false);
}
},
);
}
unsubscribe(el: HTMLElement): void {
@@ -232,7 +246,7 @@ class SelectInputBinding extends InputBinding {
}
protected _selectize(
el: SelectHTMLElement,
update = false
update = false,
): SelectizeInfo | undefined {
// Apps like 008-html do not have the selectize js library
// Safe-guard against missing the selectize js library
@@ -244,21 +258,17 @@ 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",
searchField: ["label"],
},
JSON.parse(config.html())
JSON.parse(config.html()),
);
options = this._addShinyRemoveButton(options, el.hasAttribute("multiple"));
// selectize created from selectInput()
if (typeof config.data("nonempty") !== "undefined") {
el.nonempty = true;
@@ -271,7 +281,7 @@ class SelectInputBinding extends InputBinding {
$("<option/>", {
value: value,
selected: true,
})
}),
)
.trigger("change");
},
@@ -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

@@ -61,7 +61,7 @@ type Prettify = (num: number) => string;
function getTypePrettifyer(
dataType: string,
timeFormat: string,
timezone: string
timezone: string,
) {
let timeFormatter: TimeFormatter;
let prettify: Prettify;
@@ -121,7 +121,7 @@ class SliderInputBinding extends TextInputBindingBase {
else return null;
}
getValue(
el: TextHTMLElement
el: TextHTMLElement,
): number | string | [number | string, number | string] {
const $el = $(el);
const result = $(el).data("ionRangeSlider").result as IonRangeSliderEvent;
@@ -153,7 +153,7 @@ class SliderInputBinding extends TextInputBindingBase {
}
setValue(
el: HTMLElement,
value: number | string | [number | string, number | string]
value: number | string | [number | string, number | string],
): void {
const $el = $(el);
const slider = $el.data("ionRangeSlider");
@@ -181,7 +181,7 @@ class SliderInputBinding extends TextInputBindingBase {
}
async receiveMessage(
el: HTMLElement,
data: SliderReceiveMessageData
data: SliderReceiveMessageData,
): Promise<void> {
const $el = $(el);
const slider = $el.data("ionRangeSlider");
@@ -242,7 +242,7 @@ class SliderInputBinding extends TextInputBindingBase {
const elem = domElements[i];
if (hasDefinedProperty(data, elem)) {
$el.data(elem, data[elem]);
$el.data(elem, data[elem]!);
}
}
@@ -266,12 +266,13 @@ class SliderInputBinding extends TextInputBindingBase {
policy: "debounce",
delay: 250,
};
el;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
// TODO-barret Why not implemented?
getState(el: HTMLInputElement): void {
// empty
el;
return;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
initialize(el: HTMLElement): void {
@@ -297,14 +298,14 @@ class SliderInputBinding extends TextInputBindingBase {
function formatNumber(
num: number,
thousandSep = ",",
decimalSep = "."
decimalSep = ".",
): string {
const parts = num.toString().split(".");
// Add separators to portion before decimal mark.
parts[0] = parts[0].replace(
/(\d{1,3}(?=(?:\d\d\d)+(?!\d)))/g,
"$1" + thousandSep
"$1" + thousandSep,
);
if (parts.length === 1) return parts[0];
@@ -375,14 +376,14 @@ $(document).on("click", ".slider-animate-button", function (evt: Event) {
const val: { from: number; to?: number } = {
from: Math.min(
slider.result.max,
slider.result.from + slider.options.step
slider.result.from + slider.options.step,
),
};
if (slider.options.type === "double")
val.to = Math.min(
slider.result.max,
slider.result.to + slider.options.step
slider.result.to + slider.options.step,
);
slider.update(val);

View File

@@ -65,7 +65,7 @@ class BootstrapTabInputBinding extends InputBinding {
// event: Event
function () {
callback(false);
}
},
);
}
unsubscribe(el: HTMLElement): void {

View File

@@ -23,7 +23,7 @@ function getLabelNode(el: HTMLElement): JQuery<HTMLElement> {
class TextInputBindingBase extends InputBinding {
find(scope: HTMLElement): JQuery<HTMLElement> {
const $inputs = $(scope).find(
'input[type="text"], input[type="search"], input[type="url"], input[type="email"]'
'input[type="text"], input[type="search"], input[type="url"], input[type="email"]',
);
// selectize.js 0.12.4 inserts a hidden text input with an
// id that ends in '-selectized'. The .not() selector below
@@ -41,12 +41,12 @@ class TextInputBindingBase extends InputBinding {
getValue(el: TextHTMLElement): unknown {
throw "not implemented";
el;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
setValue(el: TextHTMLElement, value: unknown): void {
throw "not implemented";
el;
value;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
value; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
subscribe(el: TextHTMLElement, callback: (x: boolean) => void): void {
@@ -59,7 +59,7 @@ class TextInputBindingBase extends InputBinding {
// event: Event
function () {
callback(true);
}
},
);
} else if (updateOn === "blur") {
$el.on("blur.textInputBinding", function () {
@@ -88,13 +88,13 @@ class TextInputBindingBase extends InputBinding {
receiveMessage(el: TextHTMLElement, data: unknown): void {
throw "not implemented";
el;
data;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
data; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
getState(el: TextHTMLElement): unknown {
throw "not implemented";
el;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
getRatePolicy(el: HTMLElement): { policy: "debounce"; delay: 250 } {
@@ -102,7 +102,7 @@ class TextInputBindingBase extends InputBinding {
policy: "debounce",
delay: 250,
};
el;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
}
@@ -126,16 +126,19 @@ class TextInputBinding extends TextInputBindingBase {
placeholder: el.placeholder,
};
}
async receiveMessage(
el: TextHTMLElement,
data: TextReceiveMessageData
data: TextReceiveMessageData,
): Promise<void> {
if (hasDefinedProperty(data, "value")) this.setValue(el, data.value);
if (hasDefinedProperty(data, "value")) this.setValue(el, data.value!);
await updateLabel(data.label, getLabelNode(el));
if (hasDefinedProperty(data, "placeholder"))
if (hasDefinedProperty(data, "placeholder")) {
// @ts-expect-error; data.value is currently a never type
el.placeholder = data.placeholder;
}
$(el).trigger("change");
}

View File

@@ -31,7 +31,7 @@ class DatatableOutputBinding extends OutputBinding {
evalOptions?: string[];
callback?: string;
searchDelay?: number;
} | null
} | null,
): void {
const $el = $(el).empty();
@@ -89,7 +89,9 @@ class DatatableOutputBinding extends OutputBinding {
url: data.action,
type: "POST",
data: function (d: NonNullable<typeof data.options>) {
d.search || (d.search = {});
if (!d.search) {
d.search = {};
}
d.search.caseInsensitive = searchCI;
// Copy from the R value (`data.escape`) to the escape option
// (`d.escape`) similar to `data.options.escape`;
@@ -100,8 +102,8 @@ class DatatableOutputBinding extends OutputBinding {
},
},
},
data.options
)
data.options,
),
);
// the table object may need post-processing
@@ -120,7 +122,7 @@ class DatatableOutputBinding extends OutputBinding {
.keyup(
debounce(data.searchDelay, function (this: HTMLInputElement) {
oTable.search(this.value).draw();
})
}),
);
const searchInputs = $el.find("tfoot input");
@@ -134,7 +136,7 @@ class DatatableOutputBinding extends OutputBinding {
searchInputs.keyup(
debounce(data.searchDelay, function (this: HTMLInputElement) {
oTable.column(searchInputs.index(this)).search(this.value).draw();
})
}),
);
}
// FIXME: ugly scrollbars in tab panels b/c Bootstrap uses 'visible: auto'

View File

@@ -16,8 +16,8 @@ class DownloadLinkOutputBinding extends OutputBinding {
// (progress will be shown as a page level pulse instead)
showProgress(el: HTMLElement, show: boolean): void {
return;
el;
show;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
show; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
}
@@ -32,14 +32,15 @@ $(document).on(
"click.shinyDownloadLink",
"a.shiny-download-link",
function (e: Event) {
e;
const evt: FileDownloadEvent = $.Event("shiny:filedownload");
evt.name = this.id;
evt.href = this.href;
$(document).trigger(evt);
}
return;
e; // eslint-disable-line @typescript-eslint/no-unused-expressions
},
);
export { DownloadLinkOutputBinding };

View File

@@ -15,7 +15,7 @@ class HtmlOutputBinding extends OutputBinding {
}
override async renderValue(
el: HTMLElement,
data: Parameters<typeof renderContentAsync>[1]
data: Parameters<typeof renderContentAsync>[1],
): Promise<void> {
await renderContentAsync(el, data);
}

View File

@@ -5,6 +5,7 @@ import {
createClickInfo,
createHoverHandler,
disableDrag,
findImageOutputs,
initCoordmap,
} from "../../imageutils";
import type { CoordmapInit } from "../../imageutils/initCoordmap";
@@ -21,7 +22,7 @@ import { OutputBinding } from "./outputBinding";
class ImageOutputBinding extends OutputBinding {
find(scope: HTMLElement): JQuery<HTMLElement> {
return $(scope).find(".shiny-image-output, .shiny-plot-output");
return findImageOutputs(scope);
}
renderValue(
@@ -29,7 +30,7 @@ class ImageOutputBinding extends OutputBinding {
data: {
coordmap: CoordmapInit;
error?: string;
} & { [key: string]: string }
} & { [key: string]: string },
): void {
// The overall strategy:
// * Clear out existing image and event handlers.
@@ -81,7 +82,7 @@ class ImageOutputBinding extends OutputBinding {
hoverDelay: ifUndefined($el.data("hover-delay"), 300),
hoverNullOutside: ifUndefined(
strToBool($el.data("hover-null-outside")),
false
false,
),
brushId: $el.data("brush-id"),
@@ -94,7 +95,7 @@ class ImageOutputBinding extends OutputBinding {
brushDirection: ifUndefined($el.data("brush-direction"), "xy"),
brushResetOnNew: ifUndefined(
strToBool($el.data("brush-reset-on-new")),
false
false,
),
coordmap: data.coordmap,
@@ -167,7 +168,7 @@ class ImageOutputBinding extends OutputBinding {
const clickInfo = createClickInfo(
$el,
opts.dblclickId,
opts.dblclickDelay
opts.dblclickDelay,
);
$el.on("mousedown.image_output", clickInfo.mousedown);
@@ -185,7 +186,7 @@ class ImageOutputBinding extends OutputBinding {
const clickHandler = createClickHandler(
opts.clickId,
opts.clickClip,
optsCoordmap
optsCoordmap,
);
$el.on("mousedown2.image_output", clickHandler.mousedown);
@@ -205,7 +206,7 @@ class ImageOutputBinding extends OutputBinding {
const dblclickHandler = createClickHandler(
opts.dblclickId,
opts.clickClip,
optsCoordmap
optsCoordmap,
);
$el.on("dblclick2.image_output", dblclickHandler.mousedown);
@@ -223,7 +224,7 @@ class ImageOutputBinding extends OutputBinding {
opts.hoverDelayType,
opts.hoverClip,
opts.hoverNullOutside,
optsCoordmap
optsCoordmap,
);
$el.on("mousemove.image_output", hoverHandler.mousemove);
@@ -241,7 +242,7 @@ class ImageOutputBinding extends OutputBinding {
$el,
opts,
optsCoordmap,
outputId
outputId,
);
$el.on("mousedown.image_output", brushHandler.mousedown);
@@ -285,12 +286,12 @@ class ImageOutputBinding extends OutputBinding {
resize(
el: HTMLElement,
width: number | string,
height: number | string
height: number | string,
): void {
$(el).find("img").trigger("resize");
return;
width;
height;
width; // eslint-disable-line @typescript-eslint/no-unused-expressions
height; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
}

View File

@@ -16,11 +16,11 @@ function initOutputBindings(): InitOutputBindings {
outputBindings.register(new TextOutputBinding(), "shiny.textOutput");
outputBindings.register(
new DownloadLinkOutputBinding(),
"shiny.downloadLink"
"shiny.downloadLink",
);
outputBindings.register(
new DatatableOutputBinding(),
"shiny.datatableOutput"
"shiny.datatableOutput",
);
outputBindings.register(new HtmlOutputBinding(), "shiny.htmlOutput");
outputBindings.register(imageOutputBinding, "shiny.imageOutput");
@@ -28,4 +28,4 @@ function initOutputBindings(): InitOutputBindings {
return { outputBindings };
}
export { OutputBinding, initOutputBindings };
export { initOutputBindings, OutputBinding };

View File

@@ -9,12 +9,12 @@ class OutputBinding {
// descendants of scope that match this binding
find(scope: HTMLElement | JQuery<HTMLElement>): JQuery<HTMLElement> {
throw "Not implemented";
scope;
scope; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
renderValue(el: HTMLElement, data: unknown): Promise<void> | void {
throw "Not implemented";
el;
data;
el; // eslint-disable-line @typescript-eslint/no-unused-expressions
data; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
getId(el: HTMLElement): string {

View File

@@ -6,7 +6,7 @@ interface OutpuBindingWithResize extends OutputBinding {
resize?: (
el: HTMLElement,
width: number | string,
height: number | string
height: number | string,
) => void;
}
@@ -22,7 +22,6 @@ class OutputBindingAdapter {
// onResize with a version that does a makeResizeFilter on the element.
if (binding.resize) {
this.onResize = makeResizeFilter(el, function (width, height) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
binding.resize!(el, width, height);
});
}

View File

@@ -1,8 +1,6 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { css, html, LitElement } from "lit";
import { Shiny } from "..";
import { ShinyClientError } from "../shiny/error";
import { isShinyInDevMode } from "../utils";
const buttonStyles = css`
button {
@@ -57,16 +55,17 @@ class ShinyErrorConsole extends LitElement {
--shadow-color: 220 3% 15%;
--shadow-strength: 1%;
--shadow-3: 0 -1px 3px 0 hsl(var(--shadow-color) /
calc(var(--shadow-strength) + 2%)),
0 1px 2px -5px hsl(var(--shadow-color) /
calc(var(--shadow-strength) + 2%)),
0 2px 5px -5px hsl(var(--shadow-color) /
calc(var(--shadow-strength) + 4%)),
0 4px 12px -5px hsl(var(--shadow-color) /
calc(var(--shadow-strength) + 5%)),
0 12px 15px -5px hsl(var(--shadow-color) /
calc(var(--shadow-strength) + 7%));
--shadow-3:
0 -1px 3px 0
hsl(var(--shadow-color) / calc(var(--shadow-strength) + 2%)),
0 1px 2px -5px
hsl(var(--shadow-color) / calc(var(--shadow-strength) + 2%)),
0 2px 5px -5px
hsl(var(--shadow-color) / calc(var(--shadow-strength) + 4%)),
0 4px 12px -5px
hsl(var(--shadow-color) / calc(var(--shadow-strength) + 5%)),
0 12px 15px -5px
hsl(var(--shadow-color) / calc(var(--shadow-strength) + 7%));
--ring-shadow: 0 0 0 1px var(--gray-2);
@@ -231,7 +230,7 @@ class ShinyErrorConsole extends LitElement {
}
this.appendChild(
ShinyErrorConsole.createClientMessageElement({ headline, message })
ShinyErrorConsole.createClientMessageElement({ headline, message }),
);
return;
}
@@ -305,10 +304,8 @@ export class ShinyErrorMessage extends LitElement {
font-size: var(--font-md);
position: relative;
--icon-size: var(--font-lg)
/* Reset box sizing */
box-sizing: border-box;
--icon-size: var(--font-lg) /* Reset box sizing */
box-sizing: border-box;
}
.container {
@@ -327,7 +324,6 @@ export class ShinyErrorMessage extends LitElement {
}
:host(:last-of-type) .contents {
padding-block-end: var(--space-1);
}
@@ -375,7 +371,7 @@ export class ShinyErrorMessage extends LitElement {
position: absolute;
width: var(--dot-size);
height: var(--dot-size);
top: calc(-1px + var(--dot-size) / 2);
top: calc(-1px + var(--dot-size) / 2);
left: calc(50% - var(--dot-size) / 2);
border-radius: 100%;
transform: scale(var(--scale, 1));
@@ -553,7 +549,7 @@ function showShinyClientMessage({
break;
}
if (!Shiny.inDevMode()) {
if (!isShinyInDevMode()) {
return;
}
@@ -606,7 +602,7 @@ window.addEventListener("shiny:client-message", (ev: Event) => {
const { headline, message, status } = ev.detail;
if (!message) {
throw new Error(
"[shiny] shiny:client-message expected a `message` property in `event.detail`."
"[shiny] shiny:client-message expected a `message` property in `event.detail`.",
);
}
showShinyClientMessage({ headline, message, status });

View File

@@ -8,7 +8,7 @@ function triggerFileInputChanged(
binding: FileInputBinding,
el: HTMLElement,
inputType: string,
onEl: typeof document
onEl: typeof document,
): ShinyEventInputChanged {
const evt = $.Event("shiny:inputchanged") as ShinyEventInputChanged;

View File

@@ -1,5 +1,4 @@
// Used to avoid isolated module warning
import type { JQueryEventHandlerBase } from "bootstrap";
import "jquery";
type EvtPrefix<T extends string> = `${T}.${string}`;
@@ -11,32 +10,32 @@ declare global {
on(
events: EvtPrefix<"mousdown">,
handler: EvtFn<JQuery.MouseDownEvent>
handler: EvtFn<JQuery.MouseDownEvent>,
): this;
on(
events: EvtPrefix<"dblclick">,
handler: EvtFn<JQuery.DoubleClickEvent>
handler: EvtFn<JQuery.DoubleClickEvent>,
): this;
on(
events: EvtPrefix<"dblclick2">,
// Note: This may not be the _right type_, but it is how it is handled internally
handler: EvtFn<JQuery.MouseDownEvent>
handler: EvtFn<JQuery.MouseDownEvent>,
): this;
on(
events: EvtPrefix<"mousemove">,
handler: EvtFn<JQuery.MouseMoveEvent>
handler: EvtFn<JQuery.MouseMoveEvent>,
): this;
on(
events: EvtPrefix<"mouseout">,
handler: EvtFn<JQuery.MouseOutEvent>
handler: EvtFn<JQuery.MouseOutEvent>,
): this;
on(
events: EvtPrefix<"mousedown">,
handler: EvtFn<JQuery.MouseDownEvent>
handler: EvtFn<JQuery.MouseDownEvent>,
): this;
on(
events: EvtPrefix<"mousedown2">,
handler: EvtFn<JQuery.MouseDownEvent>
handler: EvtFn<JQuery.MouseDownEvent>,
): this;
on(events: EvtPrefix<"mouseup">, handler: EvtFn<JQuery.MouseUpEvent>): this;
on(events: EvtPrefix<"resize">, handler: EvtFn<JQuery.ResizeEvent>): this;
@@ -46,11 +45,11 @@ declare global {
selector: string,
handler: (
this: HTMLElement,
e: JQueryEventHandlerBase<HTMLElement, any>
e: JQuery.EventHandlerBase<HTMLElement, any>,
// e: JQuery.Event & {
// namespace: string;
// }
) => void
) => void,
): this;
}
}

View File

@@ -32,9 +32,9 @@ interface ShinyEventMessage extends JQuery.Event {
}
export type {
ShinyEventError,
ShinyEventInputChanged,
ShinyEventMessage,
ShinyEventUpdateInput,
ShinyEventValue,
ShinyEventError,
ShinyEventMessage,
};

View File

@@ -31,12 +31,14 @@ class FileProcessor {
// Begin callbacks. Subclassers/cloners may override any or all of these.
onBegin(files: File[], cont: () => void): void {
files;
setTimeout(cont, 0);
return;
files; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
onFile(file: File, cont: () => void): void {
file;
setTimeout(cont, 0);
return;
file; // eslint-disable-line @typescript-eslint/no-unused-expressions
}
onComplete(): void {
return;
@@ -108,7 +110,7 @@ class FileUploader extends FileProcessor {
shinyapp: ShinyApp,
id: string,
files: FileList,
el: HTMLElement
el: HTMLElement,
) {
// Init super with files, do not execute `this.$run()` before setting variables
super(files, false);
@@ -123,7 +125,7 @@ class FileUploader extends FileProcessor {
args: Array<Array<{ name: string; size: number; type: string }>>,
onSuccess: (value: UploadInitValue) => void,
onFailure: Parameters<ShinyApp["makeRequest"]>[3],
blobs: Parameters<ShinyApp["makeRequest"]>[4]
blobs: Parameters<ShinyApp["makeRequest"]>[4],
): void;
makeRequest(
method: "uploadEnd",
@@ -131,14 +133,14 @@ class FileUploader extends FileProcessor {
// UploadEndValue can not be used as the type will not conform
onSuccess: (value: unknown) => void,
onFailure: Parameters<ShinyApp["makeRequest"]>[3],
blobs: Parameters<ShinyApp["makeRequest"]>[4]
blobs: Parameters<ShinyApp["makeRequest"]>[4],
): void;
makeRequest(
method: string,
args: unknown[],
onSuccess: Parameters<ShinyApp["makeRequest"]>[2],
onFailure: Parameters<ShinyApp["makeRequest"]>[3],
blobs: Parameters<ShinyApp["makeRequest"]>[4]
blobs: Parameters<ShinyApp["makeRequest"]>[4],
): void {
this.shinyapp.makeRequest(method, args, onSuccess, onFailure, blobs);
}
@@ -174,13 +176,12 @@ class FileUploader extends FileProcessor {
(error) => {
this.onError(error);
},
undefined
undefined,
);
}
onFile(file: File, cont: () => void): void {
this.onProgress(file, 0);
/* eslint-disable-next-line @typescript-eslint/no-floating-promises */
$.ajax(this.uploadUrl, {
type: "POST",
cache: false,
@@ -195,7 +196,7 @@ class FileUploader extends FileProcessor {
if (e.lengthComputable) {
this.onProgress(
file,
(this.progressBytes + e.loaded) / this.totalBytes
(this.progressBytes + e.loaded) / this.totalBytes,
);
}
};
@@ -210,8 +211,9 @@ class FileUploader extends FileProcessor {
cont();
},
error: (jqXHR, textStatus, errorThrown) => {
errorThrown;
this.onError(jqXHR.responseText || textStatus);
return;
errorThrown; // eslint-disable-line @typescript-eslint/no-unused-expressions
},
});
}
@@ -222,7 +224,7 @@ class FileUploader extends FileProcessor {
size: file.size,
type: file.type,
};
i;
i; // eslint-disable-line @typescript-eslint/no-unused-expressions
});
// Trigger shiny:inputchanged. Unlike a normal shiny:inputchanged event,
@@ -234,7 +236,7 @@ class FileUploader extends FileProcessor {
getFileInputBinding(),
this.el,
"shiny.fileupload",
document
document,
);
this.makeRequest(
@@ -251,7 +253,7 @@ class FileUploader extends FileProcessor {
(error) => {
this.onError(error);
},
undefined
undefined,
);
this.$bar().text("Finishing upload");
}
@@ -273,7 +275,7 @@ class FileUploader extends FileProcessor {
return $(
"#" +
$escape(this.id) +
"_progress.shiny-file-input-progress .progress-bar"
"_progress.shiny-file-input-progress .progress-bar",
);
}
$setVisible(visible: boolean): void {
@@ -292,4 +294,4 @@ class FileUploader extends FileProcessor {
}
export { FileUploader };
export type { UploadInitValue, UploadEndValue };
export type { UploadEndValue, UploadInitValue };

View File

@@ -109,7 +109,7 @@ function createBrush(
$el: JQuery<HTMLElement>,
opts: BrushOpts,
coordmap: Coordmap,
expandPixels: number
expandPixels: number,
): Brush {
// Number of pixels outside of brush to allow start resizing
const resizeExpand = 10;
@@ -306,7 +306,6 @@ function createBrush(
let minCss: Offset = { x: boxCss.xmin, y: boxCss.ymin };
let maxCss: Offset = { x: boxCss.xmax, y: boxCss.ymax };
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const panel = state.panel!;
const panelBoundsImg = panel.range;
@@ -343,15 +342,15 @@ function createBrush(
// Round to 14 significant digits to avoid spurious changes in FP values
// (#1634).
state.boundsData = mapValues(state.boundsData, (val) =>
roundSignif(val, 14)
roundSignif(val, 14),
);
// We also need to attach the data bounds and panel as data attributes, so
// that if the image is re-sent, we can grab the data bounds to create a new
// brush. This should be fast because it doesn't actually modify the DOM.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
$div!.data("bounds-data", state.boundsData);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
$div!.data("panel", state.panel);
return undefined;
}
@@ -364,7 +363,6 @@ function createBrush(
return { ...state.boundsData };
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
let boxCss = imgToCss(state.panel!.scaleDataToImg(boxData));
// Round to 13 significant digits to avoid spurious changes in FP values
// (#2197).
@@ -424,7 +422,7 @@ function createBrush(
$div
.offset(
// @ts-expect-error; This is a jQuery Typing issue
{ x: 0, y: 0 }
{ x: 0, y: 0 },
)
.width(0)
.outerHeight(0);
@@ -437,7 +435,6 @@ function createBrush(
const imgOffsetCss = findOrigin($el.find("img"));
const b = state.boundsCss;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
$div!
.offset({
top: imgOffsetCss.y + b.ymin,
@@ -480,7 +477,7 @@ function createBrush(
function brushTo(offsetCss: Offset) {
boundsCss(findBox(state.down, offsetCss));
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
$div!.show();
updateDiv();
}
@@ -527,12 +524,12 @@ function createBrush(
xvalsImg = shiftToRange(
xvalsImg,
panelBoundsImg.left,
panelBoundsImg.right
panelBoundsImg.right,
);
yvalsImg = shiftToRange(
yvalsImg,
panelBoundsImg.top,
panelBoundsImg.bottom
panelBoundsImg.bottom,
);
// Convert back to bounds format
@@ -580,7 +577,7 @@ function createBrush(
const xminImg = shiftToRange(
bImg.xmin + dImg.x,
panelBoundsImg.left,
bImg.xmax
bImg.xmax,
)[0];
bImg.xmin = xminImg;
@@ -588,7 +585,7 @@ function createBrush(
const xmaxImg = shiftToRange(
bImg.xmax + dImg.x,
bImg.xmin,
panelBoundsImg.right
panelBoundsImg.right,
)[0];
bImg.xmax = xmaxImg;
@@ -598,7 +595,7 @@ function createBrush(
const yminImg = shiftToRange(
bImg.ymin + dImg.y,
panelBoundsImg.top,
bImg.ymax
bImg.ymax,
)[0];
bImg.ymin = yminImg;
@@ -606,7 +603,7 @@ function createBrush(
const ymaxImg = shiftToRange(
bImg.ymax + dImg.y,
bImg.ymin,
panelBoundsImg.bottom
panelBoundsImg.bottom,
)[0];
bImg.ymax = ymaxImg;
@@ -656,4 +653,4 @@ function createBrush(
}
export { createBrush };
export type { Bounds, BrushOpts, BoundsCss };
export type { Bounds, BoundsCss, BrushOpts };

View File

@@ -9,7 +9,7 @@ import $ from "jquery";
function createClickInfo(
$el: JQuery<HTMLElement>,
dblclickId: string,
dblclickDelay: number
dblclickDelay: number,
): {
mousedown: (e: JQuery.MouseDownEvent) => void;
dblclickIE8: (e: JQuery.DoubleClickEvent) => void;
@@ -21,7 +21,7 @@ function createClickInfo(
// it with the information stored in this.e.
function triggerEvent(
newEventType: string,
e: JQuery.DoubleClickEvent | JQuery.MouseDownEvent
e: JQuery.DoubleClickEvent | JQuery.MouseDownEvent,
) {
// Extract important info from e and construct a new event with type
// eventType.

View File

@@ -1,11 +1,11 @@
import $ from "jquery";
import { imageOutputBinding } from "../bindings/output/image";
import type { InputRatePolicy } from "../inputPolicies";
import { shinySetInputValue } from "../shiny/initedMethods";
import { Debouncer, Throttler } from "../time";
import type { Bounds, BoundsCss, BrushOpts } from "./createBrush";
import { createBrush } from "./createBrush";
import type { Offset } from "./findbox";
import { findImageOutputs } from "./imageBindingUtils";
import type { Coordmap } from "./initCoordmap";
import type { Panel } from "./initPanelScales";
@@ -53,7 +53,7 @@ type NullOutside = Parameters<Coordmap["mouseCoordinateSender"]>[2];
function createClickHandler(
inputId: InputId,
clip: Clip,
coordmap: Coordmap
coordmap: Coordmap,
): CreateHandler {
const clickInfoSender = coordmap.mouseCoordinateSender(inputId, clip);
@@ -79,12 +79,12 @@ function createHoverHandler(
delayType: string | "throttle",
clip: Clip,
nullOutside: NullOutside,
coordmap: Coordmap
coordmap: Coordmap,
): CreateHandler {
const sendHoverInfo = coordmap.mouseCoordinateSender(
inputId,
clip,
nullOutside
nullOutside,
);
let hoverInfoSender: InputRatePolicy<typeof sendHoverInfo>;
@@ -127,7 +127,7 @@ function createBrushHandler(
$el: JQuery<HTMLElement>,
opts: BrushOpts,
coordmap: Coordmap,
outputId: BrushInfo["outputId"]
outputId: BrushInfo["outputId"],
): CreateHandler {
// Parameter: expand the area in which a brush can be started, by this
// many pixels in all directions. (This should probably be a brush option)
@@ -168,10 +168,10 @@ function createBrushHandler(
| "nesw-resize"
| "ns-resize"
| "nwse-resize"
| null
| null,
) {
$el.removeClass(
"crosshair grabbable grabbing ns-resize ew-resize nesw-resize nwse-resize"
"crosshair grabbable grabbing ns-resize ew-resize nesw-resize nwse-resize",
);
if (style) $el.addClass(style);
@@ -184,27 +184,25 @@ function createBrushHandler(
if (isNaN(coords.xmin)) {
shinySetInputValue(inputId, null);
// Must tell other brushes to clear.
imageOutputBinding
.find(document.documentElement)
.trigger("shiny-internal:brushed", {
findImageOutputs(document.documentElement).trigger(
"shiny-internal:brushed",
{
brushId: inputId,
outputId: null,
});
},
);
return;
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const panel = brush.getPanel()!;
// Add the panel (facet) variables, if present
$.extend(coords, panel.panel_vars);
// eslint-disable-next-line camelcase
coords.coords_css = brush.boundsCss();
// eslint-disable-next-line camelcase
coords.coords_img = coordmap.scaleCssToImg(coords.coords_css);
// eslint-disable-next-line camelcase
coords.img_css_ratio = coordmap.cssToImgScalingRatio();
// Add variable name mappings
@@ -224,9 +222,10 @@ function createBrushHandler(
shinySetInputValue(inputId, coords);
$el.data("mostRecentBrush", true);
imageOutputBinding
.find(document.documentElement)
.trigger("shiny-internal:brushed", coords);
findImageOutputs(document.documentElement).trigger(
"shiny-internal:brushed",
coords,
);
}
let brushInfoSender:
@@ -265,7 +264,6 @@ function createBrushHandler(
brush.down(offsetCss);
if (brush.isInResizeArea(offsetCss)) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error; TODO-barret; Remove the variable? it is not used
brush.startResizing(offsetCss);
@@ -439,5 +437,5 @@ function createBrushHandler(
};
}
export { createClickHandler, createHoverHandler, createBrushHandler };
export { createBrushHandler, createClickHandler, createHoverHandler };
export type { BrushInfo };

View File

@@ -1,6 +1,6 @@
function disableDrag(
$el: JQuery<HTMLElement>,
$img: JQuery<HTMLElement>
$img: JQuery<HTMLElement>,
): void {
// Make image non-draggable (Chrome, Safari)
$img.css("-webkit-user-drag", "none");

View File

@@ -18,5 +18,5 @@ function findBox(offset1: Offset, offset2: Offset): Bounds {
};
}
export type { Offset };
export { findBox };
export type { Offset };

View File

@@ -0,0 +1,7 @@
import $ from "jquery";
export function findImageOutputs(
scope: HTMLElement = document.documentElement,
): JQuery<HTMLElement> {
return $(scope).find(".shiny-image-output, .shiny-plot-output");
}

View File

@@ -7,19 +7,21 @@ import {
} from "./createHandlers";
import { disableDrag } from "./disableDrag";
import { findBox } from "./findbox";
import { findImageOutputs } from "./imageBindingUtils";
import { initCoordmap } from "./initCoordmap";
import { initPanelScales } from "./initPanelScales";
import { shiftToRange } from "./shiftToRange";
export {
disableDrag,
initPanelScales,
initCoordmap,
findBox,
shiftToRange,
createClickInfo,
createClickHandler,
createHoverHandler,
createBrushHandler,
createBrush,
createBrushHandler,
createClickHandler,
createClickInfo,
createHoverHandler,
disableDrag,
findBox,
findImageOutputs,
initCoordmap,
initPanelScales,
shiftToRange,
};

View File

@@ -16,15 +16,13 @@ function findScalingRatio($el: JQuery<HTMLElement>) {
const boundingRect = $el[0].getBoundingClientRect();
return {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
x: boundingRect.width / $el.outerWidth()!,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
y: boundingRect.height / $el.outerHeight()!,
};
}
function findOrigin($el: JQuery<HTMLElement>): Offset {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const offset = $el.offset()!;
const scalingRatio = findScalingRatio($el);
@@ -53,9 +51,8 @@ function findDims($el: JQuery<HTMLElement>) {
// If there's any padding/border, we need to find the ratio of the actual
// element content compared to the element plus padding and border.
const contentRatio = {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
x: $el.width()! / $el.outerWidth()!,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
y: $el.height()! / $el.outerHeight()!,
};
@@ -125,7 +122,7 @@ type Coordmap = {
mouseCoordinateSender: (
inputId: string,
clip?: boolean,
nullOutside?: boolean
nullOutside?: boolean,
) => (e: JQuery.MouseDownEvent | JQuery.MouseMoveEvent | null) => void;
};
@@ -150,7 +147,7 @@ type Coordmap = {
// than the other two, because there can be multiple panels (as in facets).
function initCoordmap(
$el: JQuery<HTMLElement>,
coordmap_: CoordmapInit
coordmap_: CoordmapInit,
): Coordmap {
const $img = $el.find("img");
const img = $img[0];
@@ -350,7 +347,7 @@ function initCoordmap(
coordmap.mouseCoordinateSender = function (
inputId,
clip = true,
nullOutside = false
nullOutside = false,
) {
return function (e) {
if (e === null) {
@@ -377,7 +374,7 @@ function initCoordmap(
shinySetInputValue(inputId, coords, { priority: "event" });
return;
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const panel = coordmap.getPanelCss(coordsCss)!;
const coordsImg = coordmap.scaleCssToImg(coordsCss);

View File

@@ -11,7 +11,7 @@ function mapLinear(
domainMax: number,
rangeMin: number,
rangeMax: number,
clip = true
clip = true,
) {
// By default, clip to range
clip = clip || true;
@@ -36,7 +36,7 @@ function scaler1D(
domainMax: number,
rangeMin: number,
rangeMax: number,
logbase: number | null
logbase: number | null,
) {
return {
scale: function (val: number, clip?: boolean) {
@@ -107,7 +107,7 @@ function addScaleFuns(panel_: PanelInit): Panel {
// };
function scaleDataToImg(
val: Bounds,
clip?: Parameters<typeof xscaler.scale>[1]
clip?: Parameters<typeof xscaler.scale>[1],
): Bounds {
return mapValues(val, (value, key) => {
const prefix = key.substring(0, 1);
@@ -168,5 +168,5 @@ function initPanelScales(panels: PanelInit[]): Panel[] {
return panels.map((panel) => addScaleFuns(panel));
}
export type { Panel, PanelInit };
export { initPanelScales };
export type { Panel, PanelInit };

View File

@@ -5,7 +5,7 @@
function shiftToRange(
vals: number[] | number,
min: number,
max: number
max: number,
): number[] {
if (!(vals instanceof Array)) vals = [vals];

Some files were not shown because too many files have changed in this diff Show More