├── .Rbuildignore
├── .github
├── .gitignore
└── workflows
│ └── check-standard.yaml
├── .gitignore
├── DESCRIPTION
├── LICENSE
├── LICENSE.md
├── NAMESPACE
├── NEWS.md
├── R
├── add_alternate_layout.R
├── array_table_to_matrix.R
├── bootstrap-background-colors.R
├── check_for_area_mismatches.R
├── get_elements.R
├── get_info.R
├── grid_card.R
├── grid_card_old.R
├── grid_card_text.R
├── grid_container.R
├── grid_nested.R
├── grid_page.R
├── grid_place.R
├── grid_plot.R
├── gridlayout-package.R
├── helper-demo-apps.R
├── md_table_to_matrix.R
├── md_to_gridlayout.R
├── new_gridlayout.R
├── parse_layout_matrix.R
├── parsing-utils.R
├── tag-utils.R
├── to_css.R
├── to_md.R
├── use_gridlayout_rmd.R
├── use_gridlayout_shiny.R
├── utils-pipe.R
└── utils.R
├── README.Rmd
├── README.md
├── _pkgdown.yml
├── docs
├── 404.html
├── LICENSE-text.html
├── LICENSE.html
├── ace-1.2.3
│ ├── ace.js
│ ├── mode-css.js
│ ├── mode-html.js
│ ├── mode-javascript.js
│ ├── mode-markdown.js
│ ├── mode-plain_text.js
│ ├── mode-r.js
│ ├── mode-rdoc.js
│ ├── mode-rhtml.js
│ ├── mode-text.js
│ ├── mode-xml.js
│ └── theme-textmate.js
├── articles
│ ├── alternate-layouts.html
│ ├── alternate-layouts_files
│ │ └── header-attrs-2.7.1
│ │ │ └── header-attrs.js
│ ├── alternate-layouts_resizing.gif
│ ├── alternate-layouts_w1000_h1000.png
│ ├── alternate-layouts_w2000_h1000.png
│ ├── alternate-layouts_w500_h1000.png
│ ├── defining-a-layout.html
│ ├── index.html
│ ├── layout-examples.html
│ ├── layout-examples_files
│ │ └── header-attrs-2.7.1
│ │ │ └── header-attrs.js
│ ├── layout-examples_focal_chart_side.png
│ ├── layout-examples_focal_chart_top.png
│ ├── layout-examples_four_panel.png
│ ├── layout-examples_scrolling_stack.png
│ ├── layout-examples_stack.png
│ ├── use_gridlayout_rmd.png
│ ├── use_gridlayout_rmd_base.png
│ ├── use_gridlayout_rmd_extra_child_styles.png
│ ├── use_gridlayout_rmd_only_grid_panel.png
│ ├── using_with_rmd.html
│ └── using_with_rmd_files
│ │ └── header-attrs-2.7.1
│ │ └── header-attrs.js
├── authors.html
├── bootstrap-toc.css
├── bootstrap-toc.js
├── docsearch.css
├── docsearch.js
├── holder-2.9.0
│ └── holder.min.js
├── index.html
├── link.svg
├── news
│ └── index.html
├── pkgdown.css
├── pkgdown.js
├── pkgdown.yml
├── reference
│ ├── Rplot001.png
│ ├── add_alternate_layout.gridlayout.html
│ ├── add_alternate_layout.html
│ ├── build_css_rule.html
│ ├── card_plot_output.html
│ ├── figures
│ │ ├── basic_markdown.png
│ │ ├── geyser_demo.png
│ │ ├── geyser_w_grided.png
│ │ ├── grided_default.png
│ │ ├── lifecycle-archived.svg
│ │ ├── lifecycle-defunct.svg
│ │ ├── lifecycle-deprecated.svg
│ │ ├── lifecycle-experimental.svg
│ │ ├── lifecycle-maturing.svg
│ │ ├── lifecycle-questioning.svg
│ │ ├── lifecycle-stable.svg
│ │ ├── lifecycle-superseded.svg
│ │ └── nested_demo.png
│ ├── flex_stack.html
│ ├── get_element_ids.html
│ ├── get_elements.html
│ ├── grid_card.html
│ ├── grid_card_old.html
│ ├── grid_card_plot.html
│ ├── grid_card_text.html
│ ├── grid_container.html
│ ├── grid_nested.html
│ ├── grid_page.html
│ ├── grid_panel.html
│ ├── grid_panel_nested.html
│ ├── grid_panel_plot.html
│ ├── grid_panel_stack.html
│ ├── grid_panel_text.html
│ ├── grid_place.html
│ ├── grid_plot.html
│ ├── grided_create_new_app.html
│ ├── grided_edit_existing_layout.html
│ ├── gridlayout-package.html
│ ├── index.html
│ ├── make_bg_class.html
│ ├── md_to_gridlayout.html
│ ├── nested_grid_panel.html
│ ├── new_gridlayout.html
│ ├── pipe.html
│ ├── run_with_grided.html
│ ├── text_panel.html
│ ├── title_panel.html
│ ├── to_app_template.html
│ ├── to_css.html
│ ├── to_matrix.html
│ ├── to_md.html
│ ├── use_gridlayout_rmd.html
│ ├── use_gridlayout_shiny.html
│ └── vertical_stack_panel.html
├── rmarkdown.png
├── rmd.css
├── sitemap.xml
├── snippets
│ └── snippets.js
├── tidyverse-2.css
└── tidyverse.css
├── gridlayout.Rproj
├── inst
├── demo_apps
│ ├── alternate_layouts
│ │ ├── README.md
│ │ ├── app.R
│ │ └── tests
│ │ │ ├── testthat.R
│ │ │ └── testthat
│ │ │ ├── _snaps
│ │ │ ├── mac-4.1
│ │ │ │ └── shinytest2
│ │ │ │ │ ├── alternate_layouts-001.png
│ │ │ │ │ ├── alternate_layouts-002.png
│ │ │ │ │ └── alternate_layouts-003.png
│ │ │ └── mac-4.2
│ │ │ │ └── shinytest2
│ │ │ │ ├── alternate_layouts-001.png
│ │ │ │ ├── alternate_layouts-002.png
│ │ │ │ └── alternate_layouts-003.png
│ │ │ ├── setup.R
│ │ │ └── test-shinytest2.R
│ ├── geyser
│ │ ├── README.md
│ │ └── app.R
│ ├── nested_grids
│ │ ├── README.md
│ │ ├── app.R
│ │ └── tests
│ │ │ ├── testthat.R
│ │ │ └── testthat
│ │ │ ├── _snaps
│ │ │ ├── mac-4.1
│ │ │ │ └── shinytest2
│ │ │ │ │ └── nested_grids-001.png
│ │ │ └── mac-4.2
│ │ │ │ └── shinytest2
│ │ │ │ └── nested_grids-001.png
│ │ │ ├── setup.R
│ │ │ └── test-shinytest2.R
│ ├── recursive_nesting
│ │ ├── app.R
│ │ └── tests
│ │ │ ├── testthat.R
│ │ │ └── testthat
│ │ │ ├── _snaps
│ │ │ ├── mac-4.1
│ │ │ │ └── shinytest2
│ │ │ │ │ └── recursive_nesting-001.png
│ │ │ └── mac-4.2
│ │ │ │ └── shinytest2
│ │ │ │ └── recursive_nesting-001.png
│ │ │ ├── setup.R
│ │ │ └── test-shinytest2.R
│ ├── rmarkdown_demo
│ │ ├── README.md
│ │ ├── grid_markdown.Rmd
│ │ ├── grid_markdown_options.Rmd
│ │ └── grid_markdown_options.html
│ ├── setupScreenshots.R
│ ├── simple
│ │ ├── README.md
│ │ └── app.R
│ └── tabset
│ │ └── app.R
└── resources
│ ├── gridlayout.css
│ ├── gridlayout.js
│ └── gridlayout_rmd_styles.css
├── man
├── add_alternate_layout.Rd
├── build_css_rule.Rd
├── card_plot_output.Rd
├── examples
│ ├── grid_place_app.R
│ ├── nested_app.R
│ ├── simple_app.R
│ └── simple_app_old.R
├── figures
│ ├── basic_markdown.png
│ ├── geyser_demo.png
│ ├── geyser_w_grided.png
│ ├── grided_default.png
│ ├── lifecycle-archived.svg
│ ├── lifecycle-defunct.svg
│ ├── lifecycle-deprecated.svg
│ ├── lifecycle-experimental.svg
│ ├── lifecycle-maturing.svg
│ ├── lifecycle-questioning.svg
│ ├── lifecycle-stable.svg
│ ├── lifecycle-superseded.svg
│ └── nested_demo.png
├── flex_stack.Rd
├── get_element_ids.Rd
├── get_elements.Rd
├── grid_card.Rd
├── grid_card_old.Rd
├── grid_card_plot.Rd
├── grid_card_text.Rd
├── grid_container.Rd
├── grid_nested.Rd
├── grid_page.Rd
├── grid_place.Rd
├── gridlayout-package.Rd
├── make_bg_class.Rd
├── md_to_gridlayout.Rd
├── new_gridlayout.Rd
├── pipe.Rd
├── to_css.Rd
├── to_matrix.Rd
├── to_md.Rd
├── use_gridlayout_rmd.Rd
└── use_gridlayout_shiny.Rd
├── tests
├── testthat.R
└── testthat
│ ├── _snaps
│ ├── grid_page.md
│ ├── markdown-layout-parsing.md
│ ├── nested-grids.md
│ ├── new_gridlayout.md
│ └── to_css.md
│ ├── test-alternate_layouts.R
│ ├── test-array_table_to_matrix.R
│ ├── test-demo-apps.R
│ ├── test-grid_container.R
│ ├── test-grid_page.R
│ ├── test-markdown-layout-parsing.R
│ ├── test-md_table_to_matrix.R
│ ├── test-nested-grids.R
│ ├── test-new_gridlayout.R
│ ├── test-parse_layout_matrix.R
│ ├── test-to_css.R
│ └── test-to_md.R
└── vignettes
├── .gitignore
├── alternate-layouts.Rmd
├── alternate-layouts_resizing.gif
├── alternate-layouts_w1000_h1000.png
├── alternate-layouts_w2000_h1000.png
├── alternate-layouts_w500_h1000.png
├── defining-a-layout.Rmd
├── layout-examples.Rmd
├── layout-examples_focal_chart_side.png
├── layout-examples_focal_chart_top.png
├── layout-examples_four_panel.png
├── layout-examples_scrolling_stack.png
├── layout-examples_stack.png
├── use_gridlayout_rmd.png
├── use_gridlayout_rmd_base.png
├── use_gridlayout_rmd_extra_child_styles.png
├── use_gridlayout_rmd_only_grid_panel.png
└── using_with_rmd.Rmd
/.Rbuildignore:
--------------------------------------------------------------------------------
1 | ^.*\.Rproj$
2 | ^\.Rproj\.user$
3 | ^README\.Rmd$
4 | ^_pkgdown\.yml$
5 | ^docs$
6 | ^pkgdown$
7 | ^LICENSE\.md$
8 | ^inst/grided/www/rmd_layout_editing_files$
9 | ^tests/run-screenshot-tests\.R$
10 | ^tests/screenshot-tests$
11 | ^inst/grided/www/\.cache$
12 | ^inst/grided/www/node_modules$
13 | ^inst/demo_apps/.*.html
14 | ^inst/demo_apps/.*_files$
15 | ^doc$
16 | ^Meta$
17 | ^\.github$
18 | ^data-raw$
19 | ^inst\/demo_apps\/\w+\/tests/testthat/_snaps
20 |
--------------------------------------------------------------------------------
/.github/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 |
--------------------------------------------------------------------------------
/.github/workflows/check-standard.yaml:
--------------------------------------------------------------------------------
1 | # For help debugging build failures open an issue on the RStudio community with the 'github-actions' tag.
2 | # https://community.rstudio.com/new-topic?category=Package%20development&tags=github-actions
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | branches:
9 | - main
10 |
11 | name: R-CMD-check
12 |
13 | jobs:
14 | website:
15 | uses: rstudio/shiny-workflows/.github/workflows/website.yaml@v1
16 | R-CMD-check:
17 | runs-on: ${{ matrix.config.os }}
18 |
19 | name: ${{ matrix.config.os }} (${{ matrix.config.r }})
20 |
21 | strategy:
22 | fail-fast: false
23 | matrix:
24 | config:
25 | - {os: windows-latest, r: 'release'}
26 | - {os: macOS-latest, r: 'release'}
27 | - {os: ubuntu-20.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
28 | - {os: ubuntu-20.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
29 |
30 | env:
31 | R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
32 | RSPM: ${{ matrix.config.rspm }}
33 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
34 |
35 | steps:
36 | - uses: actions/checkout@v2
37 |
38 | - uses: r-lib/actions/setup-r@v1
39 | with:
40 | r-version: ${{ matrix.config.r }}
41 |
42 | - uses: r-lib/actions/setup-pandoc@v1
43 |
44 | - name: Query dependencies
45 | run: |
46 | install.packages('remotes')
47 | saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2)
48 | writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version")
49 | shell: Rscript {0}
50 |
51 | - name: Restore R package cache
52 | if: runner.os != 'Windows'
53 | uses: actions/cache@v2
54 | with:
55 | path: ${{ env.R_LIBS_USER }}
56 | key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }}
57 | restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-
58 |
59 | - name: Install system dependencies
60 | if: runner.os == 'Linux'
61 | run: |
62 | while read -r cmd
63 | do
64 | eval sudo $cmd
65 | done < <(Rscript -e 'writeLines(remotes::system_requirements("ubuntu", "20.04"))')
66 |
67 | - name: Install dependencies
68 | run: |
69 | remotes::install_deps(dependencies = TRUE)
70 | remotes::install_cran("rcmdcheck")
71 | shell: Rscript {0}
72 |
73 | - name: Check
74 | env:
75 | _R_CHECK_CRAN_INCOMING_REMOTE_: false
76 | run: |
77 | options(crayon.enabled = TRUE)
78 | rcmdcheck::rcmdcheck(args = c("--no-manual", "--as-cran"), error_on = "warning", check_dir = "check")
79 | shell: Rscript {0}
80 |
81 | - name: Upload check results
82 | if: failure()
83 | uses: actions/upload-artifact@main
84 | with:
85 | name: ${{ runner.os }}-r${{ matrix.config.r }}-results
86 | path: check
87 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .Rproj.user
2 | .Rhistory
3 | .RData
4 | .Ruserdata
5 |
6 | */.DS_Store
7 | .DS_Store
8 |
9 | inst/griditor/www/.cache/
10 | inst/grided/www/.cache/
11 |
12 | # Ignore all the stuff in the dist folder
13 | inst/grided/dist/*
14 | inst/grided/www/dist/*
15 | # Except index.js becuse that's the bundled js we actually want
16 | !inst/grided/dist/index.js
17 |
18 | inst/rmarkdown_demo/grid_markdown.html
19 | inst/doc
20 |
21 | inst/grided/www/rmd_layout_editing_files/
22 |
23 | inst/rmarkdown_demo/rmd_layout_editing_files/
24 |
25 | inst/rmarkdown_demo/rmd_layout_editing.html
26 |
27 | inst/demo_apps/rmarkdown_demo/rmd_layout_editing_files/
28 |
29 | *.mov
30 | doc
31 | Meta
32 |
33 | inst/grided/www/node_modules/
34 |
35 | inst/grided/www/.parcel-cache/
36 |
37 | inst/grided/www/yarn-error.log
38 |
39 | inst/demo_apps/rmarkdown_demo/remarker_test.html
40 |
41 | inst/demo_apps/rmarkdown_demo/grid_markdown.html
42 |
43 | inst/demo_apps/remarker/app.html
44 | /doc/
45 | /Meta/
46 |
--------------------------------------------------------------------------------
/DESCRIPTION:
--------------------------------------------------------------------------------
1 | Package: gridlayout
2 | Type: Package
3 | Title: Build Layouts for R-Webapps Using CSS-Grid
4 | Version: 0.2.1
5 | Authors@R: c(person("Nick", "Strayer", role = c("aut", "cre"), email = "nick.strayer@rstudio.com"))
6 | Description: Makes it easy to layout your Shiny app or other R-derived HTML documents using CSS grid.
7 | License: MIT + file LICENSE
8 | Encoding: UTF-8
9 | Suggests:
10 | testthat (>= 3.0.0),
11 | shiny,
12 | bslib,
13 | crayon,
14 | knitr,
15 | rmarkdown,
16 | fontawesome,
17 | here,
18 | rstudioapi,
19 | fs,
20 | glue,
21 | ggplot2,
22 | gt,
23 | shinytest2
24 | Config/testthat/edition: 3
25 | RoxygenNote: 7.2.3
26 | Roxygen: list(markdown = TRUE)
27 | VignetteBuilder: knitr
28 | Imports:
29 | magrittr,
30 | htmltools,
31 | rlang,
32 | lifecycle
33 | Config/Needs/website:
34 | rstudio/quillt
35 | Depends:
36 | R (>= 2.10)
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | YEAR: 2021
2 | COPYRIGHT HOLDER: gridlayout authors
3 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # MIT License
2 |
3 | Copyright (c) 2021 gridlayout authors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/NAMESPACE:
--------------------------------------------------------------------------------
1 | # Generated by roxygen2: do not edit by hand
2 |
3 | S3method(format,gridlayout)
4 | S3method(format,gridlayout_template)
5 | S3method(get_element_ids,gridlayout)
6 | S3method(get_element_ids,gridlayout_template)
7 | S3method(get_elements,default)
8 | S3method(get_elements,gridlayout)
9 | S3method(get_info,gridlayout)
10 | S3method(get_info,gridlayout_template)
11 | S3method(print,gridlayout)
12 | S3method(print,gridlayout_template)
13 | S3method(to_md,default)
14 | S3method(to_md,gridlayout)
15 | export("%>%")
16 | export(card_plot_output)
17 | export(get_element_ids)
18 | export(get_elements)
19 | export(grid_card)
20 | export(grid_card_old)
21 | export(grid_card_plot)
22 | export(grid_card_text)
23 | export(grid_container)
24 | export(grid_nested)
25 | export(grid_page)
26 | export(grid_place)
27 | export(md_to_gridlayout)
28 | export(new_gridlayout)
29 | export(to_css)
30 | export(to_matrix)
31 | export(to_md)
32 | export(use_gridlayout_rmd)
33 | importFrom(lifecycle,deprecated)
34 | importFrom(magrittr,"%>%")
35 |
--------------------------------------------------------------------------------
/NEWS.md:
--------------------------------------------------------------------------------
1 | # Development
2 |
3 | ### Minor new features and improvements
4 | - Now the default container height is 100% for any container other than `grid_page()`. This helps avoid confusing sizing when layout is embedded in other containers like a card.
5 |
6 | # gridlayout 0.2.1
7 |
8 | ### Minor new features and improvements
9 |
10 | - Replace internal usage of `bslib::card_body_fill()` with unsufixed `bslib::card_body()` to reflect updates in API. Will fix confusing warning messages about `card_body_fill` being depreciated even though it isn't used in user code.
11 |
12 | ### Bug fixes
13 | - Short cards could have squished contents (15c0397483529b34688f8f76bbc57a06ac9d9764)
14 |
15 | # gridlayout 0.2.0
16 |
17 | ### Major changes
18 |
19 | - `grid_card()` now wraps `bslib::card()` directly. This means that there are some api changes such as depreciated the `title` argument for using `bslib::card_header(title)` instead. Old `grid_card()` arguments that are present in code will get flagged with a warning to allow users to know when/how to update their code with the new version.
20 | - `card_plot_output()` is now depreciated in favor of the new `bslib` cards smart fill behavior. Simple plots can still be done with `grid_card_plot()`.
21 | - The function `grid_card_old()` has been added to ease transition to the new card api and to keep some features such as collapsibility are not available on the new api.
22 |
23 | # gridlayout 0.1.0
24 |
25 | ### Major new features and improvements
26 |
27 | - `grid_card()` is now the main method of placing items onto the grid
28 | - Added ability to add full-bleed header and sidebar with special child functions. These sit outside the main grid and can simplify layouts to not require them to constantly be added.
29 | - General interface for cards is a lighter in favor of outputting most non-layout logic to the coming `bslib::card()` and friends.
30 |
31 | ### Minor new features and improvements
32 |
33 | - Website has been updated with better resources
34 |
35 | ### Bug fixes
36 |
37 | ### Known bugs
38 |
--------------------------------------------------------------------------------
/R/array_table_to_matrix.R:
--------------------------------------------------------------------------------
1 | array_table_to_matrix <- function(array_table) {
2 |
3 |
4 | no_sizes <- array_table %>%
5 | lapply(function(line) str_trim(str_remove_all(line, CSS_VALUE_REGEX))) %>%
6 | Filter(f = function(line) line != "") %>%
7 | flatten() %>%
8 | strsplit(split = "\\s+")
9 |
10 | if (length(unique(get_num_cols_by_row(no_sizes))) > 1) {
11 | stop("Layout appears to be malformed. Make sure each row has the same number of columns")
12 | }
13 |
14 | layout_matrix <- flatten(no_sizes) %>%
15 | matrix(
16 | nrow = length(no_sizes),
17 | ncol = length(no_sizes[[1]]),
18 | byrow = TRUE
19 | )
20 |
21 | n_rows <- nrow(layout_matrix)
22 | n_cols <- ncol(layout_matrix)
23 |
24 | has_col_sizes <- length(array_table) > n_rows && any(
25 | has_css_value(
26 | vapply(
27 | split_on_space(array_table),
28 | FUN = function(line) line[1] ,
29 | FUN.VALUE = character(1L)
30 | )
31 | )
32 | )
33 |
34 | first_column_of_rows <- vapply(
35 | split_on_space(if (has_col_sizes) array_table[-1] else array_table),
36 | FUN = function(line) line[1] ,
37 | FUN.VALUE = character(1L)
38 | )
39 | has_row_sizes <- any(
40 | has_css_value(first_column_of_rows)
41 | )
42 |
43 | if (has_col_sizes){
44 | layout_matrix <- rbind("", layout_matrix)
45 | }
46 |
47 | if (has_row_sizes){
48 | layout_matrix <- cbind("", layout_matrix)
49 | }
50 |
51 |
52 | if (has_col_sizes){
53 | col_sizes <- strsplit(str_trim(array_table[[1]]), split = "\\s+")[[1]]
54 |
55 | if (length(col_sizes) < n_cols) {
56 | stop("If supplying column sizes in layout array, every column must be given a size.")
57 | }
58 |
59 | if (length(col_sizes) == n_cols && has_row_sizes) {
60 | # No gap size given so pad col_sizes with empty gap size space
61 | col_sizes <- c("", col_sizes)
62 | }
63 |
64 | layout_matrix[1,] <- col_sizes
65 | }
66 |
67 | if (has_row_sizes){
68 |
69 | # We can fill in empty values for row sizes, however, so do that here
70 | first_column_of_rows[!has_css_value(first_column_of_rows)] = ""
71 |
72 | if (has_col_sizes) {
73 | layout_matrix[-1,1] <- first_column_of_rows
74 | } else {
75 | layout_matrix[,1] <- first_column_of_rows
76 | }
77 | }
78 |
79 |
80 | layout_matrix
81 |
82 | }
83 |
84 |
--------------------------------------------------------------------------------
/R/bootstrap-background-colors.R:
--------------------------------------------------------------------------------
1 | # https://getbootstrap.com/docs/5.0/utilities/background/#background-color
2 | bslib_bg_colors <- c(
3 | "primary",
4 | "secondary",
5 | "success",
6 | "danger",
7 | "warning",
8 | "info",
9 | "light",
10 | "dark"
11 | )
12 |
13 |
14 | #' Build a bootstrap background class
15 | #'
16 | #' Info on possible colors from the [bootstrap
17 | #' website](https://getbootstrap.com/docs/5.0/utilities/background/#background-color)
18 | #'
19 | #' @param bgColor Color of background in terms of bootstrap variable names:
20 | #' Options are `"primary"`, `"secondary"`, `"success"`, `"danger"`,
21 | #' `"warning"`, `"info"`, `"light"`, and `"dark`.
22 | #' @param bgGradient Should a gradient be applied to the background instead of a
23 | #' solid color?
24 | #'
25 | #' @return A string containing the bootstrap class name to apply the requested
26 | #' background color
27 | #'
28 | #' @keywords internal
29 | #'
30 | #' @examples
31 | #'
32 | #' gridlayout:::make_bg_class("warning")
33 | #' # A gradient can be applied as well
34 | #' gridlayout:::make_bg_class("primary", TRUE)
35 | #'
36 | make_bg_class <- function(bgColor = NULL, bgGradient = FALSE) {
37 |
38 | if (is.null(bgColor)) return("")
39 | if (!bgColor %in% bslib_bg_colors) {
40 | stop("The requested color of ", bgColor, " is not one of the possible ",
41 | "options. Possible values are ",
42 | paste0("\"", bslib_bg_colors, "\"", collapse = ", "), ".")
43 | }
44 | paste0("bg-",bgColor, if (bgGradient) " bg-gradient" else "")
45 | }
46 |
47 |
48 |
--------------------------------------------------------------------------------
/R/check_for_area_mismatches.R:
--------------------------------------------------------------------------------
1 |
2 | # elements <- htmltools::tagList(
3 | # htmltools::div("hi", style="grid-area:test; background-color:green;"),
4 | # htmltools::div("there", style="background-color: red;"),
5 | # htmltools::div("world")
6 | # )
7 | get_provided_grid_areas <- function(elements){
8 | areas <- lapply(elements, FUN=get_grid_area)
9 | simplify2array(
10 | Filter(function(x) !is.null(x), x = areas)
11 | )
12 | }
13 |
14 | get_grid_area <- function(el){
15 | inline_styles <- el$attribs$style
16 | if(is.null(inline_styles)) {
17 | return(NULL)
18 | }
19 |
20 | grid_area <- str_extract(
21 | inline_styles,
22 | pattern = "(?<=grid-area:)\\s*\\w+(?=;)"
23 | )
24 |
25 | # Account for potential spaces in the grid area definition
26 | grid_area <- str_trim(grid_area)
27 |
28 | if(length(grid_area) == 0) {
29 | return(NULL)
30 | }
31 |
32 | grid_area
33 | }
34 |
35 |
36 | check_for_area_mismatches <- function(provided_areas, layout_areas){
37 |
38 | error_msg <- c()
39 |
40 | not_in_provided <- layout_areas[!layout_areas %in% provided_areas]
41 | if (length(not_in_provided) > 0) {
42 |
43 | missing_areas <- paste0("\"", not_in_provided,"\"", collapse = ', ')
44 | error_msg <- c(
45 | error_msg,
46 | paste(
47 | "Grid areas", missing_areas, "are specified in the layout but not present in the children:\n",
48 | "If the grid-area css property for these areas is being provided in a custom",
49 | " way, set `check_for_mismatches = FALSE` to avoid this error message."
50 | )
51 | )
52 | }
53 |
54 |
55 | not_in_layout <- provided_areas[!provided_areas %in% layout_areas]
56 | if (length(not_in_layout) > 0) {
57 | missing_areas <- paste0("\"", not_in_layout,"\"", collapse = ', ')
58 | error_msg <- c(
59 | error_msg,
60 | paste(
61 | "Grid areas", missing_areas,
62 | "are present in the children of grid container but not specified in the layout:\n"
63 | )
64 | )
65 | }
66 |
67 | if (length(error_msg) == 0) { return(NULL) }
68 |
69 |
70 | stop(paste(error_msg, collapse = "\n"), call. = FALSE)
71 | }
72 |
--------------------------------------------------------------------------------
/R/get_elements.R:
--------------------------------------------------------------------------------
1 | #' Get elements and positions out of a `gridlayout` object
2 | #'
3 | #' @param layout Object of class `"gridlayout"`
4 | #'
5 | #' @return List of all unique elements in the layout and their `id`,
6 | #' `{start,end}_row`, and `{start,end}_col`. Positions are indexed starting at
7 | #' 1
8 | #'
9 | #' @seealso [get_element_ids]
10 | #' @examples
11 | #' grid_obj <- md_to_gridlayout(
12 | #' layout_table = "
13 | #' | |120px |1fr |1fr |
14 | #' |------|--------|-------|-------|
15 | #' |100px |header |header |header |
16 | #' |1fr |sidebar |plot_a |plot_a |
17 | #' |1fr |sidebar |plot_b |plot_c |"
18 | #' )
19 | #'
20 | #' get_elements(grid_obj)
21 | #'
22 | #' @export
23 | get_elements <- function(layout){
24 | UseMethod("get_elements")
25 | }
26 |
27 | #' @export
28 | get_elements.default <- function(layout){
29 | warning("The get_elements function is only defined for objects of the gridlayout class")
30 | }
31 |
32 | #' @export
33 | get_elements.gridlayout <- function(layout){
34 | # Just remove the gridlayout class so printing doesn't confuse people
35 | get_info(layout, "elements")
36 | }
37 |
38 | #' Get ids of element in `gridlayout` object
39 | #'
40 | #' @param x Object of class `"gridlayout"`.
41 | #'
42 | #' @return Character vector of ids of all elements in layout
43 | #' @export
44 | #'
45 | #' @seealso [get_elements]
46 | #' @examples
47 | #'
48 | #' grid_obj <- md_to_gridlayout(
49 | #' layout_table = "
50 | #' | |120px |1fr |1fr |
51 | #' |------|--------|-------|-------|
52 | #' |100px |header |header |header |
53 | #' |1fr |sidebar |plot_a |plot_a |
54 | #' |1fr |sidebar |plot_b |plot_c |"
55 | #' )
56 | #'
57 | #' get_element_ids(grid_obj)
58 | get_element_ids <- function(x){
59 | UseMethod("get_element_ids")
60 | }
61 |
62 | get_element_ids.default <- function(x){
63 | cat("get_element_ids generic")
64 | }
65 |
66 | #' @export
67 | get_element_ids.gridlayout <- function(x){
68 | get_info(x, "element_ids")
69 | }
70 |
71 | #' @export
72 | get_element_ids.gridlayout_template <- function(x){
73 | extract_chr(get_info(x, "elements"), "id")
74 | }
75 |
76 |
--------------------------------------------------------------------------------
/R/get_info.R:
--------------------------------------------------------------------------------
1 | get_info <- function(x, prop){
2 | UseMethod("get_info")
3 | }
4 |
5 | get_info.default <- function(x, prop){
6 | cat("get_info generic")
7 | }
8 |
9 | #' @export
10 | get_info.gridlayout <- function(x, prop){
11 | if (is_gridlayout_prop(prop)) {
12 | return (x[[prop]])
13 | }
14 | get_info.gridlayout_template(x$layout, prop)
15 | }
16 |
17 | #' @export
18 | get_info.gridlayout_template <- function(x, prop){
19 | if (is.null(x[[prop]])) {
20 | if (is_gridlayout_prop(prop)) {
21 | stop("Try to access property of gridlayout from gridlayout_template object")
22 | }
23 | stop("That property doesn't exist")
24 | }
25 | x[[prop]]
26 | }
27 |
28 | is_gridlayout_prop <- function(prop) prop %in% c("element_ids", "alternates")
29 |
30 | dump_all_info <- function(x) {
31 | list(
32 | grid = list(
33 | rows = get_info(x, "row_sizes"),
34 | cols = get_info(x, "col_sizes"),
35 | gap = get_info(x, "gap_size")
36 | ),
37 | elements = get_elements(x)
38 | )
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/R/grid_card.R:
--------------------------------------------------------------------------------
1 | #' Grid-positioned card element
2 | #'
3 | #' The standard element for placing elements on the grid in a simple card
4 | #' container
5 | #'
6 | #' @param area Name of grid area, should match an area defined in the layout
7 | #' section of the wrapping `grid_page()` or `grid_container()`.
8 | #' @inheritDotParams bslib::card
9 | #'
10 | #' @seealso [bslib::card] for underlying function. [bslib::card_header],
11 | #' [bslib::card_body], [bslib::card_footer].
12 | #' [grid_card_text()] for a card with just text content,
13 | #' [grid_card_plot()] for a card with just plot content, [grid_place()] to
14 | #' place any tag onto the grid without needing to wrap in a card, and
15 | #' [card_plot_output()] for including a smart-sized plot within a card.
16 | #'
17 | #' @example man/examples/simple_app.R
18 | #' @export
19 | grid_card <- function(area, ...) {
20 | warn_about_new_api(...)
21 | grid_place(area = area, bslib::card(...))
22 | }
23 |
24 |
25 | warn_about_new_api <- function(...) {
26 | card_args <- list(...)
27 | args_names <- names(card_args)
28 | ignored_args <- args_names[args_names %in% old_api_args]
29 | if (length(ignored_args) > 0) {
30 | warning(
31 | paste0(
32 | "The grid_card() api updated with version 0.1.1 and ",
33 | "the following args are no longer supported: ",
34 | paste0("\"", ignored_args, "\"", collapse = ","),
35 | ". Look at help for bslib::card() to find alternatives! Alternatively ",
36 | "you can switch to grid_card_old() to keep the same api ",
37 | "(although updating to the new bslib version is recomended!)"
38 | )
39 | )
40 | }
41 | }
42 | old_api_args <- c(
43 | "title",
44 | "scrollable",
45 | "collapsible",
46 | "has_border",
47 | "item_gap"
48 | )
49 |
--------------------------------------------------------------------------------
/R/grid_card_text.R:
--------------------------------------------------------------------------------
1 |
2 | #' Grid-positioned card with only text
3 | #'
4 | #' Makes a grid_card that contains just text that is vertically centered within
5 | #' the panel. Useful for app titles or displaying text-based statistics.
6 | #'
7 | #' @inheritParams grid_card
8 | #' @inheritDotParams grid_card
9 | #' @param content Whatever you want the title to say. Typically just text but
10 | #' any tag or tag-list is possible. All will get wrapped in an `h3` tag.
11 | #' @param wrapping_tag What tag should the text be wrapped in. Takes either an
12 | #' `htmltools` tag function or the string of a tag accessible via
13 | #' `htmltools::tags[[wrapping_tag]]`.
14 | #' @param icon Optional icon/image for left of text. Supports image locations
15 | #' (those ending in `.png, .jpg, .jpeg` or `.svg`), ids of font-awesome icons
16 | #' (i.e. that works with `fontawesome::fa(icon)]`, or `fontawesome` icons as
17 | #' returned by [fontawesome::fa()] (if customization of icon style is
18 | #' desired.)
19 | #' @param alignment Horizontal alignment of text. Typical options include
20 | #' `start", "center", "end"`. For full list of options, see the [css-spec for
21 | #' `align-items`.](https://developer.mozilla.org/en-US/docs/Web/CSS/align-items)
22 | #'
23 | #' @param is_title Should the text of this panel be passed on as the title of
24 | #' the page? This will make the text show up in the browser tab or when you
25 | #' bookmark the app etc..
26 | #' @param img_height If the passed icon is a path to an image, how tall should
27 | #' that image be rendered (preserves aspect ratio.)
28 | #' @inheritParams grid_card
29 | #'
30 | #' @examples
31 | #'
32 | #' # Typically you'll just pass a character string to the function
33 | #' grid_card_text(area = "header", "This is my header")
34 | #'
35 | #' # Icons from `fontawesome` can be used:
36 | #'
37 | #' # Either with just the id
38 | #' grid_card_text(area = "header", "Here's my text", icon = "r-project")
39 | #'
40 | #' # Or by directly passing the icon object if you want more customization
41 | #' grid_card_text(
42 | #' "header",
43 | #' "Here's my text",
44 | #' icon = fontawesome::fa("r-project", fill = "steelblue")
45 | #' )
46 | #'
47 | #' # You can also pass arbitrary image locations for the icon
48 | #' grid_card_text(
49 | #' "header",
50 | #' "Here's my text",
51 | #' icon = "https://cran.r-project.org/Rlogo.svg"
52 | #' )
53 | #'
54 | #' # These images can have their size controlled
55 | #' grid_card_text(
56 | #' "header",
57 | #' "Here's my text",
58 | #' icon = "https://cran.r-project.org/Rlogo.svg",
59 | #' img_height = "20px"
60 | #' )
61 | #'
62 | #'
63 | #' # Commonly you may want to use the text panel text as the title of your app
64 | #' grid_card_text(area = "header", "My App Name", is_title = TRUE)
65 | #'
66 | #' @example man/examples/simple_app.R
67 | #'
68 | #' @export
69 | grid_card_text <- function(area,
70 | content = NULL,
71 | ...,
72 | alignment = "start",
73 | img_height = "55px",
74 | icon = NULL,
75 | wrapping_tag = "h2",
76 | is_title = FALSE) {
77 | if (notNull(icon)) {
78 | if (str_detect(icon, "\\.png|\\.jpg|\\.jpeg|\\.svg")) {
79 | icon <- shiny::img(src = icon, height = htmltools::validateCssUnit(img_height))
80 | } else {
81 | requireNamespace("fontawesome", quietly = TRUE)
82 | # Test against a font awesome tag in case the class changes
83 | already_fa_obj <- identical(class(icon), class(fontawesome::fa("r-project")))
84 |
85 | if (!already_fa_obj) {
86 | # Attempt to get icon from font-awesome
87 | icon <- fontawesome::fa(icon)
88 | }
89 | }
90 | }
91 |
92 | if (is.character(wrapping_tag)) {
93 | wrapping_tag <- htmltools::tags[[wrapping_tag]]
94 | }
95 |
96 | grid_place(
97 | area = area,
98 | htmltools::tags$div(
99 | class = "card grid_card_text",
100 | style = htmltools::css(
101 | `align-items` = alignment
102 | ),
103 | wrapping_tag(
104 | htmltools::tagList(
105 | icon,
106 | content
107 | )
108 | ),
109 | if (is_title) htmltools::tags$head(htmltools::tags$title(content))
110 | )
111 | )
112 | }
113 |
--------------------------------------------------------------------------------
/R/grid_nested.R:
--------------------------------------------------------------------------------
1 | #' Grid-positioned card with `gridlayout` positioned content
2 | #'
3 | #' Creates a panel for a layout with its own internal gridlayout
4 | #'
5 | #' @inheritParams grid_card
6 | #' @param title Optional title for the card. Gets wrapped in
7 | #' `bslib::card_header()`
8 | #' @inheritParams grid_container
9 | #'
10 | #' @seealso [grid_card], [grid_container]
11 | #'
12 | #' @return A `grid_card` with a nested layout within it
13 | #'
14 | #' @seealso [grid_page()] for using a gridlayout to entirely define the page.
15 | #' [grid_container()] for placing a gridlayout in non-gridlayout parent
16 | #' elements. [grid_card()] for placing content inside your layout. See
17 | #' `vignette("defining-a-layout", package = "gridlayout")` for more info on
18 | #' defining your layout.
19 | #'
20 | #' @example man/examples/nested_app.R
21 | #' @export
22 | grid_nested <- function(area,
23 | layout,
24 | ...,
25 | id = NULL,
26 | title = NULL,
27 | flag_mismatches = TRUE) {
28 |
29 | nested_grid <- grid_container(
30 | layout = new_gridlayout(layout, container_height = "100%"),
31 | flag_mismatches = flag_mismatches,
32 | id = id,
33 | ...
34 | )
35 |
36 | grid_card(
37 | area = area,
38 | if (!is.null(title)) {
39 | bslib::card_header(title)
40 | },
41 | bslib::card_body(
42 | class = "p-0",
43 | nested_grid
44 | )
45 | )
46 | }
47 |
--------------------------------------------------------------------------------
/R/grid_page.R:
--------------------------------------------------------------------------------
1 | #' Use `gridlayout` for entire app layout
2 | #'
3 | #' This is the typical way to use `gridlayout` in your `Shiny` app. `grid_page`
4 | #' will make up the entire `ui` declaration of the app. Under the hood it uses
5 | #' [shiny::fluidPage()] and [grid_container]. Elements are placed in the layout
6 | #' by wrapping in a `grid_card()` with the `area` set to the area in the layout
7 | #' the element should be placed in.
8 | #'
9 | #' @inheritParams grid_container
10 | #' @param container_height Optional parameter to control height of page.
11 | #' Defaults to `"viewport"` so app takes up full vertical space of page.
12 | #' See argument of same name in `new_gridlayout()` for more options.
13 | #' @param theme Optional argument to pass to `theme` argument of
14 | #' \code{\link[shiny]{fluidPage}}.
15 | #' @param flag_mismatches Should mismatches between the named arguments and
16 | #' layout elements trigger an error?
17 | #'
18 | #' @return A UI definition that can be passed to the
19 | #' \code{\link[shiny]{shinyUI}} function.
20 | #' @export
21 | #'
22 | #' @seealso See `vignette("defining-a-layout", package = "gridlayout")` for more info on defining your layout. [grid_container()] for using gridlayout without also setting up the
23 | #' root page layout. [grid_nested()] for placing a grid container within
24 | #' another gridlayout. [grid_card()] for placing content inside your layout.
25 | #'
26 | #' @example man/examples/simple_app.R
27 | #'
28 | grid_page <- function(layout,
29 | ...,
30 | row_sizes = NULL,
31 | col_sizes = NULL,
32 | gap_size = NULL,
33 | container_height = "viewport",
34 | theme = bslib::bs_theme(version = 5),
35 | flag_mismatches = FALSE) {
36 | dot_args <- list(...)
37 |
38 | body_elements <- Filter(
39 | f = function(x) !(is_grid_page_header(x) || is_grid_page_sidebar(x)),
40 | dot_args
41 | )
42 |
43 | header <- Filter(
44 | f = function(x) is_grid_page_header(x),
45 | dot_args
46 | )
47 |
48 | sidebar <- Filter(
49 | f = function(x) is_grid_page_sidebar(x),
50 | dot_args
51 | )
52 |
53 | container_args <- c(
54 | list(
55 | layout = layout,
56 | flag_mismatches = flag_mismatches,
57 | row_sizes = row_sizes,
58 | col_sizes = col_sizes,
59 | gap_size = gap_size,
60 | container_height=container_height,
61 | # This is used to prevent a randomly generated grid container id data
62 | # attribute which stabilizes tests and makes it easier to target with
63 | # custom css
64 | id = "gridlayout-grid-page-container"
65 | ),
66 | body_elements
67 | )
68 |
69 | container <- do.call(grid_container, container_args)
70 |
71 | shiny::fluidPage(
72 | theme = theme,
73 | htmltools::tags$div(
74 | id = "gridlayout-grid-page",
75 | header,
76 | sidebar,
77 | container
78 | )
79 | )
80 | }
81 |
82 |
83 | grid_page_header <- function(..., bgColor = "primary", bgGradient = FALSE, height = NULL) {
84 | update_el(
85 | htmltools::tags$div(...),
86 | classes = c(
87 | "grid-page-header",
88 | make_bg_class(bgColor, bgGradient)
89 | ),
90 | styles = list(height = height)
91 | )
92 | }
93 |
94 | is_grid_page_header <- function(x) {
95 | has_class(x, "grid-page-header")
96 | }
97 |
98 | grid_page_sidebar <- function(..., side = "left", bgColor = "light", bgGradient = FALSE, width = NULL) {
99 | update_el(
100 | htmltools::tags$div(...),
101 | classes = c(
102 | make_bg_class(bgColor, bgGradient),
103 | paste0("grid-page-sidebar-", side)
104 | ),
105 | styles = list(
106 | width = width
107 | )
108 | )
109 | }
110 |
111 | is_grid_page_sidebar <- function(x) {
112 | has_class(x, "grid-page-sidebar")
113 | }
114 |
--------------------------------------------------------------------------------
/R/grid_place.R:
--------------------------------------------------------------------------------
1 | #' Place any `shiny.tag` element on the grid
2 | #'
3 | #' Allows you to place any item directly on the grid without having to wrap it
4 | #' in `grid_card()` or other containers. This is done by adding a css property
5 | #' and data-attribute to the tag object.
6 | #'
7 | #' @param area Area of grid corresponding to the wrapping grid containers grid
8 | #' definition
9 | #' @param element Element (html tag) to be placed.
10 | #'
11 | #' @return The `element` updated with a `gridlayout-area` data-attribute and the
12 | #' `grid-area` property added to its styles
13 | #'
14 | #' @seealso [grid_card()] to place content on the grid wrapped in a bootstrap
15 | #' card.
16 | #' @example man/examples/grid_place_app.R
17 | #' @export
18 | grid_place <- function(area, element) {
19 | if (!inherits(element, "shiny.tag")) {
20 | stop("element needs to be a valid tag object")
21 | }
22 |
23 | htmltools::tagAppendAttributes(
24 | add_styles(
25 | element,
26 | "grid-area" = area
27 | ),
28 | "data-gridlayout-area" = area,
29 | )
30 | }
31 |
--------------------------------------------------------------------------------
/R/grid_plot.R:
--------------------------------------------------------------------------------
1 | #' Grid-positioned plot output
2 | #'
3 | #' A light wrapper for `shiny::plotOutput()` that uses gridlayout-friendly
4 | #' sizing defaults.
5 | #'
6 | #'
7 | #' @inheritParams grid_card
8 | #' @param outputId Output id of the plot output. Used to link to server code
9 | #' generating plot. If left unset this will use the same value as the `area`
10 | #' argument.
11 | #' @inheritDotParams shiny::plotOutput
12 | #'
13 | #' @return A grid panel filled with plot output
14 | #'
15 | #' @seealso [bslib::card_body], [shiny::plotOutput()]
16 | #' @example man/examples/simple_app.R
17 | #'
18 | #' @export
19 | grid_card_plot <- function(area, outputId = area,...) {
20 | grid_card(
21 | area = area,
22 | height = "100%",
23 | bslib::card_body(
24 | shiny::plotOutput(outputId = outputId, ...)
25 | )
26 | )
27 | }
28 |
29 |
30 | #' Plot output with smart sizing for use inside a `grid_card` - Depreciated
31 | #'
32 | #' `r lifecycle::badge('deprecated')`
33 | #'
34 | #' No longer necessary. Use plain `shiny::plotOutput()` wrapped with
35 | #' `bslib::card_body()`.
36 | #'
37 | #' @inheritParams shiny::plotOutput
38 | #' @param ... Named arguments become attributes on the div containing the plot.
39 | #' @param height height in valid css units (see [htmltools::validateCssUnit()]
40 | #' for more details.) Most use-cases will leave this unset and the plot will
41 | #' fill the card as best it can.
42 | #' @param stretch Set to `TRUE` if this `card_body` is eager to use any extra
43 | #' vertical space is available in the card.
44 | #'
45 | #' @seealso [grid_card_plot()] for a simpler way of placing just a plot on the
46 | #' grid
47 | #' @export
48 | card_plot_output <- function(outputId,
49 | click = NULL,
50 | dblclick = NULL,
51 | hover = NULL,
52 | brush = NULL,
53 | height = NULL,
54 | stretch = TRUE,
55 | ...) {
56 |
57 | lifecycle::deprecate_warn()("card_plot_output() is no longer needed with bslib card api. Simply use regular shiny::plotOutput()")
58 |
59 | plot_div <- shiny::plotOutput(
60 | outputId,
61 | height = height,
62 | click = click,
63 | dblclick = dblclick,
64 | hover = hover,
65 | brush = brush
66 | )
67 |
68 | # TODO: card-img-* needs to go on the
itself, not the containing
69 | htmltools::tagAppendAttributes(
70 | plot_div,
71 | style = htmltools::css(
72 | flex = if (stretch) "1 1",
73 | `-webkit-flex` = if (stretch) "1 1",
74 | # May be NULL
75 | `flex-basis` = htmltools::validateCssUnit(height),
76 | `-webkit-flex-basis` = htmltools::validateCssUnit(height),
77 | ),
78 | !!!rlang::list2(...)
79 | )
80 | }
81 |
--------------------------------------------------------------------------------
/R/gridlayout-package.R:
--------------------------------------------------------------------------------
1 | #' @keywords internal
2 | "_PACKAGE"
3 |
4 | ## usethis namespace: start
5 | #' @importFrom lifecycle deprecated
6 | ## usethis namespace: end
7 | NULL
8 |
--------------------------------------------------------------------------------
/R/helper-demo-apps.R:
--------------------------------------------------------------------------------
1 |
2 | demo_apps <- c(
3 | "alternate_layouts",
4 | "nested_grids",
5 | "recursive_nesting",
6 | "scrolling_panels"
7 | )
8 |
9 | accept_demo_snapshots <- function(){
10 | for (demo_app in demo_apps) {
11 | path_to_app <- system.file(package = "gridlayout", paste0("demo_apps/", demo_app))
12 |
13 | testthat::snapshot_accept(path=file.path(path_to_app, "tests/testthat"))
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/R/md_table_to_matrix.R:
--------------------------------------------------------------------------------
1 |
2 | md_table_to_matrix <- function(md_layout){
3 | # Split into rows
4 | by_rows <- strsplit(md_layout, "\\n")[[1]] %>% str_trim()
5 | by_rows <- by_rows[by_rows != ""]
6 |
7 | is_valid_md_table <- all(
8 | grepl(
9 | x = by_rows,
10 | pattern = "^\\s*\\|.*\\|\\s*$",
11 | perl = TRUE
12 | )
13 | )
14 |
15 | if (!is_valid_md_table){
16 | stop("Layout table is malformed. Check syntax.")
17 | }
18 |
19 | nested_arrays <- by_rows %>%
20 | # Remove any decorative header lines: e.g. "|---:|"
21 | Filter(f = function(x) !grepl(x, pattern = "^[\\s\\|\\-|:]+$", perl = TRUE)) %>%
22 | # Remove leading pipes
23 | str_remove_all("^\\|\\s*") %>%
24 | # Split into cells on internal pipes
25 | strsplit("\\s*\\|\\s*") %>%
26 | Filter(f = function(x) {length(x) > 0})
27 |
28 |
29 | layout_matrix <- matrix(
30 | do.call(c, nested_arrays),
31 | nrow = length(nested_arrays),
32 | byrow = TRUE
33 | )
34 |
35 |
36 | layout_matrix
37 | }
38 |
--------------------------------------------------------------------------------
/R/md_to_gridlayout.R:
--------------------------------------------------------------------------------
1 | #' Build `gridlayout` object from markdown table
2 | #'
3 | #' This is just a wrapper around [new_gridlayout] that is more explicit about
4 | #' its input format. Also adds the ability to absorb errors for use when parsing
5 | #' free text that may or may not represent a layout table.
6 | #'
7 | #' @param layout_table Character string with a markdown table. First row and
8 | #' column are reserved for sizing (any valid css sizing works). An optional
9 | #' grid-gap can be provided using the very first cell.
10 | #' @param null_instead_of_error When the input fails to be parsed as a layout,
11 | #' should the function return `NULL` instead of throwing an error? Useful for
12 | #' situations where you're parsing multiple tables simply want to check if a
13 | #' table can be parsed instead of relying on it being parsable.
14 | #' @inheritDotParams new_gridlayout
15 | #'
16 | #' @return An object of class "grid_layout", which stores the layout as a
17 | #' matrix. This can be passed to other functions such as `layout_to_css()`.
18 | #'
19 | #' @seealso [new_gridlayout]
20 | #' @export
21 | #'
22 | #' @examples
23 | #' md_to_gridlayout(
24 | #' layout_table = "
25 | #' | |120px |1fr |1fr |
26 | #' |:-----|:-------|:------|:------|
27 | #' |100px |header |header |header |
28 | #' |1fr |sidebar |plot_a |plot_c |
29 | #' |1fr |sidebar |plot_b |plot_b |"
30 | #' )
31 | #'
32 | #'
33 | #' # Can specify gap size in upper left cell
34 | #' md_to_gridlayout(
35 | #' layout_table = "
36 | #' |25px |120px |1fr |
37 | #' |:-----|:------|:------|
38 | #' |100px |header |header |
39 | #' |1fr |plot |table |
40 | #' |1fr |footer |footer |"
41 | #' )
42 | #'
43 | #' # Don't need to follow full md table with
44 | #' # header row if not desired
45 | #' md_to_gridlayout(
46 | #' layout_table = "
47 | #' |25px |120px |1fr |
48 | #' |100px |header |header |
49 | #' |1fr |plot |table |
50 | #' |1fr |footer |footer |"
51 | #' )
52 | #'
53 | #' # Can omit sizing as well if desired
54 | #' md_to_gridlayout(
55 | #' layout_table = "
56 | #' |header |header |
57 | #' |plot |table |
58 | #' |footer |footer |"
59 | #' )
60 | #'
61 | md_to_gridlayout <- function(layout_table, null_instead_of_error = FALSE, ...) {
62 | tryCatch(
63 | {
64 | new_gridlayout(layout_table, ...)
65 | },
66 | error = function(err) {
67 | if (null_instead_of_error) {
68 | NULL
69 | } else {
70 | stop(err)
71 | }
72 | }
73 | )
74 | }
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/R/parse_layout_matrix.R:
--------------------------------------------------------------------------------
1 | DEFAULT_SIZE_CHAR <- "."
2 |
3 | parse_layout_matrix <- function(layout_matrix){
4 |
5 | # Missing column sizes
6 | if (!all_css_or_empty(layout_matrix[1,])) {
7 | layout_matrix <- rbind(
8 | "",
9 | layout_matrix
10 | )
11 | }
12 |
13 | # Missing row sizes
14 | if (!all_css_or_empty(layout_matrix[,1])){
15 | layout_matrix <- cbind(
16 | "",
17 | layout_matrix
18 | )
19 | }
20 |
21 | # Subtract the size row and column to get layout dimensions
22 | n_rows <- nrow(layout_matrix) - 1L
23 | n_cols <- ncol(layout_matrix) - 1L
24 |
25 | # Fill in the empty or missing sizes with defaults
26 | column_sizes <- fill_missing_w_default(layout_matrix[1,-1])
27 | row_sizes <- fill_missing_w_default(layout_matrix[-1,1])
28 | gap_size <- fill_missing_w_default(layout_matrix[1,1])
29 |
30 | # Strip away sizes to get the main layout matrix
31 | items_matrix <- matrix(
32 | layout_matrix[-1,-1],
33 | nrow = n_rows,
34 | ncol = n_cols
35 | )
36 |
37 | item_ids <- unique(as.vector(items_matrix))
38 |
39 | validate_item_ids(item_ids)
40 |
41 | elements <- lapply(
42 | item_ids,
43 | function(id){
44 | all_pos <- which( items_matrix == id, arr.ind = TRUE )
45 | list(
46 | id = id,
47 | start_row = min(all_pos[,"row"]),
48 | end_row = max(all_pos[,"row"]),
49 | start_col = min(all_pos[,"col"]),
50 | end_col = max(all_pos[,"col"])
51 | )
52 | }
53 | )
54 |
55 | list(
56 | areas = items_matrix,
57 | elements = elements,
58 | column_sizes = column_sizes,
59 | row_sizes = row_sizes,
60 | gap_size = gap_size
61 | )
62 | }
63 |
64 | VALID_ITEM_ID_REGEX = "^[a-zA-Z]+\\w*|\\.$"
65 | validate_item_ids <- function(item_ids){
66 |
67 | is_valid_item_id <- str_detect(item_ids, pattern = VALID_ITEM_ID_REGEX)
68 |
69 | if (all(is_valid_item_id)) { return(TRUE) }
70 |
71 | bad_ids <- item_ids[!is_valid_item_id]
72 |
73 | stop(
74 | "Layout has the following invalid item ids in it:\n",
75 | list_in_quotes(bad_ids), "\n",
76 | "Only simple words and (non-starting) numbers are allowed.",
77 | call. = FALSE
78 | )
79 | }
80 |
--------------------------------------------------------------------------------
/R/parsing-utils.R:
--------------------------------------------------------------------------------
1 | CSS_VALUE_REGEX <- "([0-9]\\d*)(\\.\\d+)?(px|rem|fr)|auto"
2 | has_css_value <- function(x) grepl(x, pattern = CSS_VALUE_REGEX, perl = TRUE)
3 |
4 |
5 |
6 | replace_x_with_y<- function(vec, x, y){
7 | vec[vec == x] <- y
8 | vec
9 | }
10 |
11 |
12 | fill_missing_w_default <- function(vec){
13 | replace_x_with_y(vec, x = "", y = DEFAULT_SIZE_CHAR)
14 | }
15 |
16 | replace_default_with_value <- function(vec, val) {
17 | replace_x_with_y(vec, x = DEFAULT_SIZE_CHAR, y = val)
18 | }
19 |
20 |
21 | all_css_or_empty <- function(vals) {
22 | all(has_css_value(vals) | vals == "")
23 | }
24 |
25 |
26 | flatten <- function(x) { do.call(what = c, args = x)}
27 |
28 | get_num_cols_by_row <- function(nested_array){
29 | vapply(
30 | nested_array,
31 | FUN = length,
32 | FUN.VALUE = numeric(1L)
33 | )
34 | }
35 |
36 | split_on_space <- function(x){
37 | strsplit(str_trim(x), split = "\\s+")
38 | }
39 |
--------------------------------------------------------------------------------
/R/tag-utils.R:
--------------------------------------------------------------------------------
1 |
2 | add_styles <- function(el, ...) {
3 | el$attribs$style <- paste0(
4 | el$attribs$style,
5 | htmltools::css(...)
6 | )
7 |
8 | el
9 | }
10 |
11 | add_class <- function(el, class) {
12 | htmltools::tagAppendAttributes(el, class = paste(class, collapse = " "))
13 | }
14 |
15 | update_el <- function(el, classes = list(), styles = list()) {
16 | el <- htmltools::tagAppendAttributes(
17 | el,
18 | class = paste(classes, collapse = " ")
19 | )
20 |
21 | el$attribs$style <- paste0(
22 | el$attribs$style,
23 | do.call(htmltools::css, styles)
24 | )
25 |
26 | el
27 | }
28 |
29 |
30 | has_class <- function(el, class) {
31 | if (!inherits(el, "shiny.tag")) {
32 | return(FALSE)
33 | }
34 |
35 | any(
36 | grepl(
37 | x = htmltools::tagGetAttribute(el, "class"),
38 | pattern = class,
39 | fixed = TRUE
40 | )
41 | )
42 | }
43 |
--------------------------------------------------------------------------------
/R/use_gridlayout_rmd.R:
--------------------------------------------------------------------------------
1 | #' Enable `gridlayout` usage in RMarkdown documents
2 | #'
3 | #' Adds required hooks to RMarkdown to process `gridlayout` chunks and style
4 | #' document accordingly. Layout will be generated from a chunk identified with
5 | #' the syntax ```` ```{gridlayout}
``` ````
6 | #'
7 | #' See `vignette("using_with_rmd", package = "gridlayout")` for a more in-depth
8 | #' overview.
9 | #'
10 | #' @param container_query The CSS selector used to access the main grid
11 | #' container. This is typically left at the default of `'.main-container'` as
12 | #' that's the parent of each section in the standard rmd template.
13 | #' @param selector_prefix CSS prefix used to target grid elements. This will
14 | #' change if you're integrating grid with a system that you don't want to use
15 | #' ids (the `"#"` prefix) with because they are not available or are used for
16 | #' other reasons.
17 | #'
18 | #' @return NULL
19 | #' @export
20 | #'
21 | use_gridlayout_rmd <- function(container_query = ".main-container",
22 | selector_prefix = "#") {
23 | requireNamespace("knitr", quietly = TRUE)
24 |
25 | accessory_css <- get_accessory_css("gridlayout.css")
26 |
27 |
28 | knitr::knit_engines$set(gridlayout = function(options) {
29 | code <- paste(options$code, collapse = "\n")
30 | if (options$eval) {
31 | layout <- md_to_gridlayout(code)
32 | areas <- get_element_ids(layout)
33 |
34 | css_for_layout <- paste(
35 | "",
48 | sep = "\n"
49 | )
50 | }
51 | options$results <- "asis"
52 | options$echo <- FALSE
53 | knitr::engine_output(
54 | options,
55 | code = options$code,
56 | out = css_for_layout
57 | )
58 | })
59 | }
60 |
61 | # Dump css file to string for inlining while still keeping in a .css file for
62 | # easier editing
63 | get_accessory_css <- function(file) {
64 | paste(
65 | readLines(system.file(paste0("resources/", file), package = "gridlayout")),
66 | collapse = "\n"
67 | )
68 | }
69 |
--------------------------------------------------------------------------------
/R/use_gridlayout_shiny.R:
--------------------------------------------------------------------------------
1 |
2 | #' Convert layout to css for Shiny
3 | #'
4 | #' This simply wraps the output of `to_css()` in a `style` tag and escapes HTML
5 | #' characters to simplify using in Shiny. Most of the time you'll want to use
6 | #' \code{\link{grid_page}} or \code{\link{grid_container}} instead of manually
7 | #' adding this css though.
8 | #'
9 | #' @seealso \code{\link{to_css}}, \code{\link{grid_page}}, \code{\link{grid_container}}
10 | #' @inheritParams grid_container
11 | #' @inheritDotParams to_css -layout
12 | #'
13 | #' @return Character string of css used to setup grid layout and place elements
14 | #' (referenced by id) into correct locations
15 | #'
16 | #' @keywords internal
17 | #'
18 | #' @examples
19 | #' # Only run these examples in interactive R sessions
20 | #' if (interactive()) {
21 | #' library(shiny)
22 | #' my_layout <- "
23 | #' | | | |
24 | #' |------|--------|---------|
25 | #' |2rem |200px |1fr |
26 | #' |100px |header |header |
27 | #' |500px |sidebar |distPlot |"
28 | #'
29 | #' # The classic Geyser app with grid layout
30 | #' shinyApp(
31 | #' ui = fluidPage(
32 | #' use_gridlayout_shiny(my_layout, "#app-container"),
33 | #' div(
34 | #' id = "app-container",
35 | #' div(
36 | #' style = "grid-area: header;",
37 | #' h2(id = "app-title", "Old Faithful Geyser Data")
38 | #' ),
39 | #' div(
40 | #' style = "grid-area: sidebar;",
41 | #' sliderInput("bins", "Number of bins:",
42 | #' min = 1, max = 50, value = 30
43 | #' )
44 | #' ),
45 | #' div(
46 | #' style = "grid-area:distPlot",
47 | #' plotOutput("distPlot", height = "100%")
48 | #' )
49 | #' )
50 | #' ),
51 | #' server = function(input, output) {
52 | #' output$distPlot <- renderPlot({
53 | #' x <- faithful[, 2]
54 | #' bins <- seq(min(x), max(x), length.out = input$bins + 1)
55 | #' hist(x, breaks = bins, col = "darkgray", border = "white")
56 | #' })
57 | #' }
58 | #' )
59 | #'
60 | #' }
61 | use_gridlayout_shiny <- function(layout, ...) {
62 | requireNamespace("htmltools", quietly = TRUE)
63 | layout <- as_gridlayout(layout)
64 | htmltools::tags$head(
65 | htmltools::tags$style(
66 | htmltools::HTML(to_css(layout, ...))
67 | )
68 | )
69 | }
70 |
--------------------------------------------------------------------------------
/R/utils-pipe.R:
--------------------------------------------------------------------------------
1 | #' Pipe operator
2 | #'
3 | #' See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details.
4 | #'
5 | #' @name %>%
6 | #' @rdname pipe
7 | #' @keywords internal
8 | #' @export
9 | #' @importFrom magrittr %>%
10 | #' @usage lhs \%>\% rhs
11 | #' @param lhs A value or the magrittr placeholder.
12 | #' @param rhs A function call using the magrittr semantics.
13 | #' @return The result of calling `rhs(lhs)`.
14 | NULL
15 |
--------------------------------------------------------------------------------
/_pkgdown.yml:
--------------------------------------------------------------------------------
1 | template:
2 | package: quillt
3 |
4 | development:
5 | mode: auto
6 |
7 | home:
8 | strip_header: false
9 |
10 | navbar:
11 | title: ~
12 | type: default
13 | structure:
14 | left: [setting-up, examples, articles, reference]
15 | # right: [examples, github]
16 | components:
17 | home: ~
18 | examples:
19 | text: Layout Examples
20 | href: articles/layout-examples.html
21 | setting-up:
22 | text: Defining a layout
23 | href: articles/defining-a-layout.html
24 | reference:
25 | text: Reference
26 | href: reference/index.html
27 | github:
28 | icon: fab fa-github fa-lg
29 | href: https://github.com/rstudio/gridlayout
30 |
31 | destination: docs
32 |
33 | reference:
34 | - title: Layouts
35 | desc: >
36 | Setup `gridlayout` containers
37 | - contents:
38 | - grid_page
39 | - grid_container
40 | - use_gridlayout_rmd
41 | - title: Content containers
42 | desc: >
43 | Place content on the grid.
44 | - contents:
45 | - starts_with("grid_card")
46 | - grid_card_plot
47 | - grid_nested
48 | - card_plot_output
49 | - grid_place
50 | - title: Working with gridlayout objects
51 | desc: >
52 | Functions for creating, editing, or generating content with `gridlayout` objects. For advanced use-cases.
53 | - contents:
54 | - new_gridlayout
55 | - md_to_gridlayout
56 | - get_elements
57 | - get_element_ids
58 | - to_md
59 | - to_matrix
60 | - to_css
61 |
--------------------------------------------------------------------------------
/docs/ace-1.2.3/mode-plain_text.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/mode/plain_text",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/text_highlight_rules","ace/mode/behaviour"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./text_highlight_rules").TextHighlightRules,o=e("./behaviour").Behaviour,u=function(){this.HighlightRules=s,this.$behaviour=new o};r.inherits(u,i),function(){this.type="text",this.getNextLineIndent=function(e,t,n){return""},this.$id="ace/mode/plain_text"}.call(u.prototype),t.Mode=u})
--------------------------------------------------------------------------------
/docs/ace-1.2.3/mode-r.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/mode/tex_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=function(e){e||(e="text"),this.$rules={start:[{token:"comment",regex:"%.*$"},{token:e,regex:"\\\\[$&%#\\{\\}]"},{token:"keyword",regex:"\\\\(?:documentclass|usepackage|newcounter|setcounter|addtocounter|value|arabic|stepcounter|newenvironment|renewenvironment|ref|vref|eqref|pageref|label|cite[a-zA-Z]*|tag|begin|end|bibitem)\\b",next:"nospell"},{token:"keyword",regex:"\\\\(?:[a-zA-z0-9]+|[^a-zA-z0-9])"},{token:"paren.keyword.operator",regex:"[[({]"},{token:"paren.keyword.operator",regex:"[\\])}]"},{token:e,regex:"\\s+"}],nospell:[{token:"comment",regex:"%.*$",next:"start"},{token:"nospell."+e,regex:"\\\\[$&%#\\{\\}]"},{token:"keyword",regex:"\\\\(?:documentclass|usepackage|newcounter|setcounter|addtocounter|value|arabic|stepcounter|newenvironment|renewenvironment|ref|vref|eqref|pageref|label|cite[a-zA-Z]*|tag|begin|end|bibitem)\\b"},{token:"keyword",regex:"\\\\(?:[a-zA-z0-9]+|[^a-zA-z0-9])",next:"start"},{token:"paren.keyword.operator",regex:"[[({]"},{token:"paren.keyword.operator",regex:"[\\])]"},{token:"paren.keyword.operator",regex:"}",next:"start"},{token:"nospell."+e,regex:"\\s+"},{token:"nospell."+e,regex:"\\w+"}]}};r.inherits(o,s),t.TexHighlightRules=o}),ace.define("ace/mode/r_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules","ace/mode/tex_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=e("./tex_highlight_rules").TexHighlightRules,u=function(){var e=i.arrayToMap("function|if|in|break|next|repeat|else|for|return|switch|while|try|tryCatch|stop|warning|require|library|attach|detach|source|setMethod|setGeneric|setGroupGeneric|setClass".split("|")),t=i.arrayToMap("NULL|NA|TRUE|FALSE|T|F|Inf|NaN|NA_integer_|NA_real_|NA_character_|NA_complex_".split("|"));this.$rules={start:[{token:"comment.sectionhead",regex:"#+(?!').*(?:----|====|####)\\s*$"},{token:"comment",regex:"#+'",next:"rd-start"},{token:"comment",regex:"#.*$"},{token:"string",regex:'["]',next:"qqstring"},{token:"string",regex:"[']",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+[Li]?\\b"},{token:"constant.numeric",regex:"\\d+L\\b"},{token:"constant.numeric",regex:"\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d*)?i?\\b"},{token:"constant.numeric",regex:"\\.\\d+(?:[eE][+\\-]?\\d*)?i?\\b"},{token:"constant.language.boolean",regex:"(?:TRUE|FALSE|T|F)\\b"},{token:"identifier",regex:"`.*?`"},{onMatch:function(n){return e[n]?"keyword":t[n]?"constant.language":n=="..."||n.match(/^\.\.\d+$/)?"variable.language":"identifier"},regex:"[a-zA-Z.][a-zA-Z0-9._]*\\b"},{token:"keyword.operator",regex:"%%|>=|<=|==|!=|\\->|<\\-|\\|\\||&&|=|\\+|\\-|\\*|/|\\^|>|<|!|&|\\||~|\\$|:"},{token:"keyword.operator",regex:"%.*?%"},{token:"paren.keyword.operator",regex:"[[({]"},{token:"paren.keyword.operator",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",regex:".+"}]};var n=(new o("comment")).getRules();for(var r=0;r :first-child");
5 | var i, h, a;
6 | for (i = 0; i < hs.length; i++) {
7 | h = hs[i];
8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6
9 | a = h.attributes;
10 | while (a.length > 0) h.removeAttribute(a[0].name);
11 | }
12 | });
13 |
--------------------------------------------------------------------------------
/docs/articles/alternate-layouts_resizing.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/articles/alternate-layouts_resizing.gif
--------------------------------------------------------------------------------
/docs/articles/alternate-layouts_w1000_h1000.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/articles/alternate-layouts_w1000_h1000.png
--------------------------------------------------------------------------------
/docs/articles/alternate-layouts_w2000_h1000.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/articles/alternate-layouts_w2000_h1000.png
--------------------------------------------------------------------------------
/docs/articles/alternate-layouts_w500_h1000.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/articles/alternate-layouts_w500_h1000.png
--------------------------------------------------------------------------------
/docs/articles/layout-examples_files/header-attrs-2.7.1/header-attrs.js:
--------------------------------------------------------------------------------
1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to
2 | // be compatible with the behavior of Pandoc < 2.8).
3 | document.addEventListener('DOMContentLoaded', function(e) {
4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child");
5 | var i, h, a;
6 | for (i = 0; i < hs.length; i++) {
7 | h = hs[i];
8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6
9 | a = h.attributes;
10 | while (a.length > 0) h.removeAttribute(a[0].name);
11 | }
12 | });
13 |
--------------------------------------------------------------------------------
/docs/articles/layout-examples_focal_chart_side.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/articles/layout-examples_focal_chart_side.png
--------------------------------------------------------------------------------
/docs/articles/layout-examples_focal_chart_top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/articles/layout-examples_focal_chart_top.png
--------------------------------------------------------------------------------
/docs/articles/layout-examples_four_panel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/articles/layout-examples_four_panel.png
--------------------------------------------------------------------------------
/docs/articles/layout-examples_scrolling_stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/articles/layout-examples_scrolling_stack.png
--------------------------------------------------------------------------------
/docs/articles/layout-examples_stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/articles/layout-examples_stack.png
--------------------------------------------------------------------------------
/docs/articles/use_gridlayout_rmd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/articles/use_gridlayout_rmd.png
--------------------------------------------------------------------------------
/docs/articles/use_gridlayout_rmd_base.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/articles/use_gridlayout_rmd_base.png
--------------------------------------------------------------------------------
/docs/articles/use_gridlayout_rmd_extra_child_styles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/articles/use_gridlayout_rmd_extra_child_styles.png
--------------------------------------------------------------------------------
/docs/articles/use_gridlayout_rmd_only_grid_panel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/articles/use_gridlayout_rmd_only_grid_panel.png
--------------------------------------------------------------------------------
/docs/articles/using_with_rmd_files/header-attrs-2.7.1/header-attrs.js:
--------------------------------------------------------------------------------
1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to
2 | // be compatible with the behavior of Pandoc < 2.8).
3 | document.addEventListener('DOMContentLoaded', function(e) {
4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child");
5 | var i, h, a;
6 | for (i = 0; i < hs.length; i++) {
7 | h = hs[i];
8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6
9 | a = h.attributes;
10 | while (a.length > 0) h.removeAttribute(a[0].name);
11 | }
12 | });
13 |
--------------------------------------------------------------------------------
/docs/bootstrap-toc.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/)
3 | * Copyright 2015 Aidan Feldman
4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */
5 |
6 | /* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */
7 |
8 | /* All levels of nav */
9 | nav[data-toggle='toc'] .nav > li > a {
10 | display: block;
11 | padding: 4px 20px;
12 | font-size: 13px;
13 | font-weight: 500;
14 | color: #767676;
15 | }
16 | nav[data-toggle='toc'] .nav > li > a:hover,
17 | nav[data-toggle='toc'] .nav > li > a:focus {
18 | padding-left: 19px;
19 | color: #563d7c;
20 | text-decoration: none;
21 | background-color: transparent;
22 | border-left: 1px solid #563d7c;
23 | }
24 | nav[data-toggle='toc'] .nav > .active > a,
25 | nav[data-toggle='toc'] .nav > .active:hover > a,
26 | nav[data-toggle='toc'] .nav > .active:focus > a {
27 | padding-left: 18px;
28 | font-weight: bold;
29 | color: #563d7c;
30 | background-color: transparent;
31 | border-left: 2px solid #563d7c;
32 | }
33 |
34 | /* Nav: second level (shown on .active) */
35 | nav[data-toggle='toc'] .nav .nav {
36 | display: none; /* Hide by default, but at >768px, show it */
37 | padding-bottom: 10px;
38 | }
39 | nav[data-toggle='toc'] .nav .nav > li > a {
40 | padding-top: 1px;
41 | padding-bottom: 1px;
42 | padding-left: 30px;
43 | font-size: 12px;
44 | font-weight: normal;
45 | }
46 | nav[data-toggle='toc'] .nav .nav > li > a:hover,
47 | nav[data-toggle='toc'] .nav .nav > li > a:focus {
48 | padding-left: 29px;
49 | }
50 | nav[data-toggle='toc'] .nav .nav > .active > a,
51 | nav[data-toggle='toc'] .nav .nav > .active:hover > a,
52 | nav[data-toggle='toc'] .nav .nav > .active:focus > a {
53 | padding-left: 28px;
54 | font-weight: 500;
55 | }
56 |
57 | /* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */
58 | nav[data-toggle='toc'] .nav > .active > ul {
59 | display: block;
60 | }
61 |
--------------------------------------------------------------------------------
/docs/docsearch.js:
--------------------------------------------------------------------------------
1 | $(function() {
2 |
3 | // register a handler to move the focus to the search bar
4 | // upon pressing shift + "/" (i.e. "?")
5 | $(document).on('keydown', function(e) {
6 | if (e.shiftKey && e.keyCode == 191) {
7 | e.preventDefault();
8 | $("#search-input").focus();
9 | }
10 | });
11 |
12 | $(document).ready(function() {
13 | // do keyword highlighting
14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */
15 | var mark = function() {
16 |
17 | var referrer = document.URL ;
18 | var paramKey = "q" ;
19 |
20 | if (referrer.indexOf("?") !== -1) {
21 | var qs = referrer.substr(referrer.indexOf('?') + 1);
22 | var qs_noanchor = qs.split('#')[0];
23 | var qsa = qs_noanchor.split('&');
24 | var keyword = "";
25 |
26 | for (var i = 0; i < qsa.length; i++) {
27 | var currentParam = qsa[i].split('=');
28 |
29 | if (currentParam.length !== 2) {
30 | continue;
31 | }
32 |
33 | if (currentParam[0] == paramKey) {
34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20"));
35 | }
36 | }
37 |
38 | if (keyword !== "") {
39 | $(".contents").unmark({
40 | done: function() {
41 | $(".contents").mark(keyword);
42 | }
43 | });
44 | }
45 | }
46 | };
47 |
48 | mark();
49 | });
50 | });
51 |
52 | /* Search term highlighting ------------------------------*/
53 |
54 | function matchedWords(hit) {
55 | var words = [];
56 |
57 | var hierarchy = hit._highlightResult.hierarchy;
58 | // loop to fetch from lvl0, lvl1, etc.
59 | for (var idx in hierarchy) {
60 | words = words.concat(hierarchy[idx].matchedWords);
61 | }
62 |
63 | var content = hit._highlightResult.content;
64 | if (content) {
65 | words = words.concat(content.matchedWords);
66 | }
67 |
68 | // return unique words
69 | var words_uniq = [...new Set(words)];
70 | return words_uniq;
71 | }
72 |
73 | function updateHitURL(hit) {
74 |
75 | var words = matchedWords(hit);
76 | var url = "";
77 |
78 | if (hit.anchor) {
79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor;
80 | } else {
81 | url = hit.url + '?q=' + escape(words.join(" "));
82 | }
83 |
84 | return url;
85 | }
86 |
--------------------------------------------------------------------------------
/docs/link.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/pkgdown.js:
--------------------------------------------------------------------------------
1 | /* http://gregfranko.com/blog/jquery-best-practices/ */
2 | (function($) {
3 | $(function() {
4 |
5 | $('.navbar-fixed-top').headroom();
6 |
7 | $('body').css('padding-top', $('.navbar').height() + 10);
8 | $(window).resize(function(){
9 | $('body').css('padding-top', $('.navbar').height() + 10);
10 | });
11 |
12 | $('[data-toggle="tooltip"]').tooltip();
13 |
14 | var cur_path = paths(location.pathname);
15 | var links = $("#navbar ul li a");
16 | var max_length = -1;
17 | var pos = -1;
18 | for (var i = 0; i < links.length; i++) {
19 | if (links[i].getAttribute("href") === "#")
20 | continue;
21 | // Ignore external links
22 | if (links[i].host !== location.host)
23 | continue;
24 |
25 | var nav_path = paths(links[i].pathname);
26 |
27 | var length = prefix_length(nav_path, cur_path);
28 | if (length > max_length) {
29 | max_length = length;
30 | pos = i;
31 | }
32 | }
33 |
34 | // Add class to parent , and enclosing if in dropdown
35 | if (pos >= 0) {
36 | var menu_anchor = $(links[pos]);
37 | menu_anchor.parent().addClass("active");
38 | menu_anchor.closest("li.dropdown").addClass("active");
39 | }
40 | });
41 |
42 | function paths(pathname) {
43 | var pieces = pathname.split("/");
44 | pieces.shift(); // always starts with /
45 |
46 | var end = pieces[pieces.length - 1];
47 | if (end === "index.html" || end === "")
48 | pieces.pop();
49 | return(pieces);
50 | }
51 |
52 | // Returns -1 if not found
53 | function prefix_length(needle, haystack) {
54 | if (needle.length > haystack.length)
55 | return(-1);
56 |
57 | // Special case for length-0 haystack, since for loop won't run
58 | if (haystack.length === 0) {
59 | return(needle.length === 0 ? 0 : -1);
60 | }
61 |
62 | for (var i = 0; i < haystack.length; i++) {
63 | if (needle[i] != haystack[i])
64 | return(i);
65 | }
66 |
67 | return(haystack.length);
68 | }
69 |
70 | /* Clipboard --------------------------*/
71 |
72 | function changeTooltipMessage(element, msg) {
73 | var tooltipOriginalTitle=element.getAttribute('data-original-title');
74 | element.setAttribute('data-original-title', msg);
75 | $(element).tooltip('show');
76 | element.setAttribute('data-original-title', tooltipOriginalTitle);
77 | }
78 |
79 | if(ClipboardJS.isSupported()) {
80 | $(document).ready(function() {
81 | var copyButton = "";
82 |
83 | $("div.sourceCode").addClass("hasCopyButton");
84 |
85 | // Insert copy buttons:
86 | $(copyButton).prependTo(".hasCopyButton");
87 |
88 | // Initialize tooltips:
89 | $('.btn-copy-ex').tooltip({container: 'body'});
90 |
91 | // Initialize clipboard:
92 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', {
93 | text: function(trigger) {
94 | return trigger.parentNode.textContent.replace(/\n#>[^\n]*/g, "");
95 | }
96 | });
97 |
98 | clipboardBtnCopies.on('success', function(e) {
99 | changeTooltipMessage(e.trigger, 'Copied!');
100 | e.clearSelection();
101 | });
102 |
103 | clipboardBtnCopies.on('error', function() {
104 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy');
105 | });
106 | });
107 | }
108 | })(window.jQuery || window.$)
109 |
--------------------------------------------------------------------------------
/docs/pkgdown.yml:
--------------------------------------------------------------------------------
1 | pandoc: 2.19.2
2 | pkgdown: 2.0.5
3 | pkgdown_sha: ~
4 | articles:
5 | alternate-layouts: alternate-layouts.html
6 | defining-a-layout: defining-a-layout.html
7 | layout-examples: layout-examples.html
8 | using_with_rmd: using_with_rmd.html
9 | last_built: 2023-02-28T15:43Z
10 |
11 |
--------------------------------------------------------------------------------
/docs/reference/Rplot001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/reference/Rplot001.png
--------------------------------------------------------------------------------
/docs/reference/figures/basic_markdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/reference/figures/basic_markdown.png
--------------------------------------------------------------------------------
/docs/reference/figures/geyser_demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/reference/figures/geyser_demo.png
--------------------------------------------------------------------------------
/docs/reference/figures/geyser_w_grided.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/reference/figures/geyser_w_grided.png
--------------------------------------------------------------------------------
/docs/reference/figures/grided_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/reference/figures/grided_default.png
--------------------------------------------------------------------------------
/docs/reference/figures/lifecycle-archived.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/reference/figures/lifecycle-defunct.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/reference/figures/lifecycle-deprecated.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/reference/figures/lifecycle-experimental.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/reference/figures/lifecycle-maturing.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/reference/figures/lifecycle-questioning.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/reference/figures/lifecycle-stable.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/reference/figures/lifecycle-superseded.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/reference/figures/nested_demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/reference/figures/nested_demo.png
--------------------------------------------------------------------------------
/docs/rmarkdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/docs/rmarkdown.png
--------------------------------------------------------------------------------
/docs/sitemap.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | /404.html
5 |
6 |
7 | /LICENSE-text.html
8 |
9 |
10 | /LICENSE.html
11 |
12 |
13 | /articles/alternate-layouts.html
14 |
15 |
16 | /articles/defining-a-layout.html
17 |
18 |
19 | /articles/index.html
20 |
21 |
22 | /articles/layout-examples.html
23 |
24 |
25 | /articles/using_with_rmd.html
26 |
27 |
28 | /authors.html
29 |
30 |
31 | /index.html
32 |
33 |
34 | /news/index.html
35 |
36 |
37 | /reference/add_alternate_layout.gridlayout.html
38 |
39 |
40 | /reference/add_alternate_layout.html
41 |
42 |
43 | /reference/build_css_rule.html
44 |
45 |
46 | /reference/card_plot_output.html
47 |
48 |
49 | /reference/flex_stack.html
50 |
51 |
52 | /reference/get_element_ids.html
53 |
54 |
55 | /reference/get_elements.html
56 |
57 |
58 | /reference/grid_card.html
59 |
60 |
61 | /reference/grid_card_old.html
62 |
63 |
64 | /reference/grid_card_plot.html
65 |
66 |
67 | /reference/grid_card_text.html
68 |
69 |
70 | /reference/grid_container.html
71 |
72 |
73 | /reference/grid_nested.html
74 |
75 |
76 | /reference/grid_page.html
77 |
78 |
79 | /reference/grid_panel.html
80 |
81 |
82 | /reference/grid_panel_nested.html
83 |
84 |
85 | /reference/grid_panel_plot.html
86 |
87 |
88 | /reference/grid_panel_stack.html
89 |
90 |
91 | /reference/grid_panel_text.html
92 |
93 |
94 | /reference/grid_place.html
95 |
96 |
97 | /reference/grid_plot.html
98 |
99 |
100 | /reference/grided_create_new_app.html
101 |
102 |
103 | /reference/grided_edit_existing_layout.html
104 |
105 |
106 | /reference/gridlayout-package.html
107 |
108 |
109 | /reference/index.html
110 |
111 |
112 | /reference/make_bg_class.html
113 |
114 |
115 | /reference/md_to_gridlayout.html
116 |
117 |
118 | /reference/nested_grid_panel.html
119 |
120 |
121 | /reference/new_gridlayout.html
122 |
123 |
124 | /reference/pipe.html
125 |
126 |
127 | /reference/run_with_grided.html
128 |
129 |
130 | /reference/text_panel.html
131 |
132 |
133 | /reference/title_panel.html
134 |
135 |
136 | /reference/to_app_template.html
137 |
138 |
139 | /reference/to_css.html
140 |
141 |
142 | /reference/to_matrix.html
143 |
144 |
145 | /reference/to_md.html
146 |
147 |
148 | /reference/use_gridlayout_rmd.html
149 |
150 |
151 | /reference/use_gridlayout_shiny.html
152 |
153 |
154 | /reference/vertical_stack_panel.html
155 |
156 |
157 |
--------------------------------------------------------------------------------
/docs/snippets/snippets.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | function loadSnippet(snippet, mode) {
4 | mode = mode || "markdown";
5 | $("#" + snippet).addClass("snippet");
6 | var editor = ace.edit(snippet);
7 | editor.setHighlightActiveLine(false);
8 | editor.setShowPrintMargin(false);
9 | editor.setReadOnly(true);
10 | editor.setShowFoldWidgets(false);
11 | editor.renderer.setDisplayIndentGuides(false);
12 | editor.setTheme("ace/theme/textmate");
13 | editor.$blockScrolling = Infinity;
14 | editor.session.setMode("ace/mode/" + mode);
15 | editor.session.getSelection().clearSelection();
16 |
17 | $.get("snippets/" + snippet + ".md", function(data) {
18 | editor.setValue(data, -1);
19 | editor.setOptions({
20 | maxLines: editor.session.getLength()
21 | });
22 | });
23 | }
24 |
--------------------------------------------------------------------------------
/docs/tidyverse-2.css:
--------------------------------------------------------------------------------
1 | body {font-size: 16px;}
2 | h1 {font-size: 40px;}
3 | h2 {font-size: 30px;}
4 | h3 {font-size: 23px;}
5 |
6 | .contents .page-header {
7 | margin-top: 10px;
8 | }
9 |
10 | /* reduce h3 margin for proper nesting under h2 */
11 | .contents h3 {margin-top: -60px}
12 |
13 | .ref-arguments th {vertical-align: top;}
14 |
15 | /* navbar ----------------------------------------------- */
16 |
17 | .navbar .info {
18 | float: left;
19 | height: 50px;
20 | width: 140px;
21 | font-size: 80%;
22 | position: relative;
23 | margin-left: 5px;
24 | }
25 | .navbar .info .partof {
26 | position: absolute;
27 | top: 0;
28 | }
29 | .navbar .info .version {
30 | position: absolute;
31 | bottom: 0;
32 | }
33 | .navbar .info .version-danger {
34 | font-weight: bold;
35 | color: orange;
36 | }
37 |
38 | .navbar-form {
39 | margin-top: 3px;
40 | margin-bottom: 0;
41 | }
42 |
43 | .navbar-toggle {
44 | margin-top: 8px;
45 | margin-bottom: 5px;
46 | }
47 |
48 | .navbar-nav li a {
49 | padding-bottom: 10px;
50 | }
51 | .navbar-default .navbar-nav > .active > a,
52 | .navbar-default .navbar-nav > .active > a:hover,
53 | .navbar-default .navbar-nav > .active > a:focus {
54 | background-color: #eee;
55 | border-radius: 3px;
56 | }
57 |
58 | /* syntax highlighting ----------------------------------- */
59 |
60 | .co {
61 | color: #333;
62 | }
63 |
64 | /* footer ------------------------------------------------ */
65 |
66 | footer {
67 | margin-top: 45px;
68 | padding: 35px 0 36px;
69 | border-top: 1px solid #e5e5e5;
70 |
71 | display: flex;
72 | color: #666;
73 | }
74 | footer p {
75 | margin-bottom: 0;
76 | }
77 | footer .tidyverse {
78 | flex: 1;
79 | margin-right: 1em;
80 | }
81 | footer .author {
82 | flex: 1;
83 | text-align: right;
84 | margin-left: 1em;
85 | }
86 |
87 | /* sidebar ------------------------------------------------ */
88 |
89 | #sidebar h2 {
90 | font-size: 1.6em;
91 | margin-top: 1em;
92 | margin-bottom: 0.25em;
93 | }
94 |
95 | #sidebar .list-unstyled li {
96 | margin-bottom: 0.5em;
97 | line-height: 1.4;
98 | }
99 |
100 | #sidebar small {
101 | color: #777;
102 | }
103 |
104 | #sidebar .nav {
105 | padding-left: 0px;
106 | list-style-type: none;
107 | color: #5a9ddb;
108 | }
109 |
110 | #sidebar .nav > li {
111 | padding: 10px 0 0px 20px;
112 | display: list-item;
113 | line-height: 20px;
114 | background-image: url(./tocBullet.svg);
115 | background-repeat: no-repeat;
116 | background-size: 16px 280px;
117 | background-position: left 0px;
118 | }
119 |
120 | #sidebar .nav > li.active {
121 | background-position: left -240px;
122 | }
123 |
124 | #sidebar a {
125 | padding: 0px;
126 | color: #5a9ddb;
127 | background-color: transparent;
128 | }
129 |
130 | #sidebar a:hover {
131 | background-color: transparent;
132 | text-decoration: underline;
133 | }
134 |
--------------------------------------------------------------------------------
/gridlayout.Rproj:
--------------------------------------------------------------------------------
1 | Version: 1.0
2 |
3 | RestoreWorkspace: Default
4 | SaveWorkspace: Default
5 | AlwaysSaveHistory: Default
6 |
7 | EnableCodeIndexing: Yes
8 | UseSpacesForTab: Yes
9 | NumSpacesForTab: 2
10 | Encoding: UTF-8
11 |
12 | RnwWeave: Sweave
13 | LaTeX: pdfLaTeX
14 |
15 | AutoAppendNewline: Yes
16 | StripTrailingWhitespace: Yes
17 |
18 | BuildType: Package
19 | PackageUseDevtools: Yes
20 | PackageInstallArgs: --no-multiarch --with-keep.source
21 | PackageRoxygenize: rd,collate,namespace
22 |
--------------------------------------------------------------------------------
/inst/demo_apps/alternate_layouts/README.md:
--------------------------------------------------------------------------------
1 | ## Alternate Layouts
2 |
3 | ### Purpose
4 | Demonstrates how multiple layouts can be declared for a veriety of screen sizes. Shows that these layouts can be used for large screens in addition to just providing mobile views.
5 |
6 | ### Screenshots
7 | - `tests/screenshot-tests/_snaps/demo-apps/alternate-layouts-mobile.png`
8 | - `tests/screenshot-tests/_snaps/demo-apps/alternate-layouts-normal.png`
9 | - `tests/screenshot-tests/_snaps/demo-apps/alternate-layouts-wide.png`
10 |
--------------------------------------------------------------------------------
/inst/demo_apps/alternate_layouts/app.R:
--------------------------------------------------------------------------------
1 | # The geyser app... but in grid!
2 | library(gridlayout)
3 | library(shiny)
4 | library(bslib)
5 |
6 | main_layout <- c(
7 | "10px 200px 1fr ",
8 | "70px header header",
9 | "1fr sidebar plot "
10 | )
11 |
12 | mobile_layout <- c(
13 | "10px 1fr ",
14 | "100px header ",
15 | "250px sidebar",
16 | "400px plot "
17 | )
18 |
19 | big_screen_layout <- c(
20 | "10px 250px 250px 1fr ",
21 | "1fr header sidebar plot"
22 | )
23 |
24 | my_layout <- new_gridlayout(
25 | main_layout,
26 | alternate_layouts = list(
27 | list(
28 | layout = mobile_layout,
29 | width_bounds = c(max = 600)
30 | ),
31 | list(
32 | layout = big_screen_layout,
33 | width_bounds = c(min = 1600)
34 | )
35 | )
36 | )
37 |
38 |
39 | # The classic Geyser app with grid layout
40 | shinyApp(
41 | ui = grid_page(
42 | layout = my_layout,
43 | theme = bs_theme(),
44 | grid_card_text("header", "Geysers!"),
45 | grid_card(
46 | "sidebar",
47 | card_header("Settings"),
48 | sliderInput("bins","Number of bins:", min = 1, max = 50, value = 30, width = "100%")
49 | ),
50 | grid_card(
51 | "plot",
52 | card_body(
53 | plotOutput("distPlot")
54 | )
55 | )
56 | ),
57 | server = function(input, output) {
58 | output$distPlot <- renderPlot({
59 | x <- faithful[, 2]
60 | bins <- seq(min(x), max(x), length.out = input$bins + 1)
61 | hist(x, breaks = bins, col = 'darkgray', border = 'white')
62 | })
63 | }
64 | )
65 |
--------------------------------------------------------------------------------
/inst/demo_apps/alternate_layouts/tests/testthat.R:
--------------------------------------------------------------------------------
1 | shinytest2::test_app()
2 |
--------------------------------------------------------------------------------
/inst/demo_apps/alternate_layouts/tests/testthat/_snaps/mac-4.1/shinytest2/alternate_layouts-001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/inst/demo_apps/alternate_layouts/tests/testthat/_snaps/mac-4.1/shinytest2/alternate_layouts-001.png
--------------------------------------------------------------------------------
/inst/demo_apps/alternate_layouts/tests/testthat/_snaps/mac-4.1/shinytest2/alternate_layouts-002.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/inst/demo_apps/alternate_layouts/tests/testthat/_snaps/mac-4.1/shinytest2/alternate_layouts-002.png
--------------------------------------------------------------------------------
/inst/demo_apps/alternate_layouts/tests/testthat/_snaps/mac-4.1/shinytest2/alternate_layouts-003.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/inst/demo_apps/alternate_layouts/tests/testthat/_snaps/mac-4.1/shinytest2/alternate_layouts-003.png
--------------------------------------------------------------------------------
/inst/demo_apps/alternate_layouts/tests/testthat/_snaps/mac-4.2/shinytest2/alternate_layouts-001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/inst/demo_apps/alternate_layouts/tests/testthat/_snaps/mac-4.2/shinytest2/alternate_layouts-001.png
--------------------------------------------------------------------------------
/inst/demo_apps/alternate_layouts/tests/testthat/_snaps/mac-4.2/shinytest2/alternate_layouts-002.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/inst/demo_apps/alternate_layouts/tests/testthat/_snaps/mac-4.2/shinytest2/alternate_layouts-002.png
--------------------------------------------------------------------------------
/inst/demo_apps/alternate_layouts/tests/testthat/_snaps/mac-4.2/shinytest2/alternate_layouts-003.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/inst/demo_apps/alternate_layouts/tests/testthat/_snaps/mac-4.2/shinytest2/alternate_layouts-003.png
--------------------------------------------------------------------------------
/inst/demo_apps/alternate_layouts/tests/testthat/setup.R:
--------------------------------------------------------------------------------
1 | # Load application support files into testing environment
2 | shinytest2::load_app_env()
3 |
--------------------------------------------------------------------------------
/inst/demo_apps/alternate_layouts/tests/testthat/test-shinytest2.R:
--------------------------------------------------------------------------------
1 | library(shinytest2)
2 |
3 | test_that("{shinytest2} recording: alternate_layouts", {
4 | app <- AppDriver$new(variant = platform_variant(), name = "alternate_layouts",
5 | height = 2024, width = 1619)
6 | app$expect_screenshot()
7 | app$set_window_size(width = 1348, height = 2024)
8 | app$expect_screenshot()
9 | app$set_window_size(width = 575, height = 2024)
10 | app$expect_screenshot()
11 | })
12 |
--------------------------------------------------------------------------------
/inst/demo_apps/geyser/README.md:
--------------------------------------------------------------------------------
1 | ## Geyser app
2 |
3 | ### Purpose
4 | This is a kind-of "Minimum viable example", where we take the classic geyser app and recreate it using `gridlayout::grid_page()`
5 |
6 | ### Screenshots
7 | - `tests/screenshot-tests/_snaps/demo-apps/geyser-app.png`
8 |
--------------------------------------------------------------------------------
/inst/demo_apps/geyser/app.R:
--------------------------------------------------------------------------------
1 | # The geyser app... but in grid!
2 |
3 | library(gridlayout)
4 | library(shiny)
5 | library(bslib)
6 |
7 | shinyApp(
8 | ui = grid_page(
9 | layout = c(
10 | "header header",
11 | "sidebar distPlot"
12 | ),
13 | row_sizes = c("50px", "1fr"),
14 | col_sizes = c("200px", "1fr"),
15 | grid_card_text("header", "This is my header", is_title = TRUE),
16 | grid_card(
17 | "sidebar",
18 | card_header("Settings"),
19 | sliderInput("bins","Number of bins:", 1, 50, 30, width = "100%")
20 | ),
21 | grid_card_plot("distPlot")
22 | ),
23 | server = function(input, output) {
24 | output$distPlot <- renderPlot({
25 | x <- faithful[, 2]
26 | bins <- seq(min(x), max(x), length.out = input$bins + 1)
27 | hist(x, breaks = bins, col = 'darkgray', border = 'white')
28 | })
29 | }
30 | )
31 |
--------------------------------------------------------------------------------
/inst/demo_apps/nested_grids/README.md:
--------------------------------------------------------------------------------
1 | ## Nested Grid Layouts
2 |
3 | ### Purpose
4 |
5 | Shows how you can nest a grid layout within another using the `grid_container()` UI function. The app has two identical nested grids, sitting in basic grid_card and the other wrapped in a `grid_card()` call with a title. They both should sit nicely contained and not overflow their bounds.
6 |
7 | ### Screenshots
8 |
9 | - `tests/screenshot-tests/_snaps/demo-apps/nested-app.png`
10 |
--------------------------------------------------------------------------------
/inst/demo_apps/nested_grids/app.R:
--------------------------------------------------------------------------------
1 | # Demonstrating the ability to nest grid layouts within other gridlayouts
2 | library(gridlayout)
3 | library(shiny)
4 | library(bslib)
5 |
6 | ui <- grid_page(
7 | layout = c(
8 | " 250px 1fr ",
9 | "50px header header",
10 | "1fr sidebar plots "
11 | ),
12 | grid_card_text("header", "This is my header"),
13 | grid_card(
14 | "sidebar",
15 | card_header("Settings"),
16 | sliderInput("bins", "Number of bins:", min = 1, max = 50, value = 30, width = "100%")
17 | ),
18 | grid_nested(
19 | "plots",
20 | title = "Plots - in technicolor",
21 | layout = c(
22 | "distPlot distPlot distPlot",
23 | "redPlot bluePlot greenPlot"
24 | ),
25 | grid_card_plot("distPlot"),
26 | grid_card_plot("redPlot"),
27 | grid_card_plot("bluePlot"),
28 | grid_card_plot("greenPlot")
29 | )
30 | )
31 |
32 |
33 | drawHist <- function(nbins, color) {
34 | x <- faithful[, 2]
35 | bins <- seq(min(x), max(x), length.out = nbins + 1)
36 | hist(x, breaks = bins, col = color, border = "white")
37 | }
38 |
39 | server <- function(input, output) {
40 | output$distPlot <- renderPlot(drawHist(input$bins, "darkgray"))
41 | output$redPlot <- renderPlot(drawHist(input$bins, "orangered"))
42 | output$bluePlot <- renderPlot(drawHist(input$bins, "steelblue"))
43 | output$greenPlot <- renderPlot(drawHist(input$bins, "forestgreen"))
44 | }
45 |
46 | shinyApp(ui, server)
47 |
48 |
--------------------------------------------------------------------------------
/inst/demo_apps/nested_grids/tests/testthat.R:
--------------------------------------------------------------------------------
1 | shinytest2::test_app()
2 |
--------------------------------------------------------------------------------
/inst/demo_apps/nested_grids/tests/testthat/_snaps/mac-4.1/shinytest2/nested_grids-001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/inst/demo_apps/nested_grids/tests/testthat/_snaps/mac-4.1/shinytest2/nested_grids-001.png
--------------------------------------------------------------------------------
/inst/demo_apps/nested_grids/tests/testthat/_snaps/mac-4.2/shinytest2/nested_grids-001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/inst/demo_apps/nested_grids/tests/testthat/_snaps/mac-4.2/shinytest2/nested_grids-001.png
--------------------------------------------------------------------------------
/inst/demo_apps/nested_grids/tests/testthat/setup.R:
--------------------------------------------------------------------------------
1 | # Load application support files into testing environment
2 | shinytest2::load_app_env()
3 |
--------------------------------------------------------------------------------
/inst/demo_apps/nested_grids/tests/testthat/test-shinytest2.R:
--------------------------------------------------------------------------------
1 | library(shinytest2)
2 |
3 | test_that("{shinytest2} recording: nested_grids", {
4 | app <- AppDriver$new(variant = platform_variant(), name = "nested_grids", height = 1470,
5 | width = 1684)
6 | app$expect_screenshot()
7 | })
8 |
--------------------------------------------------------------------------------
/inst/demo_apps/recursive_nesting/app.R:
--------------------------------------------------------------------------------
1 | library(gridlayout)
2 | library(shiny)
3 | library(fontawesome)
4 |
5 | max_depth <- 2
6 |
7 | emoji_panel <- function(area, emoji){
8 | grid_card_text(
9 | area = area,
10 | content = emoji,
11 | alignment = "center"
12 | )
13 | }
14 |
15 | make_nested_panels <- function(level = 0) {
16 |
17 | is_nested <- level > 0
18 |
19 | container_fn <- if (is_nested) grid_nested else grid_page
20 |
21 | container_fn(
22 | layout = new_gridlayout(
23 | c(
24 | "top top right",
25 | "left nested right",
26 | "left bottom bottom"
27 | ),
28 | row_sizes = c("1fr", "5fr", "1fr"),
29 | col_sizes = c("1fr", "5fr", "1fr"),
30 | gap_size = "30px"
31 | ),
32 | emoji_panel("top", "↓"),
33 | emoji_panel("bottom", "↑"),
34 | emoji_panel("left", "→"),
35 | emoji_panel("right", "←"),
36 | if(level < max_depth) make_nested_panels(level + 1) else emoji_panel("nested", "🐢"),
37 | area = if(is_nested) "nested"
38 | )
39 | }
40 |
41 | shinyApp(
42 | ui = make_nested_panels(),
43 | server = function(input, output) {}
44 | )
45 |
--------------------------------------------------------------------------------
/inst/demo_apps/recursive_nesting/tests/testthat.R:
--------------------------------------------------------------------------------
1 | shinytest2::test_app()
2 |
--------------------------------------------------------------------------------
/inst/demo_apps/recursive_nesting/tests/testthat/_snaps/mac-4.1/shinytest2/recursive_nesting-001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/inst/demo_apps/recursive_nesting/tests/testthat/_snaps/mac-4.1/shinytest2/recursive_nesting-001.png
--------------------------------------------------------------------------------
/inst/demo_apps/recursive_nesting/tests/testthat/_snaps/mac-4.2/shinytest2/recursive_nesting-001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/inst/demo_apps/recursive_nesting/tests/testthat/_snaps/mac-4.2/shinytest2/recursive_nesting-001.png
--------------------------------------------------------------------------------
/inst/demo_apps/recursive_nesting/tests/testthat/setup.R:
--------------------------------------------------------------------------------
1 | # Load application support files into testing environment
2 | shinytest2::load_app_env()
3 |
--------------------------------------------------------------------------------
/inst/demo_apps/recursive_nesting/tests/testthat/test-shinytest2.R:
--------------------------------------------------------------------------------
1 | library(shinytest2)
2 |
3 | test_that("{shinytest2} recording: recursive_nesting", {
4 | app <- AppDriver$new(variant = platform_variant(), name = "recursive_nesting",
5 | height = 1121, width = 1126)
6 | app$expect_screenshot()
7 | })
8 |
--------------------------------------------------------------------------------
/inst/demo_apps/rmarkdown_demo/README.md:
--------------------------------------------------------------------------------
1 | ## Gridlayout in RMarkdown
2 |
3 | ### Purpose
4 |
5 | A simple RMarkdown document that uses the function `gridlayout::use_gridlayout_rmd()` to allow the user to define a gridlayout using a chunk of type `gridlayout`.
6 |
7 | The main article of interest here is `grid_markdown.Rmd` which is self-contained and should knit as normal.
8 |
9 | `grid_markdown_options.Rmd` is a parameterized version of `grid_markdown.Rmd` that is used to generate the vignette `vignettes/using_with_rmd.Rmd`.
10 |
11 | `rmd_layout_editing.Rmd` is a test file for developing the `grided` layout editor. It can be ignored.
12 |
13 | ### Screenshots
14 |
15 | - For `grid_markdown.Rmd`
16 | - `tests/screenshot-tests/_snaps/demo-apps/rmarkdown-doc.png`
17 | - For `grid_markdown_options.Rmd`
18 | - `vignettes/use_gridlayout_rmd_base.png`
19 | - `vignettes/use_gridlayout_rmd_extra_child_styles.png`
20 | - `vignettes/use_gridlayout_rmd_only_grid_card.png`
21 |
--------------------------------------------------------------------------------
/inst/demo_apps/rmarkdown_demo/grid_markdown.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "`gridlayout` in Rmarkdown"
3 | author: "Nick Strayer"
4 | date: "3/9/2021"
5 | output:
6 | html_document:
7 | theme:
8 | version: 5
9 | ---
10 |
11 | ```{r setup, include=FALSE}
12 | library(gridlayout)
13 |
14 | knitr::opts_chunk$set(echo = TRUE)
15 |
16 | use_gridlayout_rmd()
17 | ```
18 |
19 | ```{css echo=FALSE}
20 | .section {
21 | outline: 2px solid silver;
22 | padding: 10px;
23 | }
24 | ```
25 |
26 |
27 | # main {.no-header}
28 |
29 | Main content!
30 |
31 | ```{gridlayout}
32 | | | | |
33 | |------|--------|---------|
34 | | |200px |1fr |
35 | |170px |header |header |
36 | |1fr |sidebar |main |
37 | |120px |footer |footer |
38 | ```
39 |
40 |
41 | # Sidebar
42 |
43 | Here is some content for the sidebar
44 |
45 | # Footer
46 |
47 | Anything you want could go in the footer.
48 |
--------------------------------------------------------------------------------
/inst/demo_apps/rmarkdown_demo/grid_markdown_options.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "`gridlayout` in Rmarkdown"
3 | author: "Nick Strayer"
4 | date: "3/9/2021"
5 | output: html_document
6 | params:
7 | mode: base
8 | ---
9 |
10 | ```{r setup, include=FALSE}
11 | library(gridlayout)
12 |
13 | knitr::opts_chunk$set(echo = TRUE)
14 | use_gridlayout_rmd()
15 | ```
16 |
17 | ## Main
18 |
19 | ```{gridlayout}
20 | | | | |
21 | |------|--------|---------|
22 | |2rem |200px |1fr |
23 | |150px |header |header |
24 | |1fr |sidebar |main |
25 | |120px |footer |footer |
26 | ```
27 |
28 |
29 | ## Sidebar
30 |
31 | Here is some content for the sidebar
32 |
33 | ## Footer
34 |
35 | Anything you want could go in the footer.
36 |
--------------------------------------------------------------------------------
/inst/demo_apps/simple/README.md:
--------------------------------------------------------------------------------
1 | ## Geyser app
2 |
3 | ### Purpose
4 | This is a kind-of "Minimum viable example", where we take the classic geyser app and recreate it using `gridlayout::grid_page()`
5 |
6 | ### Screenshots
7 | - `tests/screenshot-tests/_snaps/demo-apps/geyser-app.png`
8 |
--------------------------------------------------------------------------------
/inst/demo_apps/simple/app.R:
--------------------------------------------------------------------------------
1 | # Experiment with how little we can do but still get layout
2 |
3 | # pak::pkg_install('rstudio/bslib@joe/feature/cards')
4 | # pak::pkg_install('rstudio/bslib')
5 | library(gridlayout)
6 | library(shiny)
7 | library(bslib)
8 |
9 | shinyApp(
10 | ui = grid_page(
11 | layout = c("A B B"),
12 | grid_place(
13 | "A",
14 | sliderInput("bins","Number of bins:", min = 1, max = 50, value = 30, width = "100%")
15 | ),
16 | grid_place(
17 | "B",
18 | plotOutput("distPlot", height = "100%")
19 | )
20 | ),
21 | server = function(input, output, session) {
22 | output$distPlot <- renderPlot({
23 | x <- faithful[, 2]
24 | bins <- seq(min(x), max(x), length.out = input$bins + 1)
25 | hist(x, breaks = bins, col = 'darkgray', border = 'white')
26 | })
27 | }
28 | )
29 |
--------------------------------------------------------------------------------
/inst/demo_apps/tabset/app.R:
--------------------------------------------------------------------------------
1 | library(gridlayout)
2 | library(shiny)
3 |
4 | ui <- grid_page(
5 | layout = c(
6 | "tabs tabs cookies",
7 | "bottom bottom bottom"
8 | ),
9 | grid_card(
10 | area = "tabs",
11 | tabsetPanel(
12 | tabPanel("Tab 1"),
13 | tabPanel("Tab 2"),
14 | tabPanel("Tab 3")
15 | )),
16 | grid_card_plot(area = "cookies"),
17 | grid_card(area = "bottom", a(href="https://github.com/rstudio/flexdashboard/issues/37", "flexdashboard issue #37"))
18 | )
19 |
20 | shinyApp(
21 | ui = ui,
22 | server = function(input, output) {
23 | output$cookies <- renderPlot({
24 | plot(
25 | x = c(1,3,4,6),
26 | y = c(0,3,2,4),
27 | "b",
28 | main = "Cookies Stolen",
29 | col="steelblue",
30 | xlab = "",
31 | ylab = ""
32 | )
33 | })
34 | }
35 | )
36 |
37 |
38 |
--------------------------------------------------------------------------------
/inst/resources/gridlayout.js:
--------------------------------------------------------------------------------
1 | // Watch for cards being hidden or shown and alert shiny of this
2 | function watch_cards() {
3 | const panel_visibility_map = new Map();
4 | const resizeObserver = new ResizeObserver((entries) => {
5 | for (let entry of entries) {
6 | const el = entry.target;
7 |
8 | const content_height = getComputedStyle(el)
9 | .getPropertyValue("grid-template-rows")
10 | .split(" ")[1];
11 |
12 | // An item is visible if the grid-row for the panel content is not set to 0px
13 | const is_visible = content_height != "0px";
14 |
15 | if (panel_visibility_map.get(el) !== is_visible) {
16 | // Trigger shown or hidden events on all the bound ouputs so
17 | // Shiny knows to update them or not
18 | el.querySelectorAll(".shiny-bound-output").forEach((el) => {
19 | const $el = $(el);
20 | if (is_visible) {
21 | $el.trigger("show");
22 | $el.show();
23 | $el.trigger("shown");
24 | } else {
25 | $el.trigger("hide");
26 | $el.hide();
27 | $el.trigger("hidden");
28 | }
29 | });
30 | panel_visibility_map.set(el, "seen");
31 | }
32 | }
33 | });
34 |
35 | document
36 | .querySelectorAll(".grid_card")
37 | .forEach((el) => resizeObserver.observe(el));
38 | }
39 |
40 | window.onload = function () {
41 | watch_cards();
42 | };
43 |
--------------------------------------------------------------------------------
/inst/resources/gridlayout_rmd_styles.css:
--------------------------------------------------------------------------------
1 | .section.no-header > h1:first-child {
2 | display: none;
3 | }
4 |
5 | .section > h1,
6 | .section > h2,
7 | .section > h3 {
8 | margin: 0;
9 | }
10 |
11 | .section.v_start,
12 | .section.v_center,
13 | .section.v_end,
14 | .section.h_start,
15 | .section.h_center,
16 | .section.h_end {
17 | display: grid;
18 | }
19 |
20 | .section.v_start { align-items: start; }
21 | .section.v_center { align-items: center; }
22 | .section.v_end { align-items: end; }
23 |
24 | .section.h_start { justify-items: start; }
25 | .section.h_center { justify-items: center; }
26 | .section.h_end { justify-items: end; }
27 |
--------------------------------------------------------------------------------
/man/add_alternate_layout.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/add_alternate_layout.R
3 | \name{add_alternate_layout}
4 | \alias{add_alternate_layout}
5 | \title{Add alternate layout options}
6 | \usage{
7 | add_alternate_layout(
8 | layout,
9 | alternate_layout,
10 | width_bounds = NULL,
11 | container_height = NULL
12 | )
13 | }
14 | \arguments{
15 | \item{layout}{Main (or default) layout object}
16 |
17 | \item{alternate_layout}{A \code{gridlayout} object or layout-as-markdown-table
18 | defining layout.}
19 |
20 | \item{width_bounds}{A named vector with at least one element of name \code{min},
21 | or \code{max}. These two values are used to set when the layout occurs. For
22 | instance, \code{c(max = 600)} means the layout will occur up until the page is
23 | wider than \verb{600px}.}
24 |
25 | \item{container_height}{How tall the layout should be. If left as \code{NULL} this
26 | will simply inherit the main layout's height. Often this should be set to
27 | \code{"auto"} to allow mobile user's to scroll. Beware though, you will want to
28 | absolutely size any plot outputs in these cases.}
29 | }
30 | \description{
31 | Adds a layout that will be triggered based upon the size of the viewport.
32 | This is typically used to add a mobile view (or a desktop view if your app is
33 | mobile first.)
34 | }
35 | \keyword{internal}
36 |
--------------------------------------------------------------------------------
/man/build_css_rule.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/to_css.R
3 | \name{build_css_rule}
4 | \alias{build_css_rule}
5 | \title{Build css properties named or unnamed list of property values}
6 | \usage{
7 | build_css_rule(selector, prop_list)
8 | }
9 | \arguments{
10 | \item{selector}{valid css selector to target. E.g. \code{body} or
11 | \code{div.blue_boxes}... For inline styles where no selector is desired use
12 | \code{"inline"}.}
13 |
14 | \item{prop_list}{A list of property-value pairs for additional styles to be
15 | added to each element. Pairs can be given as named elements: e.g.
16 | \code{prop_list = c("background" = "blue")}. See \link[htmltools:css]{htmltools::css} for rules
17 | on formatting.}
18 | }
19 | \value{
20 | A concatenated string of property values to be used inside a css
21 | selector. If the \code{prop_list} is empty, an empty string (\code{""}) is returned
22 | to avoid placing empty css rules on the webpage.
23 | }
24 | \description{
25 | Build css properties named or unnamed list of property values
26 | }
27 | \keyword{internal}
28 |
--------------------------------------------------------------------------------
/man/card_plot_output.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/grid_plot.R
3 | \name{card_plot_output}
4 | \alias{card_plot_output}
5 | \title{Plot output with smart sizing for use inside a \code{grid_card} - Depreciated}
6 | \usage{
7 | card_plot_output(
8 | outputId,
9 | click = NULL,
10 | dblclick = NULL,
11 | hover = NULL,
12 | brush = NULL,
13 | height = NULL,
14 | stretch = TRUE,
15 | ...
16 | )
17 | }
18 | \arguments{
19 | \item{outputId}{output variable to read the plot/image from.}
20 |
21 | \item{click}{This can be \code{NULL} (the default), a string, or an object
22 | created by the \code{\link[shiny:clickOpts]{clickOpts()}} function. If you use a value like
23 | \code{"plot_click"} (or equivalently, \code{clickOpts(id="plot_click")}),
24 | the plot will send coordinates to the server whenever it is clicked, and
25 | the value will be accessible via \code{input$plot_click}. The value will be
26 | a named list with \code{x} and \code{y} elements indicating the mouse
27 | position.}
28 |
29 | \item{dblclick}{This is just like the \code{click} argument, but for
30 | double-click events.}
31 |
32 | \item{hover}{Similar to the \code{click} argument, this can be \code{NULL}
33 | (the default), a string, or an object created by the
34 | \code{\link[shiny:hoverOpts]{hoverOpts()}} function. If you use a value like
35 | \code{"plot_hover"} (or equivalently, \code{hoverOpts(id="plot_hover")}),
36 | the plot will send coordinates to the server pauses on the plot, and the
37 | value will be accessible via \code{input$plot_hover}. The value will be a
38 | named list with \code{x} and \code{y} elements indicating the mouse
39 | position. To control the hover time or hover delay type, you must use
40 | \code{\link[shiny:hoverOpts]{hoverOpts()}}.}
41 |
42 | \item{brush}{Similar to the \code{click} argument, this can be \code{NULL}
43 | (the default), a string, or an object created by the
44 | \code{\link[shiny:brushOpts]{brushOpts()}} function. If you use a value like
45 | \code{"plot_brush"} (or equivalently, \code{brushOpts(id="plot_brush")}),
46 | the plot will allow the user to "brush" in the plotting area, and will send
47 | information about the brushed area to the server, and the value will be
48 | accessible via \code{input$plot_brush}. Brushing means that the user will
49 | be able to draw a rectangle in the plotting area and drag it around. The
50 | value will be a named list with \code{xmin}, \code{xmax}, \code{ymin}, and
51 | \code{ymax} elements indicating the brush area. To control the brush
52 | behavior, use \code{\link[shiny:brushOpts]{brushOpts()}}. Multiple
53 | \code{imageOutput}/\code{plotOutput} calls may share the same \code{id}
54 | value; brushing one image or plot will cause any other brushes with the
55 | same \code{id} to disappear.}
56 |
57 | \item{height}{height in valid css units (see \code{\link[htmltools:validateCssUnit]{htmltools::validateCssUnit()}}
58 | for more details.) Most use-cases will leave this unset and the plot will
59 | fill the card as best it can.}
60 |
61 | \item{stretch}{Set to \code{TRUE} if this \code{card_body} is eager to use any extra
62 | vertical space is available in the card.}
63 |
64 | \item{...}{Named arguments become attributes on the div containing the plot.}
65 | }
66 | \description{
67 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
68 | }
69 | \details{
70 | No longer necessary. Use plain \code{shiny::plotOutput()} wrapped with
71 | \code{bslib::card_body()}.
72 | }
73 | \seealso{
74 | \code{\link[=grid_card_plot]{grid_card_plot()}} for a simpler way of placing just a plot on the
75 | grid
76 | }
77 |
--------------------------------------------------------------------------------
/man/examples/grid_place_app.R:
--------------------------------------------------------------------------------
1 | if (FALSE) {
2 | library(gridlayout)
3 | library(shiny)
4 | library(bslib)
5 |
6 | shinyApp(
7 | ui = grid_page(
8 | layout = c("A B B"),
9 | grid_place(
10 | "A",
11 | sliderInput("bins","Number of bins:", min = 1, max = 50, value = 30, width = "100%")
12 | ),
13 | grid_place(
14 | "B",
15 | plotOutput("distPlot", height = "100%")
16 | )
17 | ),
18 | server = function(input, output, session) {
19 | output$distPlot <- renderPlot({
20 | x <- faithful[, 2]
21 | bins <- seq(min(x), max(x), length.out = input$bins + 1)
22 | hist(x, breaks = bins, col = 'darkgray', border = 'white')
23 | })
24 | }
25 | )
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/man/examples/nested_app.R:
--------------------------------------------------------------------------------
1 | # Demonstrating the ability to nest grid layouts within other gridlayouts
2 | library(gridlayout)
3 | library(shiny)
4 | library(bslib)
5 |
6 | ui <- grid_page(
7 | layout = c(
8 | "header header",
9 | "sidebar plots"
10 | ),
11 | row_sizes = c("50px", "1fr"),
12 | col_sizes = c("250px", "1fr"),
13 | grid_card_text("header", "This is my header"),
14 | grid_card(
15 | "sidebar",
16 | card_header("Settings"),
17 | sliderInput("bins","Number of bins:", 1, 50, 30, width = "100%")
18 | ),
19 | grid_nested(
20 | "plots",
21 | title = "Plots - in technicolor",
22 | layout = c(
23 | "distPlot distPlot distPlot",
24 | "redPlot bluePlot greenPlot"
25 | ),
26 | grid_card_plot("distPlot"),
27 | grid_card_plot("redPlot"),
28 | grid_card_plot("bluePlot"),
29 | grid_card_plot("greenPlot")
30 | )
31 | )
32 |
33 |
34 | drawHist <- function(nbins, color) {
35 | x <- faithful[, 2]
36 | bins <- seq(min(x), max(x), length.out = nbins + 1)
37 | hist(x, breaks = bins, col = color, border = "white")
38 | }
39 |
40 | server <- function(input, output) {
41 | output$distPlot <- renderPlot(drawHist(input$bins, "darkgray"))
42 | output$redPlot <- renderPlot(drawHist(input$bins, "orangered"))
43 | output$bluePlot <- renderPlot(drawHist(input$bins, "steelblue"))
44 | output$greenPlot <- renderPlot(drawHist(input$bins, "forestgreen"))
45 | }
46 |
47 | if(FALSE){
48 | shinyApp(ui, server)
49 | }
50 |
--------------------------------------------------------------------------------
/man/examples/simple_app.R:
--------------------------------------------------------------------------------
1 | if (FALSE) {
2 | library(gridlayout)
3 | library(shiny)
4 | library(bslib)
5 |
6 | shinyApp(
7 | ui = grid_page(
8 | layout = c(
9 | "header header",
10 | "sidebar distPlot"
11 | ),
12 | row_sizes = c("50px", "1fr"),
13 | col_sizes = c("200px", "1fr"),
14 | grid_card_text("header", "This is my header"),
15 | grid_card(
16 | area = "sidebar",
17 | card_header("Settings"),
18 | card_body(
19 | sliderInput("bins", "Number of bins:", 1, 50, 30, width = "100%")
20 | )
21 | ),
22 | grid_card_plot("distPlot")
23 | ),
24 | server = function(input, output) {
25 | output$distPlot <- renderPlot({
26 | x <- faithful[, 2]
27 | bins <- seq(min(x), max(x), length.out = input$bins + 1)
28 | hist(x, breaks = bins, col = 'darkgray', border = 'white')
29 | })
30 | }
31 | )
32 | }
33 |
--------------------------------------------------------------------------------
/man/examples/simple_app_old.R:
--------------------------------------------------------------------------------
1 | if (FALSE) {
2 | library(gridlayout)
3 | library(shiny)
4 | library(bslib)
5 |
6 | shinyApp(
7 | ui = grid_page(
8 | layout = c(
9 | "header header",
10 | "sidebar distPlot"
11 | ),
12 | row_sizes = c("50px", "1fr"),
13 | col_sizes = c("200px", "1fr"),
14 | grid_card_text("header", "This is my header"),
15 | grid_card_old(
16 | "sidebar",
17 | title = "Settings",
18 | sliderInput("bins","Number of bins:", 1, 50, 30, width = "100%")
19 | ),
20 | grid_card_plot("distPlot")
21 | ),
22 | server = function(input, output) {
23 | output$distPlot <- renderPlot({
24 | x <- faithful[, 2]
25 | bins <- seq(min(x), max(x), length.out = input$bins + 1)
26 | hist(x, breaks = bins, col = 'darkgray', border = 'white')
27 | })
28 | }
29 | )
30 | }
31 |
--------------------------------------------------------------------------------
/man/figures/basic_markdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/man/figures/basic_markdown.png
--------------------------------------------------------------------------------
/man/figures/geyser_demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/man/figures/geyser_demo.png
--------------------------------------------------------------------------------
/man/figures/geyser_w_grided.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/man/figures/geyser_w_grided.png
--------------------------------------------------------------------------------
/man/figures/grided_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/man/figures/grided_default.png
--------------------------------------------------------------------------------
/man/figures/lifecycle-archived.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-defunct.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-deprecated.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-experimental.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-maturing.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-questioning.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-stable.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-superseded.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/nested_demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/man/figures/nested_demo.png
--------------------------------------------------------------------------------
/man/flex_stack.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/grid_card_old.R
3 | \name{flex_stack}
4 | \alias{flex_stack}
5 | \title{Div with vertically stacked elements}
6 | \usage{
7 | flex_stack(..., title, collapsible, scrollable, item_gap = "10px")
8 | }
9 | \arguments{
10 | \item{...}{Arguments (typically children) passed to the \code{htmltools::div()}
11 | that contain the card's contents}
12 |
13 | \item{title}{Character string to go across top of panel with label. If left
14 | blank the card contents will take up entire space.}
15 |
16 | \item{collapsible}{Should the card be able to be collapsed (\code{TRUE} or
17 | \code{FALSE})? Gridlayout will only show collapser if the layout allows it
18 | (panel is entirely positioned within "auto" sized rows, and has a title).
19 | Setting this to \code{FALSE} will mean collapsibility of the panel will never be
20 | enabled, regardless of layout.}
21 |
22 | \item{scrollable}{Should scroll-bars be added so content that is larger than
23 | the panel can be seen?}
24 |
25 | \item{item_gap}{How much space should there be between consecutive items?}
26 | }
27 | \value{
28 | Elements from \code{...} wrapped in a \code{shiny::div()} with styles for
29 | vertical stacking applied.
30 | }
31 | \description{
32 | Contain a series of ui elements with each vertically stacked on top of
33 | eachother. Internally uses css flexbox to align items.
34 | }
35 | \seealso{
36 | \link{grid_card}
37 | }
38 | \keyword{internal}
39 |
--------------------------------------------------------------------------------
/man/get_element_ids.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/get_elements.R
3 | \name{get_element_ids}
4 | \alias{get_element_ids}
5 | \title{Get ids of element in \code{gridlayout} object}
6 | \usage{
7 | get_element_ids(x)
8 | }
9 | \arguments{
10 | \item{x}{Object of class \code{"gridlayout"}.}
11 | }
12 | \value{
13 | Character vector of ids of all elements in layout
14 | }
15 | \description{
16 | Get ids of element in \code{gridlayout} object
17 | }
18 | \examples{
19 |
20 | grid_obj <- md_to_gridlayout(
21 | layout_table = "
22 | | |120px |1fr |1fr |
23 | |------|--------|-------|-------|
24 | |100px |header |header |header |
25 | |1fr |sidebar |plot_a |plot_a |
26 | |1fr |sidebar |plot_b |plot_c |"
27 | )
28 |
29 | get_element_ids(grid_obj)
30 | }
31 | \seealso{
32 | \link{get_elements}
33 | }
34 |
--------------------------------------------------------------------------------
/man/get_elements.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/get_elements.R
3 | \name{get_elements}
4 | \alias{get_elements}
5 | \title{Get elements and positions out of a \code{gridlayout} object}
6 | \usage{
7 | get_elements(layout)
8 | }
9 | \arguments{
10 | \item{layout}{Object of class \code{"gridlayout"}}
11 | }
12 | \value{
13 | List of all unique elements in the layout and their \code{id},
14 | \verb{\{start,end\}_row}, and \verb{\{start,end\}_col}. Positions are indexed starting at
15 | 1
16 | }
17 | \description{
18 | Get elements and positions out of a \code{gridlayout} object
19 | }
20 | \examples{
21 | grid_obj <- md_to_gridlayout(
22 | layout_table = "
23 | | |120px |1fr |1fr |
24 | |------|--------|-------|-------|
25 | |100px |header |header |header |
26 | |1fr |sidebar |plot_a |plot_a |
27 | |1fr |sidebar |plot_b |plot_c |"
28 | )
29 |
30 | get_elements(grid_obj)
31 |
32 | }
33 | \seealso{
34 | \link{get_element_ids}
35 | }
36 |
--------------------------------------------------------------------------------
/man/grid_card.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/grid_card.R
3 | \name{grid_card}
4 | \alias{grid_card}
5 | \title{Grid-positioned card element}
6 | \usage{
7 | grid_card(area, ...)
8 | }
9 | \arguments{
10 | \item{area}{Name of grid area, should match an area defined in the layout
11 | section of the wrapping \code{grid_page()} or \code{grid_container()}.}
12 |
13 | \item{...}{
14 | Arguments passed on to \code{\link[bslib:card]{bslib::card}}
15 | \describe{
16 | \item{\code{full_screen}}{If \code{TRUE}, an icon will appear when hovering over the card
17 | body. Clicking the icon expands the card to fit viewport size.}
18 | \item{\code{height}}{Any valid \link[htmltools:validateCssUnit]{CSS unit} (e.g.,
19 | \code{height="200px"}). Doesn't apply when a card is made \code{full_screen}
20 | (in this case, consider setting a \code{height} in \code{\link[bslib:card_body]{card_body()}}).}
21 | \item{\code{max_height,min_height}}{Any valid \link[htmltools:validateCssUnit]{CSS unit} (e.g.,
22 | \code{max_height="200px"}). Doesn't apply when a card is made \code{full_screen}
23 | (in this case, consider setting a \code{max_height} in \code{\link[bslib:card_body]{card_body()}}).}
24 | \item{\code{fill}}{Whether or not to allow the card to grow/shrink to fit a
25 | fillable container with an opinionated height (e.g., \code{page_fillable()}).}
26 | \item{\code{class}}{Additional CSS classes for the returned UI element.}
27 | \item{\code{wrapper}}{A function (which returns a UI element) to call on unnamed
28 | arguments in \code{...} which are not already card item(s) (like
29 | \code{\link[bslib:card_header]{card_header()}}, \code{\link[bslib:card_body]{card_body()}}, etc.). Note that non-card items are grouped
30 | together into one \code{wrapper} call (e.g. given \code{card("a", "b", card_body("c"), "d")}, \code{wrapper} would be called twice, once with \code{"a"} and
31 | \code{"b"} and once with \code{"d"}).}
32 | }}
33 | }
34 | \description{
35 | The standard element for placing elements on the grid in a simple card
36 | container
37 | }
38 | \examples{
39 | if (FALSE) {
40 | library(gridlayout)
41 | library(shiny)
42 | library(bslib)
43 |
44 | shinyApp(
45 | ui = grid_page(
46 | layout = c(
47 | "header header",
48 | "sidebar distPlot"
49 | ),
50 | row_sizes = c("50px", "1fr"),
51 | col_sizes = c("200px", "1fr"),
52 | grid_card_text("header", "This is my header"),
53 | grid_card(
54 | area = "sidebar",
55 | card_header("Settings"),
56 | card_body(
57 | sliderInput("bins", "Number of bins:", 1, 50, 30, width = "100\%")
58 | )
59 | ),
60 | grid_card_plot("distPlot")
61 | ),
62 | server = function(input, output) {
63 | output$distPlot <- renderPlot({
64 | x <- faithful[, 2]
65 | bins <- seq(min(x), max(x), length.out = input$bins + 1)
66 | hist(x, breaks = bins, col = 'darkgray', border = 'white')
67 | })
68 | }
69 | )
70 | }
71 | }
72 | \seealso{
73 | \link[bslib:card]{bslib::card} for underlying function. \link[bslib:card_body]{bslib::card_header},
74 | \link[bslib:card_body]{bslib::card_body}, \link[bslib:card_body]{bslib::card_footer}.
75 | \code{\link[=grid_card_text]{grid_card_text()}} for a card with just text content,
76 | \code{\link[=grid_card_plot]{grid_card_plot()}} for a card with just plot content, \code{\link[=grid_place]{grid_place()}} to
77 | place any tag onto the grid without needing to wrap in a card, and
78 | \code{\link[=card_plot_output]{card_plot_output()}} for including a smart-sized plot within a card.
79 | }
80 |
--------------------------------------------------------------------------------
/man/grid_card_old.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/grid_card_old.R
3 | \name{grid_card_old}
4 | \alias{grid_card_old}
5 | \title{Grid-positioned card element - old version}
6 | \usage{
7 | grid_card_old(
8 | area,
9 | ...,
10 | title = NULL,
11 | scrollable = FALSE,
12 | collapsible = TRUE,
13 | has_border = TRUE,
14 | item_gap = "10px",
15 | class = NULL
16 | )
17 | }
18 | \arguments{
19 | \item{area}{Name of grid area, should match an area defined in the layout
20 | section of the wrapping \code{grid_page()} or \code{grid_container()}.}
21 |
22 | \item{...}{Arguments (typically children) passed to the \code{htmltools::div()}
23 | that contain the card's contents}
24 |
25 | \item{title}{Character string to go across top of panel with label. If left
26 | blank the card contents will take up entire space.}
27 |
28 | \item{scrollable}{Should scroll-bars be added so content that is larger than
29 | the panel can be seen?}
30 |
31 | \item{collapsible}{Should the card be able to be collapsed (\code{TRUE} or
32 | \code{FALSE})? Gridlayout will only show collapser if the layout allows it
33 | (panel is entirely positioned within "auto" sized rows, and has a title).
34 | Setting this to \code{FALSE} will mean collapsibility of the panel will never be
35 | enabled, regardless of layout.}
36 |
37 | \item{has_border}{Should the card be surrounded by a border? Set to \code{FALSE}
38 | to turn off.}
39 |
40 | \item{item_gap}{How much vertical space should there be between children of
41 | card?}
42 |
43 | \item{class}{Additional CSS classes to include on the card div.}
44 | }
45 | \description{
46 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
47 | }
48 | \details{
49 | Note that this version of grid card has been replaced with a newer one based
50 | on \code{bslib::card()}. That is the recomended way of using cards in your layout.
51 | This version is kept for compatibility with old apps while they are switched
52 | to the new interface. The standard element for placing elements on the grid
53 | in a simple card container
54 | }
55 | \examples{
56 | if (FALSE) {
57 | library(gridlayout)
58 | library(shiny)
59 | library(bslib)
60 |
61 | shinyApp(
62 | ui = grid_page(
63 | layout = c(
64 | "header header",
65 | "sidebar distPlot"
66 | ),
67 | row_sizes = c("50px", "1fr"),
68 | col_sizes = c("200px", "1fr"),
69 | grid_card_text("header", "This is my header"),
70 | grid_card_old(
71 | "sidebar",
72 | title = "Settings",
73 | sliderInput("bins","Number of bins:", 1, 50, 30, width = "100\%")
74 | ),
75 | grid_card_plot("distPlot")
76 | ),
77 | server = function(input, output) {
78 | output$distPlot <- renderPlot({
79 | x <- faithful[, 2]
80 | bins <- seq(min(x), max(x), length.out = input$bins + 1)
81 | hist(x, breaks = bins, col = 'darkgray', border = 'white')
82 | })
83 | }
84 | )
85 | }
86 | }
87 | \seealso{
88 | \code{\link[=grid_card_text]{grid_card_text()}} for a card with just text content,
89 | \code{\link[=grid_card_plot]{grid_card_plot()}} for a card with just plot content, \code{\link[=grid_place]{grid_place()}} to
90 | place any tag onto the grid without needing to wrap in a card, and
91 | \code{\link[=card_plot_output]{card_plot_output()}} for including a smart-sized plot within a card.
92 | }
93 |
--------------------------------------------------------------------------------
/man/grid_card_text.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/grid_card_text.R
3 | \name{grid_card_text}
4 | \alias{grid_card_text}
5 | \title{Grid-positioned card with only text}
6 | \usage{
7 | grid_card_text(
8 | area,
9 | content = NULL,
10 | ...,
11 | alignment = "start",
12 | img_height = "55px",
13 | icon = NULL,
14 | wrapping_tag = "h2",
15 | is_title = FALSE
16 | )
17 | }
18 | \arguments{
19 | \item{area}{Name of grid area, should match an area defined in the layout
20 | section of the wrapping \code{grid_page()} or \code{grid_container()}.}
21 |
22 | \item{content}{Whatever you want the title to say. Typically just text but
23 | any tag or tag-list is possible. All will get wrapped in an \code{h3} tag.}
24 |
25 | \item{...}{
26 | Arguments passed on to \code{\link[=grid_card]{grid_card}}
27 | \describe{
28 | \item{\code{}}{}
29 | }}
30 |
31 | \item{alignment}{Horizontal alignment of text. Typical options include
32 | \verb{start", "center", "end"}. For full list of options, see the \href{https://developer.mozilla.org/en-US/docs/Web/CSS/align-items}{css-spec for \code{align-items}.}}
33 |
34 | \item{img_height}{If the passed icon is a path to an image, how tall should
35 | that image be rendered (preserves aspect ratio.)}
36 |
37 | \item{icon}{Optional icon/image for left of text. Supports image locations
38 | (those ending in \verb{.png, .jpg, .jpeg} or \code{.svg}), ids of font-awesome icons
39 | (i.e. that works with \verb{fontawesome::fa(icon)]}, or \code{fontawesome} icons as
40 | returned by \code{\link[fontawesome:fa]{fontawesome::fa()}} (if customization of icon style is
41 | desired.)}
42 |
43 | \item{wrapping_tag}{What tag should the text be wrapped in. Takes either an
44 | \code{htmltools} tag function or the string of a tag accessible via
45 | \code{htmltools::tags[[wrapping_tag]]}.}
46 |
47 | \item{is_title}{Should the text of this panel be passed on as the title of
48 | the page? This will make the text show up in the browser tab or when you
49 | bookmark the app etc..}
50 | }
51 | \description{
52 | Makes a grid_card that contains just text that is vertically centered within
53 | the panel. Useful for app titles or displaying text-based statistics.
54 | }
55 | \examples{
56 |
57 | # Typically you'll just pass a character string to the function
58 | grid_card_text(area = "header", "This is my header")
59 |
60 | # Icons from `fontawesome` can be used:
61 |
62 | # Either with just the id
63 | grid_card_text(area = "header", "Here's my text", icon = "r-project")
64 |
65 | # Or by directly passing the icon object if you want more customization
66 | grid_card_text(
67 | "header",
68 | "Here's my text",
69 | icon = fontawesome::fa("r-project", fill = "steelblue")
70 | )
71 |
72 | # You can also pass arbitrary image locations for the icon
73 | grid_card_text(
74 | "header",
75 | "Here's my text",
76 | icon = "https://cran.r-project.org/Rlogo.svg"
77 | )
78 |
79 | # These images can have their size controlled
80 | grid_card_text(
81 | "header",
82 | "Here's my text",
83 | icon = "https://cran.r-project.org/Rlogo.svg",
84 | img_height = "20px"
85 | )
86 |
87 |
88 | # Commonly you may want to use the text panel text as the title of your app
89 | grid_card_text(area = "header", "My App Name", is_title = TRUE)
90 |
91 | if (FALSE) {
92 | library(gridlayout)
93 | library(shiny)
94 | library(bslib)
95 |
96 | shinyApp(
97 | ui = grid_page(
98 | layout = c(
99 | "header header",
100 | "sidebar distPlot"
101 | ),
102 | row_sizes = c("50px", "1fr"),
103 | col_sizes = c("200px", "1fr"),
104 | grid_card_text("header", "This is my header"),
105 | grid_card(
106 | area = "sidebar",
107 | card_header("Settings"),
108 | card_body(
109 | sliderInput("bins", "Number of bins:", 1, 50, 30, width = "100\%")
110 | )
111 | ),
112 | grid_card_plot("distPlot")
113 | ),
114 | server = function(input, output) {
115 | output$distPlot <- renderPlot({
116 | x <- faithful[, 2]
117 | bins <- seq(min(x), max(x), length.out = input$bins + 1)
118 | hist(x, breaks = bins, col = 'darkgray', border = 'white')
119 | })
120 | }
121 | )
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/man/grid_container.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/grid_container.R
3 | \name{grid_container}
4 | \alias{grid_container}
5 | \title{\code{gridlayout} container for use within other elements}
6 | \usage{
7 | grid_container(
8 | layout,
9 | ...,
10 | id = NULL,
11 | flag_mismatches = TRUE,
12 | row_sizes = NULL,
13 | col_sizes = NULL,
14 | gap_size = NULL,
15 | container_height = NULL
16 | )
17 | }
18 | \arguments{
19 | \item{layout}{Either a markdown table representation (see
20 | \code{\link{md_to_gridlayout}}) or a \code{gridlayout} object defining the
21 | desired layout for your Shiny app.}
22 |
23 | \item{...}{\code{grid_card()} (or similar) arguments that will fill the grid
24 | layout. Note the areas should match the those provided in \code{layout}.}
25 |
26 | \item{id}{ID unique to this container (note that the HTML will be prefixed
27 | with \verb{grid-} to avoid namespace clashes)}
28 |
29 | \item{flag_mismatches}{Should a mismatch between supplied \code{elements} ui
30 | definitions and layout trigger a warning? In advanced cases you may want to
31 | dynamically set your layout and sometimes omit panels.}
32 |
33 | \item{row_sizes}{A character vector of valid css sizes for the height of each
34 | row in your grid as given by the main layout definition. If a single value
35 | is passed, it will be repeated for all columns. If sizes are provided both
36 | here and in the main layout then these sizes will be the ones used.}
37 |
38 | \item{col_sizes}{Same as \code{row_sizes}, but for column widths}
39 |
40 | \item{gap_size}{Valid css sizing for gap to be left between each element in your
41 | grid. Like \code{row_sizes} and \code{col_sizes}, this will win-out over a gap size
42 | provided in the main layout table.}
43 |
44 | \item{container_height}{Valid css unit determining how tall the containing
45 | element should be for this layout. Defaults to \verb{100\%}. Special value of
46 | \code{"viewport"} for full-page height maps to the CSS value of \verb{100vh} if any
47 | relative units (e.g. \code{fr} or \code{auto}) are included in row sizes and \code{auto}
48 | otherwise. Values such as \code{"auto"} will let the page grow to as large as it needs to be to fit all
49 | content. This should most likely be avoided when using row heights in
50 | relative units.}
51 | }
52 | \value{
53 | A taglist with grid elements wrapped inside a container div of class
54 | \code{id}.
55 | }
56 | \description{
57 | Builds a gridlayout within a div of specified id. Not typically called
58 | directly but can be used to create nested grids
59 | }
60 | \examples{
61 |
62 | if (FALSE) {
63 | library(gridlayout)
64 | library(shiny)
65 |
66 | # The classic Geyser app with grid layout
67 | shinyApp(
68 | ui = fluidPage(
69 | grid_container(
70 | layout = "
71 | |2rem |200px |1fr |
72 | |85px |header |header |
73 | |1fr |sidebar |plot |",
74 | grid_card_text("header", "Geysers!"),
75 | grid_card(
76 | "sidebar",
77 | card_header("Settings"),
78 | sliderInput("bins", "Number of bins:",
79 | min = 1,
80 | max = 50,
81 | value = 30,
82 | width = "100\%")
83 | ),
84 | grid_card_plot("plot")
85 | )
86 | ),
87 | server = function(input, output) {
88 | output$plot <- renderPlot({
89 | x <- faithful[, 2]
90 | bins <- seq(min(x), max(x), length.out = input$bins + 1)
91 | hist(x, breaks = bins, col = 'darkgray', border = 'white')
92 | })
93 | }
94 | )
95 | }
96 |
97 | }
98 | \seealso{
99 | \code{\link[=grid_page]{grid_page()}} for using a gridlayout to entirely define the page.
100 | \code{\link[=grid_nested]{grid_nested()}} for placing a grid container within another gridlayout.
101 | \code{\link[=grid_card]{grid_card()}} for placing content inside your layout. See
102 | \code{vignette("defining-a-layout", package = "gridlayout")} for more info on
103 | defining your layout.
104 | }
105 |
--------------------------------------------------------------------------------
/man/grid_nested.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/grid_nested.R
3 | \name{grid_nested}
4 | \alias{grid_nested}
5 | \title{Grid-positioned card with \code{gridlayout} positioned content}
6 | \usage{
7 | grid_nested(area, layout, ..., id = NULL, title = NULL, flag_mismatches = TRUE)
8 | }
9 | \arguments{
10 | \item{area}{Name of grid area, should match an area defined in the layout
11 | section of the wrapping \code{grid_page()} or \code{grid_container()}.}
12 |
13 | \item{layout}{Either a markdown table representation (see
14 | \code{\link{md_to_gridlayout}}) or a \code{gridlayout} object defining the
15 | desired layout for your Shiny app.}
16 |
17 | \item{...}{\code{grid_card()} (or similar) arguments that will fill the grid
18 | layout. Note the areas should match the those provided in \code{layout}.}
19 |
20 | \item{id}{ID unique to this container (note that the HTML will be prefixed
21 | with \verb{grid-} to avoid namespace clashes)}
22 |
23 | \item{title}{Optional title for the card. Gets wrapped in
24 | \code{bslib::card_header()}}
25 |
26 | \item{flag_mismatches}{Should a mismatch between supplied \code{elements} ui
27 | definitions and layout trigger a warning? In advanced cases you may want to
28 | dynamically set your layout and sometimes omit panels.}
29 | }
30 | \value{
31 | A \code{grid_card} with a nested layout within it
32 | }
33 | \description{
34 | Creates a panel for a layout with its own internal gridlayout
35 | }
36 | \examples{
37 | # Demonstrating the ability to nest grid layouts within other gridlayouts
38 | library(gridlayout)
39 | library(shiny)
40 | library(bslib)
41 |
42 | ui <- grid_page(
43 | layout = c(
44 | "header header",
45 | "sidebar plots"
46 | ),
47 | row_sizes = c("50px", "1fr"),
48 | col_sizes = c("250px", "1fr"),
49 | grid_card_text("header", "This is my header"),
50 | grid_card(
51 | "sidebar",
52 | card_header("Settings"),
53 | sliderInput("bins","Number of bins:", 1, 50, 30, width = "100\%")
54 | ),
55 | grid_nested(
56 | "plots",
57 | title = "Plots - in technicolor",
58 | layout = c(
59 | "distPlot distPlot distPlot",
60 | "redPlot bluePlot greenPlot"
61 | ),
62 | grid_card_plot("distPlot"),
63 | grid_card_plot("redPlot"),
64 | grid_card_plot("bluePlot"),
65 | grid_card_plot("greenPlot")
66 | )
67 | )
68 |
69 |
70 | drawHist <- function(nbins, color) {
71 | x <- faithful[, 2]
72 | bins <- seq(min(x), max(x), length.out = nbins + 1)
73 | hist(x, breaks = bins, col = color, border = "white")
74 | }
75 |
76 | server <- function(input, output) {
77 | output$distPlot <- renderPlot(drawHist(input$bins, "darkgray"))
78 | output$redPlot <- renderPlot(drawHist(input$bins, "orangered"))
79 | output$bluePlot <- renderPlot(drawHist(input$bins, "steelblue"))
80 | output$greenPlot <- renderPlot(drawHist(input$bins, "forestgreen"))
81 | }
82 |
83 | if(FALSE){
84 | shinyApp(ui, server)
85 | }
86 | }
87 | \seealso{
88 | \link{grid_card}, \link{grid_container}
89 |
90 | \code{\link[=grid_page]{grid_page()}} for using a gridlayout to entirely define the page.
91 | \code{\link[=grid_container]{grid_container()}} for placing a gridlayout in non-gridlayout parent
92 | elements. \code{\link[=grid_card]{grid_card()}} for placing content inside your layout. See
93 | \code{vignette("defining-a-layout", package = "gridlayout")} for more info on
94 | defining your layout.
95 | }
96 |
--------------------------------------------------------------------------------
/man/grid_page.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/grid_page.R
3 | \name{grid_page}
4 | \alias{grid_page}
5 | \title{Use \code{gridlayout} for entire app layout}
6 | \usage{
7 | grid_page(
8 | layout,
9 | ...,
10 | row_sizes = NULL,
11 | col_sizes = NULL,
12 | gap_size = NULL,
13 | container_height = "viewport",
14 | theme = bslib::bs_theme(version = 5),
15 | flag_mismatches = FALSE
16 | )
17 | }
18 | \arguments{
19 | \item{layout}{Either a markdown table representation (see
20 | \code{\link{md_to_gridlayout}}) or a \code{gridlayout} object defining the
21 | desired layout for your Shiny app.}
22 |
23 | \item{...}{\code{grid_card()} (or similar) arguments that will fill the grid
24 | layout. Note the areas should match the those provided in \code{layout}.}
25 |
26 | \item{row_sizes}{A character vector of valid css sizes for the height of each
27 | row in your grid as given by the main layout definition. If a single value
28 | is passed, it will be repeated for all columns. If sizes are provided both
29 | here and in the main layout then these sizes will be the ones used.}
30 |
31 | \item{col_sizes}{Same as \code{row_sizes}, but for column widths}
32 |
33 | \item{gap_size}{Valid css sizing for gap to be left between each element in your
34 | grid. Like \code{row_sizes} and \code{col_sizes}, this will win-out over a gap size
35 | provided in the main layout table.}
36 |
37 | \item{container_height}{Optional parameter to control height of page.
38 | Defaults to \code{"viewport"} so app takes up full vertical space of page.
39 | See argument of same name in \code{new_gridlayout()} for more options.}
40 |
41 | \item{theme}{Optional argument to pass to \code{theme} argument of
42 | \code{\link[shiny]{fluidPage}}.}
43 |
44 | \item{flag_mismatches}{Should mismatches between the named arguments and
45 | layout elements trigger an error?}
46 | }
47 | \value{
48 | A UI definition that can be passed to the
49 | \code{\link[shiny]{shinyUI}} function.
50 | }
51 | \description{
52 | This is the typical way to use \code{gridlayout} in your \code{Shiny} app. \code{grid_page}
53 | will make up the entire \code{ui} declaration of the app. Under the hood it uses
54 | \code{\link[shiny:fluidPage]{shiny::fluidPage()}} and \link{grid_container}. Elements are placed in the layout
55 | by wrapping in a \code{grid_card()} with the \code{area} set to the area in the layout
56 | the element should be placed in.
57 | }
58 | \examples{
59 | if (FALSE) {
60 | library(gridlayout)
61 | library(shiny)
62 | library(bslib)
63 |
64 | shinyApp(
65 | ui = grid_page(
66 | layout = c(
67 | "header header",
68 | "sidebar distPlot"
69 | ),
70 | row_sizes = c("50px", "1fr"),
71 | col_sizes = c("200px", "1fr"),
72 | grid_card_text("header", "This is my header"),
73 | grid_card(
74 | area = "sidebar",
75 | card_header("Settings"),
76 | card_body(
77 | sliderInput("bins", "Number of bins:", 1, 50, 30, width = "100\%")
78 | )
79 | ),
80 | grid_card_plot("distPlot")
81 | ),
82 | server = function(input, output) {
83 | output$distPlot <- renderPlot({
84 | x <- faithful[, 2]
85 | bins <- seq(min(x), max(x), length.out = input$bins + 1)
86 | hist(x, breaks = bins, col = 'darkgray', border = 'white')
87 | })
88 | }
89 | )
90 | }
91 | }
92 | \seealso{
93 | See \code{vignette("defining-a-layout", package = "gridlayout")} for more info on defining your layout. \code{\link[=grid_container]{grid_container()}} for using gridlayout without also setting up the
94 | root page layout. \code{\link[=grid_nested]{grid_nested()}} for placing a grid container within
95 | another gridlayout. \code{\link[=grid_card]{grid_card()}} for placing content inside your layout.
96 | }
97 |
--------------------------------------------------------------------------------
/man/grid_place.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/grid_place.R
3 | \name{grid_place}
4 | \alias{grid_place}
5 | \title{Place any \code{shiny.tag} element on the grid}
6 | \usage{
7 | grid_place(area, element)
8 | }
9 | \arguments{
10 | \item{area}{Area of grid corresponding to the wrapping grid containers grid
11 | definition}
12 |
13 | \item{element}{Element (html tag) to be placed.}
14 | }
15 | \value{
16 | The \code{element} updated with a \code{gridlayout-area} data-attribute and the
17 | \code{grid-area} property added to its styles
18 | }
19 | \description{
20 | Allows you to place any item directly on the grid without having to wrap it
21 | in \code{grid_card()} or other containers. This is done by adding a css property
22 | and data-attribute to the tag object.
23 | }
24 | \examples{
25 | if (FALSE) {
26 | library(gridlayout)
27 | library(shiny)
28 | library(bslib)
29 |
30 | shinyApp(
31 | ui = grid_page(
32 | layout = c("A B B"),
33 | grid_place(
34 | "A",
35 | sliderInput("bins","Number of bins:", min = 1, max = 50, value = 30, width = "100\%")
36 | ),
37 | grid_place(
38 | "B",
39 | plotOutput("distPlot", height = "100\%")
40 | )
41 | ),
42 | server = function(input, output, session) {
43 | output$distPlot <- renderPlot({
44 | x <- faithful[, 2]
45 | bins <- seq(min(x), max(x), length.out = input$bins + 1)
46 | hist(x, breaks = bins, col = 'darkgray', border = 'white')
47 | })
48 | }
49 | )
50 |
51 | }
52 | }
53 | \seealso{
54 | \code{\link[=grid_card]{grid_card()}} to place content on the grid wrapped in a bootstrap
55 | card.
56 | }
57 |
--------------------------------------------------------------------------------
/man/gridlayout-package.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/gridlayout-package.R
3 | \docType{package}
4 | \name{gridlayout-package}
5 | \alias{gridlayout}
6 | \alias{gridlayout-package}
7 | \title{gridlayout: Build Layouts for R-Webapps Using CSS-Grid}
8 | \description{
9 | Makes it easy to layout your Shiny app or other R-derived HTML documents using CSS grid.
10 | }
11 | \author{
12 | \strong{Maintainer}: Nick Strayer \email{nick.strayer@rstudio.com}
13 |
14 | }
15 | \keyword{internal}
16 |
--------------------------------------------------------------------------------
/man/make_bg_class.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/bootstrap-background-colors.R
3 | \name{make_bg_class}
4 | \alias{make_bg_class}
5 | \title{Build a bootstrap background class}
6 | \usage{
7 | make_bg_class(bgColor = NULL, bgGradient = FALSE)
8 | }
9 | \arguments{
10 | \item{bgColor}{Color of background in terms of bootstrap variable names:
11 | Options are \code{"primary"}, \code{"secondary"}, \code{"success"}, \code{"danger"},
12 | \code{"warning"}, \code{"info"}, \code{"light"}, and \verb{"dark}.}
13 |
14 | \item{bgGradient}{Should a gradient be applied to the background instead of a
15 | solid color?}
16 | }
17 | \value{
18 | A string containing the bootstrap class name to apply the requested
19 | background color
20 | }
21 | \description{
22 | Info on possible colors from the \href{https://getbootstrap.com/docs/5.0/utilities/background/#background-color}{bootstrap website}
23 | }
24 | \examples{
25 |
26 | gridlayout:::make_bg_class("warning")
27 | # A gradient can be applied as well
28 | gridlayout:::make_bg_class("primary", TRUE)
29 |
30 | }
31 | \keyword{internal}
32 |
--------------------------------------------------------------------------------
/man/md_to_gridlayout.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/md_to_gridlayout.R
3 | \name{md_to_gridlayout}
4 | \alias{md_to_gridlayout}
5 | \title{Build \code{gridlayout} object from markdown table}
6 | \usage{
7 | md_to_gridlayout(layout_table, null_instead_of_error = FALSE, ...)
8 | }
9 | \arguments{
10 | \item{layout_table}{Character string with a markdown table. First row and
11 | column are reserved for sizing (any valid css sizing works). An optional
12 | grid-gap can be provided using the very first cell.}
13 |
14 | \item{null_instead_of_error}{When the input fails to be parsed as a layout,
15 | should the function return \code{NULL} instead of throwing an error? Useful for
16 | situations where you're parsing multiple tables simply want to check if a
17 | table can be parsed instead of relying on it being parsable.}
18 |
19 | \item{...}{
20 | Arguments passed on to \code{\link[=new_gridlayout]{new_gridlayout}}
21 | \describe{
22 | \item{\code{layout_def}}{Either a list of elements with the \code{id}, \code{start_row},
23 | \code{end_row}, \code{start_col}, and \code{end_col} format, or a markdown table defining a
24 | layout.}
25 | \item{\code{row_sizes}}{A character vector of valid css sizes for the height of each
26 | row in your grid as given by the main layout definition. If a single value
27 | is passed, it will be repeated for all columns. If sizes are provided both
28 | here and in the main layout then these sizes will be the ones used.}
29 | \item{\code{col_sizes}}{Same as \code{row_sizes}, but for column widths}
30 | \item{\code{gap_size}}{Valid css sizing for gap to be left between each element in your
31 | grid. Like \code{row_sizes} and \code{col_sizes}, this will win-out over a gap size
32 | provided in the main layout table.}
33 | \item{\code{container_height}}{Valid css unit determining how tall the containing
34 | element should be for this layout. Defaults to \verb{100\%}. Special value of
35 | \code{"viewport"} for full-page height maps to the CSS value of \verb{100vh} if any
36 | relative units (e.g. \code{fr} or \code{auto}) are included in row sizes and \code{auto}
37 | otherwise. Values such as \code{"auto"} will let the page grow to as large as it needs to be to fit all
38 | content. This should most likely be avoided when using row heights in
39 | relative units.}
40 | \item{\code{alternate_layouts}}{A list of layouts to be used for different viewport
41 | widths. This is enables your app to adapt to different screensizes such as a
42 | phone or an ultra-wide monitor. Each entry in this list must contain a
43 | \code{layout}: or valid layout declaration (see \emph{Declaring your layout} section), and
44 | \code{width_bounds}: or a list with at least one of a \code{min} and \code{max} value for
45 | when your page appears. See \code{\link[=add_alternate_layout]{add_alternate_layout()}} for more details. If no
46 | alternate layouts are given a single-column layout will be automatically
47 | applied for mobile screens (viewports less than 600px wide). Set to \code{NULL}
48 | to avoid this.}
49 | }}
50 | }
51 | \value{
52 | An object of class "grid_layout", which stores the layout as a
53 | matrix. This can be passed to other functions such as \code{layout_to_css()}.
54 | }
55 | \description{
56 | This is just a wrapper around \link{new_gridlayout} that is more explicit about
57 | its input format. Also adds the ability to absorb errors for use when parsing
58 | free text that may or may not represent a layout table.
59 | }
60 | \examples{
61 | md_to_gridlayout(
62 | layout_table = "
63 | | |120px |1fr |1fr |
64 | |:-----|:-------|:------|:------|
65 | |100px |header |header |header |
66 | |1fr |sidebar |plot_a |plot_c |
67 | |1fr |sidebar |plot_b |plot_b |"
68 | )
69 |
70 |
71 | # Can specify gap size in upper left cell
72 | md_to_gridlayout(
73 | layout_table = "
74 | |25px |120px |1fr |
75 | |:-----|:------|:------|
76 | |100px |header |header |
77 | |1fr |plot |table |
78 | |1fr |footer |footer |"
79 | )
80 |
81 | # Don't need to follow full md table with
82 | # header row if not desired
83 | md_to_gridlayout(
84 | layout_table = "
85 | |25px |120px |1fr |
86 | |100px |header |header |
87 | |1fr |plot |table |
88 | |1fr |footer |footer |"
89 | )
90 |
91 | # Can omit sizing as well if desired
92 | md_to_gridlayout(
93 | layout_table = "
94 | |header |header |
95 | |plot |table |
96 | |footer |footer |"
97 | )
98 |
99 | }
100 | \seealso{
101 | \link{new_gridlayout}
102 | }
103 |
--------------------------------------------------------------------------------
/man/pipe.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils-pipe.R
3 | \name{\%>\%}
4 | \alias{\%>\%}
5 | \title{Pipe operator}
6 | \usage{
7 | lhs \%>\% rhs
8 | }
9 | \arguments{
10 | \item{lhs}{A value or the magrittr placeholder.}
11 |
12 | \item{rhs}{A function call using the magrittr semantics.}
13 | }
14 | \value{
15 | The result of calling \code{rhs(lhs)}.
16 | }
17 | \description{
18 | See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details.
19 | }
20 | \keyword{internal}
21 |
--------------------------------------------------------------------------------
/man/to_css.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/to_css.R
3 | \name{to_css}
4 | \alias{to_css}
5 | \title{Generate dynamic css for a given \code{gridlayout}}
6 | \usage{
7 | to_css(layout, container_key)
8 | }
9 | \arguments{
10 | \item{layout}{Object of class \code{"gridlayout"}.}
11 |
12 | \item{container_key}{The unique key used to identify the container to be
13 | targeted for the layout. If left blank it will default to applying grid
14 | styling to the whole app (aka the \code{body} element) for whole page grids. If
15 | plain character string is given, then it is assumed to be a
16 | \code{gridlayout-key} and the targeting is done using an attribute query for
17 | \code{data-gridlayout-key}. If container contains css selector characters such as
18 | a dot, the selector will not be transformed into an id automatically. E.g.
19 | \code{container = ".main-content"}.}
20 | }
21 | \value{
22 | Character string of css used to setup grid layout and place elements
23 | (referenced by id) into correct locations
24 | }
25 | \description{
26 | Generate dynamic css for a given \code{gridlayout}
27 | }
28 | \examples{
29 |
30 | grid_obj <- md_to_gridlayout(
31 | layout_table = "
32 | | |120px |1fr |1fr |
33 | |:-----|:-------|:------|:------|
34 | |100px |header |header |header |
35 | |1fr |sidebar |plot_a |plot_c |
36 | |1fr |sidebar |plot_b |plot_b |"
37 | )
38 |
39 | cat(to_css(grid_obj))
40 | }
41 |
--------------------------------------------------------------------------------
/man/to_matrix.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/to_md.R
3 | \name{to_matrix}
4 | \alias{to_matrix}
5 | \title{Convert \code{gridlayout} to matrix format}
6 | \usage{
7 | to_matrix(layout)
8 | }
9 | \arguments{
10 | \item{layout}{A gridlayout object (as created by \code{new_gridlayout()})}
11 | }
12 | \value{
13 | A matrix of the layout with each grid cell and its item membership
14 | corresponding to a cell in the matrix
15 | }
16 | \description{
17 | Convert \code{gridlayout} to matrix format
18 | }
19 | \examples{
20 |
21 | layout <- md_to_gridlayout("
22 | |10px |120px |1fr |1fr |
23 | |100px |header |header |header |
24 | |1fr |sidebar |plot_a |plot_c |
25 | |1fr |sidebar |plot_b |plot_b |")
26 |
27 | to_matrix(layout)
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/man/to_md.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/to_md.R
3 | \name{to_md}
4 | \alias{to_md}
5 | \title{Convert \code{gridlayout} to markdown table}
6 | \usage{
7 | to_md(layout, include_gap_size = TRUE)
8 | }
9 | \arguments{
10 | \item{layout}{Object of class \code{"gridlayout"}.}
11 |
12 | \item{include_gap_size}{Should the gap size for the layout be added in
13 | upper-left of table?}
14 | }
15 | \value{
16 | Markdown table that defines the grid layout. This can be used with
17 | the function \code{grid_layout_from_md()} to build grid layouts.
18 | }
19 | \description{
20 | Convert \code{gridlayout} to markdown table
21 | }
22 | \examples{
23 |
24 | my_layout <- md_to_gridlayout("
25 | | | | | |
26 | |:-----|:-------|:------|:------|
27 | |10px |120px |1fr |1fr |
28 | |100px |header |header |header |
29 | |1fr |sidebar |plot_a |plot_c |
30 | |1fr |sidebar |plot_b |plot_b |")
31 | cat(to_md(my_layout))
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/man/use_gridlayout_rmd.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/use_gridlayout_rmd.R
3 | \name{use_gridlayout_rmd}
4 | \alias{use_gridlayout_rmd}
5 | \title{Enable \code{gridlayout} usage in RMarkdown documents}
6 | \usage{
7 | use_gridlayout_rmd(container_query = ".main-container", selector_prefix = "#")
8 | }
9 | \arguments{
10 | \item{container_query}{The CSS selector used to access the main grid
11 | container. This is typically left at the default of \code{'.main-container'} as
12 | that's the parent of each section in the standard rmd template.}
13 |
14 | \item{selector_prefix}{CSS prefix used to target grid elements. This will
15 | change if you're integrating grid with a system that you don't want to use
16 | ids (the \code{"#"} prefix) with because they are not available or are used for
17 | other reasons.}
18 | }
19 | \description{
20 | Adds required hooks to RMarkdown to process \code{gridlayout} chunks and style
21 | document accordingly. Layout will be generated from a chunk identified with
22 | the syntax \verb{```\{gridlayout\} ```}
23 | }
24 | \details{
25 | See \code{vignette("using_with_rmd", package = "gridlayout")} for a more in-depth
26 | overview.
27 | }
28 |
--------------------------------------------------------------------------------
/man/use_gridlayout_shiny.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/use_gridlayout_shiny.R
3 | \name{use_gridlayout_shiny}
4 | \alias{use_gridlayout_shiny}
5 | \title{Convert layout to css for Shiny}
6 | \usage{
7 | use_gridlayout_shiny(layout, ...)
8 | }
9 | \arguments{
10 | \item{layout}{Either a markdown table representation (see
11 | \code{\link{md_to_gridlayout}}) or a \code{gridlayout} object defining the
12 | desired layout for your Shiny app.}
13 |
14 | \item{...}{
15 | Arguments passed on to \code{\link[=to_css]{to_css}}
16 | \describe{
17 | \item{\code{container_key}}{The unique key used to identify the container to be
18 | targeted for the layout. If left blank it will default to applying grid
19 | styling to the whole app (aka the \code{body} element) for whole page grids. If
20 | plain character string is given, then it is assumed to be a
21 | \code{gridlayout-key} and the targeting is done using an attribute query for
22 | \code{data-gridlayout-key}. If container contains css selector characters such as
23 | a dot, the selector will not be transformed into an id automatically. E.g.
24 | \code{container = ".main-content"}.}
25 | }}
26 | }
27 | \value{
28 | Character string of css used to setup grid layout and place elements
29 | (referenced by id) into correct locations
30 | }
31 | \description{
32 | This simply wraps the output of \code{to_css()} in a \code{style} tag and escapes HTML
33 | characters to simplify using in Shiny. Most of the time you'll want to use
34 | \code{\link{grid_page}} or \code{\link{grid_container}} instead of manually
35 | adding this css though.
36 | }
37 | \examples{
38 | # Only run these examples in interactive R sessions
39 | if (interactive()) {
40 | library(shiny)
41 | my_layout <- "
42 | | | | |
43 | |------|--------|---------|
44 | |2rem |200px |1fr |
45 | |100px |header |header |
46 | |500px |sidebar |distPlot |"
47 |
48 | # The classic Geyser app with grid layout
49 | shinyApp(
50 | ui = fluidPage(
51 | use_gridlayout_shiny(my_layout, "#app-container"),
52 | div(
53 | id = "app-container",
54 | div(
55 | style = "grid-area: header;",
56 | h2(id = "app-title", "Old Faithful Geyser Data")
57 | ),
58 | div(
59 | style = "grid-area: sidebar;",
60 | sliderInput("bins", "Number of bins:",
61 | min = 1, max = 50, value = 30
62 | )
63 | ),
64 | div(
65 | style = "grid-area:distPlot",
66 | plotOutput("distPlot", height = "100\%")
67 | )
68 | )
69 | ),
70 | server = function(input, output) {
71 | output$distPlot <- renderPlot({
72 | x <- faithful[, 2]
73 | bins <- seq(min(x), max(x), length.out = input$bins + 1)
74 | hist(x, breaks = bins, col = "darkgray", border = "white")
75 | })
76 | }
77 | )
78 |
79 | }
80 | }
81 | \seealso{
82 | \code{\link{to_css}}, \code{\link{grid_page}}, \code{\link{grid_container}}
83 | }
84 | \keyword{internal}
85 |
--------------------------------------------------------------------------------
/tests/testthat.R:
--------------------------------------------------------------------------------
1 | library(testthat)
2 | library(gridlayout)
3 |
4 | test_check("gridlayout")
5 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/grid_page.md:
--------------------------------------------------------------------------------
1 | # Works when it should
2 |
3 | Code
4 | grid_page(layout = "\n | | |\n |------|--------|\n |2rem |200px |\n |1fr |header |\n |1fr |plot |\n |1fr |footer |",
5 | grid_card("header", shiny::h2(id = "header", "This is my header content")),
6 | grid_card("footer", shiny::sliderInput("bins", "Number of bins:", min = 1,
7 | max = 50, value = 30)), grid_card("plot", shiny::plotOutput("myPlot")))
8 | Output
9 |
10 |
11 |
12 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
33 |
34 |
35 |
36 |
37 | # Warns about mismatches between layout and passed elements
38 |
39 | Code
40 | err_msg$message
41 | Output
42 | [1] "Grid areas \"footer\" are present in the children of grid container but not specified in the layout:\n"
43 |
44 | # Warns about both at the same time to help people debug easier
45 |
46 | Code
47 | err_msg$message
48 | Output
49 | [1] "Grid areas \"footer\" are specified in the layout but not present in the children:\n If the grid-area css property for these areas is being provided in a custom way, set `check_for_mismatches = FALSE` to avoid this error message.\nGrid areas \"footer2\" are present in the children of grid container but not specified in the layout:\n"
50 |
51 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/new_gridlayout.md:
--------------------------------------------------------------------------------
1 | # Handles an explicit missing row provided with dots
2 |
3 | Code
4 | new_gridlayout(layout_def = "\n | header | header |\n | plota | plotb |\n | . | . |",
5 | row_sizes = c("200px", "1fr", "2fr"))
6 | Output
7 | gridlayout of 3 elements:
8 | 1fr 1fr
9 | 200px header header
10 | 1fr plota plotb
11 | 2fr . .
12 | Gap of 12px. Total height of viewport.
13 |
14 | Alternate layouts:
15 |
16 | - Width < 500px
17 | 1fr
18 | 85px header
19 | 350px plota
20 | 350px plotb
21 | Gap of 12px. Total height of auto.
22 |
23 | ---
24 |
25 | Code
26 | new_gridlayout(layout_def = "\n | header | header | . |\n | plota | plotb | . |",
27 | col_sizes = c("200px", "1fr", "2fr"))
28 | Output
29 | gridlayout of 3 elements:
30 | 200px 1fr 2fr
31 | 1fr header header .
32 | 1fr plota plotb .
33 | Gap of 12px. Total height of viewport.
34 |
35 | Alternate layouts:
36 |
37 | - Width < 500px
38 | 1fr
39 | 85px header
40 | 350px plota
41 | 350px plotb
42 | Gap of 12px. Total height of auto.
43 |
44 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/to_css.md:
--------------------------------------------------------------------------------
1 | # Works with default body target
2 |
3 | Code
4 | cat(to_css(grid_obj))
5 | Output
6 |
7 | body {
8 | display:grid;
9 | grid-template-rows:100px 1fr 1fr;
10 | grid-template-columns:120px 1fr 1fr;
11 | grid-template-areas:
12 | "header header header"
13 | "sidebar plot_a plot_c"
14 | "sidebar plot_b plot_b";
15 | --grid-gap:12px;
16 | grid-gap:var(--grid-gap);
17 | padding:var(--grid-gap);
18 | height:100%;
19 | }
20 |
21 |
22 |
23 | @media (max-width:500px) {
24 | body {
25 | display:grid;
26 | grid-template-rows:85px 350px 350px 350px 350px;
27 | grid-template-columns:1fr;
28 | grid-template-areas:
29 | "header "
30 | "sidebar"
31 | "plot_a "
32 | "plot_b "
33 | "plot_c ";
34 | --grid-gap:12px;
35 | grid-gap:var(--grid-gap);
36 | padding:var(--grid-gap);
37 | height:auto;
38 | }
39 | }
40 |
41 |
42 | # Panel collapsibility rules are added as needed
43 |
44 | Code
45 | cat(to_css(grid_obj))
46 | Output
47 |
48 | body {
49 | display:grid;
50 | grid-template-rows:80px auto 400px;
51 | grid-template-columns:1fr;
52 | grid-template-areas:
53 | "header "
54 | "sidebar"
55 | "plot ";
56 | --grid-gap:12px;
57 | grid-gap:var(--grid-gap);
58 | padding:var(--grid-gap);
59 | height:100vh;
60 | }
61 | body > div[data-gridlayout-area="sidebar"] {
62 | --collapsible-visibility:block;
63 | --collapsed-content-size:0;
64 | --collapsed-panel-height:min-content;
65 | --collapsed-panel-overflow:hidden;
66 | }
67 |
68 |
69 | @media (max-width:500px) {
70 | body {
71 | display:grid;
72 | grid-template-rows:85px 350px 350px;
73 | grid-template-columns:1fr;
74 | grid-template-areas:
75 | "header "
76 | "sidebar"
77 | "plot ";
78 | --grid-gap:12px;
79 | grid-gap:var(--grid-gap);
80 | padding:var(--grid-gap);
81 | height:auto;
82 | }
83 | }
84 |
85 |
86 |
--------------------------------------------------------------------------------
/tests/testthat/test-alternate_layouts.R:
--------------------------------------------------------------------------------
1 |
2 | test_that("Alternate layouts can be added for different sized screens", {
3 |
4 | main_layout <- new_gridlayout(
5 | layout_def = "
6 | | header | header |
7 | | plota | plotb |",
8 | col_sizes = c("1fr", "2fr"),
9 | row_sizes = c("100px", "1fr"),
10 | gap_size = "2rem"
11 | )
12 |
13 | mobile_layout <- new_gridlayout(
14 | layout_def = "
15 | |header|
16 | |plota |
17 | |plotb |",
18 | col_sizes = c("1fr"),
19 | row_sizes = c("100px", "400px", "500px"),
20 | gap_size = "2rem"
21 | )
22 |
23 | main_w_alternate <- add_alternate_layout(
24 | layout = main_layout,
25 | alternate_layout = mobile_layout,
26 | width_bounds = c(max = 400)
27 | )
28 |
29 | expect_equal(
30 | mobile_layout$layout,
31 | get_info(main_w_alternate, "alternates")[[1]]$layout,
32 | ignore_attr = TRUE
33 | )
34 |
35 | mobile_wo_plota <- new_gridlayout(
36 | layout_def = "
37 | |header|
38 | |plota |",
39 | row_sizes = c("100px", "500px")
40 | )
41 |
42 | expect_error(
43 | add_alternate_layout(
44 | layout = main_layout,
45 | alternate_layout = mobile_wo_plota,
46 | width_bounds = c(max = 400)
47 | ),
48 | regexp = "Layouts have mismatched elements: plotb",
49 | fixed = TRUE
50 | )
51 |
52 | big_screen_layout <- new_gridlayout(
53 | layout_def = "|header|plota|plotb|",
54 | col_sizes = c("200px", "1fr", "1fr"),
55 | row_sizes = c("1fr")
56 | )
57 |
58 | expect_error(
59 | add_alternate_layout(
60 | main_w_alternate,
61 | alternate_layout = big_screen_layout,
62 | width_bounds = c(min = 350)
63 | ),
64 | regexp = "New alternate interval overlaps with previous interval",
65 | fixed = TRUE
66 | )
67 | })
68 |
69 | test_that("Alternate layouts can be added with alternate layouts argument or chained with add_alternate_layout()", {
70 | main_layout <- "
71 | | | | |
72 | |------|--------|-------|
73 | |2rem |200px |1fr |
74 | |80px |header |header |
75 | |1fr |sidebar |plot |"
76 |
77 | mobile_layout <- "
78 | |----- |--------|
79 | |2rem |1fr |
80 | |80px |header |
81 | |auto |sidebar |
82 | |400px |plot |"
83 |
84 | big_screen_layout <- "
85 | |-----|-------|--------|-----|
86 | |2rem |250px | 250px |1fr |
87 | |1fr |header |sidebar |plot |"
88 |
89 | alternate_layouts_argument <- new_gridlayout(
90 | main_layout,
91 | alternate_layouts = list(
92 | list(
93 | layout = mobile_layout,
94 | width_bounds = c(max = 600),
95 | container_height = "auto"
96 | ),
97 | list(
98 | layout = big_screen_layout,
99 | width_bounds = c(min = 1200)
100 | )
101 | )
102 | )
103 |
104 | chained_alternates <- new_gridlayout(main_layout)
105 |
106 | chained_alternates <- add_alternate_layout(
107 | chained_alternates,
108 | mobile_layout,
109 | width_bounds = c(max = 600),
110 | container_height = "auto"
111 | )
112 |
113 | chained_alternates <- add_alternate_layout(
114 | chained_alternates,
115 | big_screen_layout,
116 | width_bounds = c(min = 1200)
117 | )
118 |
119 | expect_identical(
120 | alternate_layouts_argument,
121 | chained_alternates
122 | )
123 | })
124 |
125 | test_that("A single alternate layout does not need to be double nested", {
126 | main_layout <- "
127 | | | | |
128 | |------|--------|-------|
129 | |2rem |200px |1fr |
130 | |80px |header |header |
131 | |1fr |sidebar |plot |"
132 |
133 | mobile_layout <- "
134 | |----- |--------|
135 | |2rem |1fr |
136 | |80px |header |
137 | |auto |sidebar |
138 | |400px |plot |"
139 |
140 |
141 | expect_identical(
142 | new_gridlayout(
143 | main_layout,
144 | alternate_layouts = list(
145 | layout = mobile_layout,
146 | width_bounds = c(min = 600),
147 | container_height = "auto"
148 | )
149 | ),
150 | new_gridlayout(
151 | main_layout,
152 | alternate_layouts = list(
153 | list(
154 | layout = mobile_layout,
155 | width_bounds = c(min = 600),
156 | container_height = "auto"
157 | )
158 | )
159 | )
160 | )
161 | })
162 |
163 |
--------------------------------------------------------------------------------
/tests/testthat/test-demo-apps.R:
--------------------------------------------------------------------------------
1 | # Don't run these tests on the CRAN build servers
2 | skip_on_cran()
3 |
4 | library(shinytest2)
5 | library(shiny)
6 |
7 | for (demo_app in demo_apps) {
8 | path_to_app <- system.file(package = "gridlayout", paste0("demo_apps/", demo_app))
9 | test_app(path_to_app, check_setup = FALSE)
10 | }
11 |
--------------------------------------------------------------------------------
/tests/testthat/test-grid_container.R:
--------------------------------------------------------------------------------
1 | make_grid_container <- function(...){
2 | htmltools::renderTags(
3 | grid_container(
4 | ...,
5 | id = "my_grid",
6 | grid_card_text("header", "This is my header content"),
7 | grid_card(
8 | "plot",
9 | shiny::plotOutput("myPlot")
10 | )
11 | )
12 | )
13 | }
14 |
15 |
16 | md_table <- make_grid_container(
17 | layout = "
18 | |2rem |200px |
19 | |100px|header |
20 | |1fr |plot |"
21 | )
22 |
23 | sized_array_table <- make_grid_container(
24 | layout = c(
25 | "2rem 200px",
26 | "100px header",
27 | "1fr plot"
28 | )
29 | )
30 |
31 | array_table_with_size_args <- make_grid_container(
32 | layout = c(
33 | "header",
34 | "plot"
35 | ),
36 | row_sizes = c("100px", "1fr"),
37 | col_sizes = c("200px"),
38 | gap_size = "2rem"
39 | )
40 |
41 | array_table_with_gap_args <- make_grid_container(
42 | layout = c(
43 | " 200px",
44 | "100px header",
45 | "1fr plot"
46 | ),
47 | gap_size = "2rem"
48 | )
49 |
50 |
51 |
52 | test_that("Different methods of defining the same layout return the same thing", {
53 |
54 | expect_equal(
55 | md_table,
56 | sized_array_table
57 | )
58 |
59 | expect_equal(
60 | sized_array_table,
61 | array_table_with_size_args
62 | )
63 |
64 | expect_equal(
65 | array_table_with_size_args,
66 | array_table_with_gap_args
67 | )
68 | })
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/tests/testthat/test-grid_page.R:
--------------------------------------------------------------------------------
1 | test_that("Works when it should", {
2 |
3 | expect_snapshot(
4 | grid_page(
5 | layout = "
6 | | | |
7 | |------|--------|
8 | |2rem |200px |
9 | |1fr |header |
10 | |1fr |plot |
11 | |1fr |footer |",
12 | grid_card(
13 | "header",
14 | shiny::h2(id = "header", "This is my header content")
15 | ),
16 | grid_card(
17 | "footer",
18 | shiny::sliderInput("bins","Number of bins:", min = 1, max = 50, value = 30)
19 | ),
20 | grid_card(
21 | "plot",
22 | shiny::plotOutput("myPlot")
23 | )
24 | )
25 | )
26 | })
27 |
28 | test_that("Warns about mismatches between layout and passed elements", {
29 |
30 | layout_wo_footer <- "
31 | | | |
32 | |------|--------|
33 | |2rem |200px |
34 | |1fr |header |
35 | |1fr |plot |"
36 |
37 | err_msg <- expect_error(
38 | grid_container(
39 | layout = layout_wo_footer,
40 | grid_card(
41 | "header",
42 | shiny::h2(id = "header", "This is my header content")
43 | ),
44 | grid_card(
45 | "footer",
46 | shiny::sliderInput("bins","Number of bins:", min = 1, max = 50, value = 30)
47 | ),
48 | grid_card(
49 | "plot",
50 | shiny::plotOutput("myPlot")
51 | )
52 | )
53 | )
54 |
55 | expect_snapshot(err_msg$message)
56 | })
57 |
58 | test_that("Warns about both at the same time to help people debug easier", {
59 |
60 | err_msg <- expect_error(
61 | grid_container(
62 | layout = "
63 | | | |
64 | |------|--------|
65 | |2rem |200px |
66 | |1fr |header |
67 | |1fr |plot |
68 | |1fr |footer |",
69 | grid_card(
70 | "header",
71 | shiny::h2(id = "header", "This is my header content")
72 | ),
73 | grid_card(
74 | "footer2",
75 | shiny::sliderInput("bins","Number of bins:", min = 1, max = 50, value = 30)
76 | ),
77 | grid_card(
78 | "plot",
79 | shiny::plotOutput("myPlot")
80 | )
81 | )
82 | )
83 |
84 | expect_snapshot(err_msg$message)
85 |
86 | })
87 |
88 |
--------------------------------------------------------------------------------
/tests/testthat/test-markdown-layout-parsing.R:
--------------------------------------------------------------------------------
1 |
2 | test_that("Basic table works", {
3 | my_layout <- new_gridlayout("
4 | | |120px |1fr |1fr |
5 | |------|--------|-------|-------|
6 | |100px |header |header |header |
7 | |1fr |sidebar |plot_a |plot_c |
8 | |1fr |sidebar |plot_b |plot_b |"
9 | )
10 |
11 | expect_s3_class(my_layout, "gridlayout")
12 |
13 | expect_equal(get_info(my_layout, "col_sizes"),
14 | c("120px", "1fr", "1fr"))
15 |
16 | expect_equal(get_info(my_layout, "row_sizes"),
17 | c("100px", "1fr", "1fr"))
18 |
19 | expect_equal(get_info(my_layout, "gap_size"),
20 | default_gap_size)
21 | })
22 |
23 | test_that("Can put gap size in upper left", {
24 | my_layout <- new_gridlayout("
25 | | 2rem |120px |1fr |1fr |
26 | |------|--------|-------|-------|
27 | |100px |header |header |header |
28 | |1fr |sidebar |plot_a |plot_c |
29 | |1fr |sidebar |plot_b |plot_b |"
30 | )
31 |
32 | expect_equal(get_info(my_layout, "gap_size"),
33 | "2rem")
34 | })
35 |
36 | test_that("Doesn't matter if col sizes are given in table header or simply first row", {
37 |
38 | expect_equal(
39 | new_gridlayout("
40 | | 2rem |120px |1fr |1fr |
41 | |------|--------|-------|-------|
42 | |100px |header |header |header |
43 | |1fr |sidebar |plot_a |plot_c |
44 | |1fr |sidebar |plot_b |plot_b |"
45 | ),
46 | new_gridlayout("
47 | | | | | |
48 | |------|--------|-------|-------|
49 | | 2rem |120px |1fr |1fr |
50 | |100px |header |header |header |
51 | |1fr |sidebar |plot_a |plot_c |
52 | |1fr |sidebar |plot_b |plot_b |"
53 | ))
54 | })
55 |
56 | test_that("No sizes will give you constant sizes rows and cols", {
57 | my_layout <- new_gridlayout("
58 | | | | |
59 | |:-------|:------|:------|
60 | |header |header |header |
61 | |sidebar |plot_a |plot_c |
62 | |sidebar |plot_b |plot_b |"
63 | )
64 |
65 | expect_equal(get_info(my_layout, "col_sizes"),
66 | c("1fr", "1fr", "1fr"))
67 |
68 | expect_equal(get_info(my_layout, "row_sizes"),
69 | c("1fr", "1fr", "1fr"))
70 | })
71 |
72 | test_that("Nonsense will give a usefull error message", {
73 | expect_error(
74 | new_gridlayout("## THis was an accidentally
75 | selected chunk of text
76 | that is not a table at all"
77 | ))
78 | })
79 |
80 |
81 | test_that("Markdown parsing -- All sizes provided", {
82 | expect_snapshot(
83 | new_gridlayout("
84 | |2rem |200px |1fr |
85 | |80px |header |header |
86 | |1fr |sidebar |plot |"
87 | )
88 | )
89 | })
90 |
91 | test_that("Markdown parsing -- Only row sizes", {
92 | expect_snapshot(
93 | new_gridlayout("
94 | |80px |header |header |
95 | |1fr |sidebar |plot |"
96 | )
97 | )
98 | })
99 |
100 |
101 | test_that("Markdown parsing -- Only col sizes", {
102 | expect_snapshot(
103 | new_gridlayout("
104 | |200px |1fr |
105 | |header |header |
106 | |sidebar |plot |"
107 | )
108 | )
109 | })
110 |
111 | test_that("Markdown parsing -- Gap and row sizes", {
112 | expect_snapshot(
113 | new_gridlayout("
114 | |2rem | | |
115 | |80px |header |header |
116 | |1fr |sidebar |plot |"
117 | )
118 | )
119 | })
120 |
121 | test_that("Markdown parsing -- Only gap size", {
122 | expect_snapshot(
123 | new_gridlayout("
124 | |3rem | | |
125 | | |header |header |
126 | | |sidebar |plot |"
127 | )
128 | )
129 | })
130 |
131 | test_that("Markdown parsing -- Single column", {
132 |
133 | expect_snapshot(
134 | new_gridlayout("
135 | |----- |--------|
136 | |2rem |1fr |
137 | |80px |header |
138 | |auto |sidebar |
139 | |400px |plot |"
140 | )
141 | )
142 |
143 | })
144 |
145 | test_that("Markdown parsing -- Single row", {
146 |
147 | expect_snapshot(
148 | new_gridlayout("
149 | |2rem |auto | 200px | 1fr |
150 | |80px |header |sidebar |sidebar |"
151 | )
152 | )
153 |
154 | })
155 |
156 |
157 | test_that("Markdown parsing -- No sizes", {
158 | expect_snapshot(
159 | new_gridlayout("
160 | |header |header |
161 | |sidebar |plot |"
162 | )
163 | )
164 | })
165 |
--------------------------------------------------------------------------------
/tests/testthat/test-md_table_to_matrix.R:
--------------------------------------------------------------------------------
1 | test_that("all sizes", {
2 | expect_equal(
3 | md_table_to_matrix( "
4 | |2rem | 300px |1fr |
5 | |80px |header |header |
6 | |1fr |sidebar |plot |"),
7 | matrix(
8 | c(
9 | "2rem", "300px", "1fr",
10 | "80px", "header", "header",
11 | "1fr", "sidebar", "plot"
12 | ),
13 | nrow=3,
14 | byrow = TRUE
15 | )
16 | )
17 | })
18 | test_that("gap-size and row-sizes", {
19 | expect_equal(
20 | md_table_to_matrix( "
21 | |2rem | | |
22 | |80px |header |header |
23 | |1fr |sidebar |plot |"),
24 | matrix(
25 | c(
26 | "2rem", "", "",
27 | "80px", "header", "header",
28 | "1fr", "sidebar", "plot"
29 | ),
30 | nrow=3,
31 | byrow = TRUE
32 | )
33 | )
34 | })
35 |
36 | test_that("only row-sizes", {
37 | expect_equal(
38 | md_table_to_matrix( "
39 | |80px |header |header |
40 | |1fr |sidebar |plot |"),
41 | matrix(
42 | c(
43 | "80px", "header", "header",
44 | "1fr", "sidebar", "plot"
45 | ),
46 | nrow=2,
47 | byrow = TRUE
48 | )
49 | )
50 | })
51 |
52 | test_that("only col-sizes", {
53 | expect_equal(
54 | md_table_to_matrix( "
55 | | 1rem | 1fr |
56 | |header |header |
57 | |sidebar |plot |"),
58 | matrix(
59 | c(
60 | "1rem", "1fr",
61 | "header", "header",
62 | "sidebar", "plot"
63 | ),
64 | nrow=3,
65 | byrow = TRUE
66 | )
67 | )
68 | })
69 |
70 |
71 | test_that("only gap-size", {
72 | expect_equal(
73 | md_table_to_matrix( "
74 | |2rem | | |
75 | | |header |header |
76 | | |sidebar |plot |"),
77 | matrix(
78 | c(
79 | "2rem", "", "",
80 | "", "header", "header",
81 | "", "sidebar", "plot"
82 | ),
83 | nrow=3,
84 | byrow = TRUE
85 | )
86 | )
87 | })
88 |
89 | test_that("no sizes", {
90 | expect_equal(
91 | md_table_to_matrix( "
92 | |header |header |
93 | |sidebar |plot |"),
94 | matrix(
95 | c(
96 | "header", "header",
97 | "sidebar", "plot"
98 | ),
99 | nrow=2,
100 | byrow = TRUE
101 | )
102 | )
103 | })
104 |
--------------------------------------------------------------------------------
/tests/testthat/test-nested-grids.R:
--------------------------------------------------------------------------------
1 |
2 | test_that("Can handle recursive nesting", {
3 |
4 | my_layout <- "
5 | | | | | |
6 | |-----|-----|-------|-------|
7 | |10px |1fr |5fr |1fr |
8 | |1fr |top |top |right |
9 | |5fr |left |nested |right |
10 | |1fr |left |bottom |bottom |"
11 |
12 | depth <- 2
13 |
14 | emoji_panel <- function(area, emoji){
15 | grid_card(
16 | area = area,
17 | htmltools::div(
18 | style = htmltools::css(
19 | width = "100%", height = "100%",
20 | display = "grid",
21 | "font-size" = "2rem",
22 | "place-content" = "center"),
23 | emoji
24 | )
25 | )
26 | }
27 |
28 | make_nested_panels <- function(level = 1) {
29 | grid_nested(
30 | area = "nested",
31 | layout = my_layout,
32 | id = paste0("level", level),
33 | emoji_panel("top", "↓"),
34 | emoji_panel("bottom", "↑"),
35 | emoji_panel("left", "→"),
36 | emoji_panel("right", "←"),
37 | if(level < depth) make_nested_panels(level + 1) else emoji_panel("nested", "🐢")
38 | )
39 | }
40 |
41 | make_nested_panels()
42 |
43 | expect_snapshot(make_nested_panels())
44 | })
45 |
--------------------------------------------------------------------------------
/tests/testthat/test-parse_layout_matrix.R:
--------------------------------------------------------------------------------
1 | test_that("Fully defined sizes", {
2 |
3 | parsed <- parse_layout_matrix(
4 | matrix(
5 | c(
6 | "11px", "1fr", "300px",
7 | "100px", "header", "header",
8 | "1fr", "plota", "plotb",
9 | "2rem", "footer", "footer"
10 | ),
11 | nrow = 4,
12 | byrow = TRUE
13 | )
14 | )
15 |
16 | expect_equal(
17 | parsed$column_sizes,
18 | c("1fr", "300px")
19 | )
20 | expect_equal(
21 | parsed$row_sizes,
22 | c("100px", "1fr", "2rem")
23 | )
24 | expect_equal(
25 | parsed$gap_size,
26 | "11px"
27 | )
28 | })
29 |
30 |
31 | test_that("Missing gap size", {
32 |
33 | parsed <- parse_layout_matrix(
34 | matrix(
35 | c(
36 | "", "1fr", "300px",
37 | "100px", "header", "header",
38 | "1fr", "plota", "plotb",
39 | "2rem", "footer", "footer"
40 | ),
41 | nrow = 4,
42 | byrow = TRUE
43 | )
44 | )
45 |
46 | expect_equal(
47 | parsed$column_sizes,
48 | c("1fr", "300px")
49 | )
50 | expect_equal(
51 | parsed$row_sizes,
52 | c("100px", "1fr", "2rem")
53 | )
54 | expect_equal(
55 | parsed$gap_size,
56 | DEFAULT_SIZE_CHAR
57 | )
58 | })
59 |
60 | test_that("No column sizes", {
61 | parsed <- parse_layout_matrix(
62 | matrix(
63 | c(
64 | "100px", "header", "header",
65 | "1fr", "plota", "plotb",
66 | "2rem", "footer", "footer"
67 | ),
68 | nrow = 3,
69 | byrow = TRUE
70 | )
71 | )
72 |
73 | expect_equal(
74 | parsed$column_sizes,
75 | c(DEFAULT_SIZE_CHAR, DEFAULT_SIZE_CHAR)
76 | )
77 | expect_equal(
78 | parsed$row_sizes,
79 | c("100px", "1fr", "2rem")
80 | )
81 | expect_equal(
82 | parsed$gap_size,
83 | DEFAULT_SIZE_CHAR
84 | )
85 | })
86 |
87 | test_that("No row sizes", {
88 | parsed <- parse_layout_matrix(
89 | matrix(
90 | c(
91 | "1fr", "2fr",
92 | "header", "header",
93 | "plota", "plotb",
94 | "footer", "footer"
95 | ),
96 | nrow = 4,
97 | byrow = TRUE
98 | )
99 | )
100 |
101 | expect_equal(
102 | parsed$column_sizes,
103 | c("1fr", "2fr")
104 | )
105 | expect_equal(
106 | parsed$row_sizes,
107 | c(DEFAULT_SIZE_CHAR, DEFAULT_SIZE_CHAR, DEFAULT_SIZE_CHAR)
108 | )
109 | expect_equal(
110 | parsed$gap_size,
111 | DEFAULT_SIZE_CHAR
112 | )
113 | })
114 |
115 |
116 |
117 | test_that("Single column - no-sizes", {
118 | parsed <- parse_layout_matrix(
119 | matrix(
120 | c(
121 | "plota",
122 | "plotb"
123 | ),
124 | nrow = 2,
125 | byrow = TRUE
126 | )
127 | )
128 |
129 | expect_equal(
130 | parsed$column_sizes,
131 | c(DEFAULT_SIZE_CHAR)
132 | )
133 | expect_equal(
134 | parsed$row_sizes,
135 | c(DEFAULT_SIZE_CHAR, DEFAULT_SIZE_CHAR)
136 | )
137 | expect_equal(
138 | parsed$gap_size,
139 | DEFAULT_SIZE_CHAR
140 | )
141 | })
142 |
143 | test_that("Single column - all-sizes", {
144 |
145 | parsed <- parse_layout_matrix(
146 | matrix(
147 | c("1rem", "430px",
148 | "240px","plota",
149 | "1fr", "plotb"),
150 | nrow = 3,
151 | byrow = TRUE
152 | )
153 | )
154 |
155 | expect_equal(
156 | parsed$column_sizes,
157 | c("430px")
158 | )
159 | expect_equal(
160 | parsed$row_sizes,
161 | c("240px", "1fr")
162 | )
163 | expect_equal(
164 | parsed$gap_size,
165 | "1rem"
166 | )
167 | })
168 |
169 |
170 | test_that("Single row - no-sizes", {
171 | parsed <- parse_layout_matrix(
172 | matrix(
173 | c(
174 | "plota","plotb"
175 | ),
176 | nrow = 1,
177 | byrow = TRUE
178 | )
179 | )
180 |
181 | expect_equal(
182 | parsed$column_sizes,
183 | c(DEFAULT_SIZE_CHAR, DEFAULT_SIZE_CHAR)
184 | )
185 | expect_equal(
186 | parsed$row_sizes,
187 | c(DEFAULT_SIZE_CHAR)
188 | )
189 | expect_equal(
190 | parsed$gap_size,
191 | DEFAULT_SIZE_CHAR
192 | )
193 | })
194 |
195 | test_that("Partially defined sizes", {
196 |
197 | parsed <- parse_layout_matrix(
198 | matrix(
199 | c(
200 | "", "1fr", "",
201 | "100px", "header", "header",
202 | "", "plota", "plotb",
203 | "2rem", "footer", "footer"
204 | ),
205 | nrow = 4,
206 | byrow = TRUE
207 | )
208 | )
209 |
210 | expect_equal(
211 | parsed$column_sizes,
212 | c("1fr", DEFAULT_SIZE_CHAR)
213 | )
214 | expect_equal(
215 | parsed$row_sizes,
216 | c("100px", DEFAULT_SIZE_CHAR, "2rem")
217 | )
218 | expect_equal(
219 | parsed$gap_size,
220 | DEFAULT_SIZE_CHAR
221 | )
222 | })
223 |
224 |
225 |
--------------------------------------------------------------------------------
/tests/testthat/test-to_css.R:
--------------------------------------------------------------------------------
1 | test_that("Works with default body target", {
2 | grid_obj <- new_gridlayout(
3 | "
4 | | |120px |1fr |1fr |
5 | |:-----|:-------|:------|:------|
6 | |100px |header |header |header |
7 | |1fr |sidebar |plot_a |plot_c |
8 | |1fr |sidebar |plot_b |plot_b |"
9 | )
10 |
11 | expect_snapshot(cat(to_css(grid_obj)))
12 | })
13 |
14 | test_that("Can change body target", {
15 | grid_obj <- new_gridlayout("
16 | | |120px |1fr |1fr |
17 | |:-----|:-------|:------|:------|
18 | |100px |header |header |header |
19 | |1fr |sidebar |plot_a |plot_c |
20 | |1fr |sidebar |plot_b |plot_b |"
21 | )
22 |
23 | app_css <- to_css(grid_obj, "app_container")
24 |
25 | expect_true(
26 | str_detect(app_css, "data-gridlayout-key=\"app_container\"", fixed = TRUE)
27 | )
28 | })
29 |
30 |
31 |
32 |
33 | test_that("Height setting can be customized", {
34 | grid_obj <- new_gridlayout("
35 | | |120px |1fr |1fr |
36 | |:-----|:-------|:------|:------|
37 | |100px |header |header |header |
38 | |1fr |sidebar |plot_a |plot_c |
39 | |1fr |sidebar |plot_b |plot_b |",
40 | container_height = "viewport"
41 | )
42 |
43 | expect_true(
44 | str_detect(
45 | to_css(grid_obj),
46 | "height:100vh",
47 | fixed = TRUE
48 | )
49 | )
50 |
51 |
52 | expect_true(
53 | str_detect(
54 | to_css(new_gridlayout(grid_obj,container_height = "800px")),
55 | "height:800px",
56 | fixed = TRUE
57 | )
58 | )
59 |
60 | })
61 |
62 |
63 | test_that("Panel collapsibility rules are added as needed", {
64 |
65 | grid_obj <- new_gridlayout( "
66 | | |1fr |
67 | |80px |header |
68 | |auto |sidebar |
69 | |400px |plot |",
70 | container_height = "viewport"
71 | )
72 |
73 | expect_snapshot(cat(to_css(grid_obj)))
74 | })
75 |
--------------------------------------------------------------------------------
/tests/testthat/test-to_md.R:
--------------------------------------------------------------------------------
1 | test_that("Can reacreate input table", {
2 | start_table <-
3 | "| 10px | 120px | 1fr | 1fr |
4 | |-------|---------|--------|--------|
5 | | 100px | header | header | header |
6 | | 1fr | sidebar | plot_a | plot_c |
7 | | 1fr | sidebar | plot_b | plot_b |"
8 |
9 | my_layout <- new_gridlayout(start_table)
10 | expect_equal(
11 | to_md(my_layout),
12 | start_table
13 | )
14 | })
15 |
16 | test_that("Gap size can be omitted if desired", {
17 | start_table <-
18 | "| 10px | 120px | 1fr | 1fr |
19 | |-------|---------|--------|--------|
20 | | 100px | header | header | header |
21 | | 1fr | sidebar | plot_a | plot_c |
22 | | 1fr | sidebar | plot_b | plot_b |"
23 |
24 | my_layout <- new_gridlayout(start_table)
25 | expect_equal(
26 | to_md(my_layout, include_gap_size = FALSE),
27 | "| | 120px | 1fr | 1fr |
28 | |-------|---------|--------|--------|
29 | | 100px | header | header | header |
30 | | 1fr | sidebar | plot_a | plot_c |
31 | | 1fr | sidebar | plot_b | plot_b |"
32 | )
33 | })
34 |
--------------------------------------------------------------------------------
/vignettes/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 | *.R
3 |
--------------------------------------------------------------------------------
/vignettes/alternate-layouts_resizing.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/vignettes/alternate-layouts_resizing.gif
--------------------------------------------------------------------------------
/vignettes/alternate-layouts_w1000_h1000.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/vignettes/alternate-layouts_w1000_h1000.png
--------------------------------------------------------------------------------
/vignettes/alternate-layouts_w2000_h1000.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/vignettes/alternate-layouts_w2000_h1000.png
--------------------------------------------------------------------------------
/vignettes/alternate-layouts_w500_h1000.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/vignettes/alternate-layouts_w500_h1000.png
--------------------------------------------------------------------------------
/vignettes/defining-a-layout.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Defining a layout"
3 | output: rmarkdown::html_vignette
4 | vignette: >
5 | %\VignetteIndexEntry{Defining a layout}
6 | %\VignetteEngine{knitr::rmarkdown}
7 | %\VignetteEncoding{UTF-8}
8 | ---
9 |
10 | ```{r, include = FALSE}
11 | knitr::opts_chunk$set(
12 | collapse = TRUE,
13 | comment = "#>"
14 | )
15 | ```
16 |
17 | ```{r setup}
18 | library(gridlayout)
19 |
20 | # Print the layout without showing mobile layouts
21 | show_layout <- function(layout) {
22 | print(layout, show_alternates = FALSE)
23 | }
24 | ```
25 |
26 | There are multiple ways to define a gridlayout. The following all describe the exact same layout. An app with a 100 pixel tall header spanning the width of the page, a 120 pixel wide sidebar on the left, and three plots in the remaining with `plot_a` being the smallest, `plot_b` being twice as wide as `plot_a`, and `plot_c` sitting below both `plot_a` and `plot_c` spanning the width of both.
27 |
28 |
29 | ## Where to pass your layout to
30 |
31 | All examples are passed to `new_gridlayout()` which generates a `gridlayout` object directly. However, typically these layouts are passed directly into the `gridlayout` container functions `new_gridlayout()`, `grid_page()`, `grid_container()`, or `grid_nested()`.
32 |
33 |
34 | ### A note sizing
35 |
36 | For the first two definition techniques we use inline sizes, however, for both layouts the sizes can be omitted for even sizes rows/columns, or passed as arrays to the`row_sizes` and `col_sizes` arguments in the grid layout container function. Additionally, the size of the gap between elements in your layout can be passed using either the upper-left "cell" of the table layout or the `gap_size` argument.
37 |
38 |
39 | ## The table array
40 |
41 | The most common way to define your layout is using an character vector where each element represents a row in your layout. Each column is delineated by one or more spaces between the names of the defined regions. This allows you to line up your layout visually. Sizes can be added for the rows and columns by placing row sizes at the left of the respective row and column sizes at the top of the respective column.
42 |
43 |
44 | ```{r md_to_gridlayout}
45 | library(gridlayout)
46 |
47 | table_array <- new_gridlayout(c(
48 | " 120px 1fr 2fr ",
49 | "100px header header header",
50 | "1fr sidebar plot_a plot_b",
51 | "1fr sidebar plot_c plot_c"
52 | ))
53 |
54 | show_layout(table_array)
55 | ```
56 |
57 | ## The single character table
58 |
59 | Similar to the table array definition, a markdown table enclosed in a single string can be used as well. This is the method used to declare a layout in an RMarkdown file but since multi-line strings can be hard to keep formatted properly, the table-array definition is usually prefered for shiny-app usage.
60 |
61 | ```{r}
62 | md_table <- new_gridlayout("
63 | | |120px |1fr |2fr |
64 | |------|--------|-------|-------|
65 | |100px |header |header |header |
66 | |1fr |sidebar |plot_a |plot_b |
67 | |1fr |sidebar |plot_c |plot_c |"
68 | )
69 |
70 | show_layout(md_table)
71 | ```
72 |
73 |
74 | ## Elements list
75 |
76 | The last method is using a list to define the give positions of the items. This method is much more verbose than the previous two but is easier to generate using code. This can be useful in layouts with a large number of rows and columns where writing out the table would be cumbersome.
77 |
78 | ```{r}
79 | # Assemble list of elements along with their positions
80 | layout_elements <- list(
81 | list(
82 | id = "header", start_row = 1, end_row = 1,
83 | start_col = 1, end_col = 3
84 | ),
85 | list(
86 | id = "sidebar", start_row = 2, end_row = 3,
87 | start_col = 1, end_col = 1
88 | ),
89 | list(
90 | id = "plot_a", start_row = 2, end_row = 2,
91 | start_col = 2, end_col = 2
92 | ),
93 | list(
94 | id = "plot_b", start_row = 2, end_row = 2,
95 | start_col = 3, end_col = 3
96 | ),
97 | list(
98 | id = "plot_c", start_row = 3, end_row = 3,
99 | start_col = 2, end_col = 3
100 | )
101 | )
102 |
103 | elements_list <- new_gridlayout(
104 | layout_elements,
105 | col_sizes = c("120px", "1fr", "2fr"),
106 | row_sizes = c("100px", "1fr", "1fr")
107 | )
108 |
109 | show_layout(elements_list)
110 | ```
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/vignettes/layout-examples_focal_chart_side.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/vignettes/layout-examples_focal_chart_side.png
--------------------------------------------------------------------------------
/vignettes/layout-examples_focal_chart_top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/vignettes/layout-examples_focal_chart_top.png
--------------------------------------------------------------------------------
/vignettes/layout-examples_four_panel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/vignettes/layout-examples_four_panel.png
--------------------------------------------------------------------------------
/vignettes/layout-examples_scrolling_stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/vignettes/layout-examples_scrolling_stack.png
--------------------------------------------------------------------------------
/vignettes/layout-examples_stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/vignettes/layout-examples_stack.png
--------------------------------------------------------------------------------
/vignettes/use_gridlayout_rmd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/vignettes/use_gridlayout_rmd.png
--------------------------------------------------------------------------------
/vignettes/use_gridlayout_rmd_base.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/vignettes/use_gridlayout_rmd_base.png
--------------------------------------------------------------------------------
/vignettes/use_gridlayout_rmd_extra_child_styles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/vignettes/use_gridlayout_rmd_extra_child_styles.png
--------------------------------------------------------------------------------
/vignettes/use_gridlayout_rmd_only_grid_panel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rstudio/gridlayout/dc7d8912ae27e5393561dcc2b9bd637f3653ca09/vignettes/use_gridlayout_rmd_only_grid_panel.png
--------------------------------------------------------------------------------
/vignettes/using_with_rmd.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Using with Rmds"
3 | output: rmarkdown::html_vignette
4 | vignette: >
5 | %\VignetteIndexEntry{Using with Rmds}
6 | %\VignetteEngine{knitr::rmarkdown}
7 | %\VignetteEncoding{UTF-8}
8 | ---
9 |
10 | ```{r, include = FALSE}
11 | knitr::opts_chunk$set(
12 | collapse = TRUE,
13 | comment = "",
14 | out.width = "100%",
15 | eval = FALSE
16 | )
17 |
18 | rmd_loc <- "demo_apps/rmarkdown_demo/grid_markdown.Rmd"
19 | ```
20 |
21 | ```{r, eval = FALSE, echo = FALSE}
22 | # Generate screenshots for this vignette
23 | source(here::here("inst/demo_apps/setupScreenshots.R"))
24 |
25 |
26 | screenshot_demo_app(
27 | app_path = here::here('inst/demo_apps/', rmd_loc),
28 | screenshot_name = "use_gridlayout_rmd.png",
29 | screenshot_root = "vignettes",
30 | vwidth = 1100
31 | )
32 |
33 | ```
34 |
35 |
36 | ```{r}
37 | library(gridlayout)
38 | ```
39 |
40 |
41 | By placing the function `use_gridlayout_rmd` in the `setup` chunk of an Rmd you can define a gridlayout table using the a code chunk with the "language" set to `gridlayout`. Any markdown style table (see `md_to_gridlayout()`) will be used to setup a grid-layout for your page. Just make sure your sections are given headers corresponding to the respective grid elements (either using their name or by using the `#My header text {#custom_id}` syntax after the header.)
42 |
43 |
44 | The following shows how you can customize the appearance of the elements of your layout using "card styles" and custom css.
45 |
46 |
47 | # The markdown code
48 |
49 | The screenshot below is based on the following `.Rmd`.
50 |
51 |
52 | ```{r, echo=FALSE, eval=TRUE}
53 | rmd_content <- readLines(
54 | system.file(rmd_loc, package = "gridlayout")
55 | )
56 |
57 | cat(paste(rmd_content, collapse = "\n"))
58 | ```
59 |
60 |
61 | ## Result
62 |
63 |
64 |
65 | ```{r, echo = FALSE, message=FALSE, eval=TRUE}
66 | knitr::include_graphics("use_gridlayout_rmd.png")
67 | ```
68 |
69 |
70 |
--------------------------------------------------------------------------------