1#' Global theming
2#'
3#' `bs_global_theme()` creates a new (global) Bootstrap Sass theme which
4#' [bs_theme_dependencies()] (or [sass_partial()]) can consume (their `theme`
5#' argument defaults to `bs_global_get()`, which get the current global theme).
6#'
7#' @inheritParams bs_theme
8#'
9#' @return functions that modify the global theme (e.g., `bs_global_set()`)
10#'   invisibly return the previously set theme. `bs_global_get()` returns the
11#'   current global theme.
12#'
13#' @seealso [bs_theme()], [bs_theme_preview()]
14#' @examples
15#'
16#' # Remember the global state now (so we can restore later)
17#' theme <- bs_global_get()
18#' # Use Bootstrap 3 (globally) with some theme customization
19#' bs_global_theme(3, bg = "#444", fg = "#e4e4e4", primary = "#e39777")
20#' if (interactive()) bs_theme_preview(with_themer = FALSE)
21#' # If no global theme is active, bs_global_get() returns NULL
22#' bs_global_clear()
23#' bs_global_get()
24#' # Restore the original state
25#' bs_global_set(theme)
26#'
27#' @export
28bs_global_theme <- function(version = version_default(), bootswatch = NULL, bg = NULL, fg = NULL,
29                            primary = NULL, secondary = NULL, success = NULL, info = NULL, warning = NULL,
30                            danger = NULL, base_font = NULL, code_font = NULL, heading_font = NULL, ...) {
31  bs_global_set(bs_theme(
32    version, bootswatch,
33    bg = bg, fg = fg,
34    primary = primary,
35    secondary = secondary,
36    success = success,
37    info = info,
38    warning = warning,
39    danger = danger,
40    base_font = base_font,
41    code_font = code_font,
42    heading_font = heading_font,
43    ...
44  ))
45}
46
47
48#' @rdname bs_global_theme
49#' @inheritParams bs_theme_update
50#' @export
51bs_global_set <- function(theme = bs_theme()) {
52  if (!is.null(theme)) {
53    assert_bs_theme(theme)
54  }
55  # In addition to setting a bslib global option, also set shiny's
56  # current theme if this code is running in an `runtime: shiny` doc
57  if (is_shiny_runtime() && is_available("shiny", "1.6")) {
58    warning(
59      "bs_global_set() may not work as expected inside runtime: shiny documents. ",
60      "To update the document's theme, use `session$setCurrentTheme()` instead.",
61      call. = FALSE
62    )
63  }
64  old_theme <- options(bslib_theme = theme)
65  invisible(old_theme[["bslib_theme"]])
66}
67
68#' @rdname bs_global_theme
69#' @export
70bs_global_get <- function() {
71  getOption("bslib_theme")
72}
73
74#' @rdname bs_global_theme
75#' @export
76bs_global_clear <- function() {
77  old_theme <- options(bslib_theme = NULL)
78  invisible(old_theme[["bslib_theme"]])
79}
80
81#' @rdname bs_global_theme
82#' @inheritParams bs_add_variables
83#' @export
84bs_global_add_variables <- function(..., .where = "defaults",
85                                    .default_flag = identical(.where, "defaults")) {
86  theme <- assert_global_theme("bs_global_add_variables()")
87  theme <- bs_add_variables(theme, ..., .where = .where, .default_flag = .default_flag)
88  bs_global_set(theme)
89}
90
91#' @rdname bs_global_theme
92#' @export
93bs_global_add_rules <- function(...) {
94  theme <- assert_global_theme("bs_global_add_rules()")
95  theme <- bs_add_rules(theme, ...)
96  bs_global_set(theme)
97}
98
99#' @rdname bs_global_theme
100#' @export
101bs_global_bundle <- function(...) {
102  theme <- assert_global_theme("bs_global_bundle()")
103  theme <- bs_bundle(theme, ...)
104  bs_global_set(theme)
105}
106
107
108
109
110assert_global_theme <- function(calling_func) {
111  theme <- bs_global_get()
112  if (is.null(theme)) {
113    stop("`", calling_func, "` requires that a global theme is first set (do you want to call `bs_global_theme()`?)")
114  }
115  theme
116}
117