From c99fba14fa75534a47328a8af70213bb6cb36c53 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Sat, 12 Sep 2026 20:51:33 -0400 Subject: [PATCH 1/3] chore: release prep for 0.1.0 (#282) - pkg-r/DESCRIPTION: 0.0.0.9000 -> 0.1.0; trailing slash on the pkgdown URL (CRAN incoming flags the redirect as an invalid URL) - first-release notes: pkg-r/NEWS.md, pkg-py/CHANGELOG.md, pkg-js/CHANGELOG.md --- pkg-js/CHANGELOG.md | 25 +++++++++++++++++++++++++ pkg-py/CHANGELOG.md | 24 ++++++++++++++++++++++++ pkg-r/DESCRIPTION | 4 ++-- pkg-r/NEWS.md | 20 ++++++++++++++++++++ pkg-r/man/shinyreact-package.Rd | 2 +- 5 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 pkg-js/CHANGELOG.md create mode 100644 pkg-py/CHANGELOG.md create mode 100644 pkg-r/NEWS.md diff --git a/pkg-js/CHANGELOG.md b/pkg-js/CHANGELOG.md new file mode 100644 index 00000000..98e837a0 --- /dev/null +++ b/pkg-js/CHANGELOG.md @@ -0,0 +1,25 @@ +# Changelog + +## 0.1.1 + +- First release published through CI with npm trusted publishing + (staged, human-approved). Same code as 0.1.0 plus a README for npm. + +## 0.1.0 + +- Initial npm release as `@posit-dev/shinyreact`. Published by hand to + bootstrap the package; no `js/v0.1.0` tag. + +- ESM entry for bundler-tier apps with React externalized as a peer + dependency, plus type declarations and `@posit-dev/shinyreact/styles`. + +- Hooks: `useShinyInput`, `useShinyInputValue`, `useSetShinyInput`, + `useShinyOutputValue`, `useShinyOutputStatus`, `useShinyOutputError`, + `useShinyMessageHandler`, `useShinyInitialized`, `useShinyBusy`. + +- Components and utilities: `ShinyOutput`, `ImageOutput`, + `ShinyModuleProvider`, `MISSING`. + +- Asserts the wire-protocol major version against the server's + `#shinyreact-config` tag at boot, and warns when a page also serves the IIFE + bundle alongside this package. diff --git a/pkg-py/CHANGELOG.md b/pkg-py/CHANGELOG.md new file mode 100644 index 00000000..9ee15dea --- /dev/null +++ b/pkg-py/CHANGELOG.md @@ -0,0 +1,24 @@ +# Changelog + +## 0.1.0 + +* Initial PyPI release. + +* Server-side plumbing for the `ui.tsx` pattern: the UI is a React client you + own, and the Shiny server contains only reactive computation. + `@reactive_output` sends JSON to `useShinyOutputValue()` hooks, + `send_message()` reaches `useShinyMessageHandler()`, and `set_react_page()` + (Express), `ReactApp` (Core), `page_react()`, `page_react_html()`, + `page_bare()`, and `page_react_dep()` bootstrap the client. + +* Renderer dependencies of traditional Shiny outputs hosted inside a React tree + are discovered automatically, so `ShinyOutput` works with zero configuration. + +* Bookmark restore is delivered through the `#shinyreact-config` script tag, + and the client asserts the wire-protocol major version at boot. + +* `shinyreact.default` and `shinyreact.asis` input handlers give Python and R + the same view of the JSON a hook sends. + +* `shinyreact.playwright.WireTap` records the Shiny websocket for end-to-end + tests. diff --git a/pkg-r/DESCRIPTION b/pkg-r/DESCRIPTION index 3c0720eb..70cd2486 100644 --- a/pkg-r/DESCRIPTION +++ b/pkg-r/DESCRIPTION @@ -1,6 +1,6 @@ Package: shinyreact Title: Shiny UI Infrastructure for Client-Side React Rendering -Version: 0.0.0.9000 +Version: 0.1.0 Authors@R: c( person("Barret", "Schloerke", , "barret@posit.co", role = c("cre", "aut"), comment = c(ORCID = "0000-0001-9986-114X")), @@ -11,7 +11,7 @@ Description: Server-side plumbing for the 'ui.tsx' pattern in Shiny: the UI is defined in a client React bundle, and the Shiny server contains only reactive computation. Ships no UI components. License: MIT + file LICENSE -URL: https://posit-dev.github.io/shinyreact/r, +URL: https://posit-dev.github.io/shinyreact/r/, https://github.com/posit-dev/shinyreact BugReports: https://github.com/posit-dev/shinyreact/issues Imports: diff --git a/pkg-r/NEWS.md b/pkg-r/NEWS.md new file mode 100644 index 00000000..d2a0f440 --- /dev/null +++ b/pkg-r/NEWS.md @@ -0,0 +1,20 @@ +# shinyreact 0.1.0 + +* Initial CRAN release. + +* Server-side plumbing for the `ui.tsx` pattern: the UI is a React client you + own, and the Shiny server contains only reactive computation. + `reactive_output()` sends JSON to `useShinyOutputValue()` hooks, + `send_message()` reaches `useShinyMessageHandler()`, and `page_react()` / + `page_react_html()` / `page_bare()` / `page_react_dep()` bootstrap the + client. + +* Automatic renderer-dependency discovery: dependencies of traditional Shiny + outputs hosted inside a React tree are pushed to the client after each + flush, so `ShinyOutput` works with zero configuration. + +* Bookmark restore is delivered through the `#shinyreact-config` script tag, + and the client asserts the wire-protocol major version at boot. + +* `shinyreact.default` and `shinyreact.asis` input handlers give R and Python + the same view of the JSON a hook sends. diff --git a/pkg-r/man/shinyreact-package.Rd b/pkg-r/man/shinyreact-package.Rd index 2993ffb5..bf31be2c 100644 --- a/pkg-r/man/shinyreact-package.Rd +++ b/pkg-r/man/shinyreact-package.Rd @@ -13,7 +13,7 @@ Server-side plumbing for the 'ui.tsx' pattern in Shiny: the UI is defined in a c \seealso{ Useful links: \itemize{ - \item \url{https://posit-dev.github.io/shinyreact/r} + \item \url{https://posit-dev.github.io/shinyreact/r/} \item \url{https://github.com/posit-dev/shinyreact} \item Report bugs at \url{https://github.com/posit-dev/shinyreact/issues} } From 0415fd404b2380d990ad9a9a4e7e6966de2d4f41 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Sat, 12 Sep 2026 20:57:04 -0400 Subject: [PATCH 2/3] build(py): require shiny>=1.8.0, drop the py-shiny git dependency py-shiny#2475 (ui.page_html()) shipped in shiny 1.8.0, so the git reference on py-shiny main and hatch's allow-direct-references go away. PyPI rejects direct URL dependencies, so this was the last blocker for py/v0.1.0. --- CLAUDE.md | 2 +- FEATURES.md | 9 ++++----- pyproject.toml | 8 ++------ 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 3e6cb5f7..a6e381a5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -124,7 +124,7 @@ Rules if you find yourself adding a third: - `shinyreact.set_react_page(path=None)` — Express helper; with no args serves `www/index.html` when present, else discovers `www/ui.js` / `www/ui.css` and emits no body HTML. Auto-discovers `HTMLDependency` objects from traditional Shiny renderers and injects the shinyreact dep. `page_opts()` options reach the page (`page_auto()` splats them into our `page_fn`): the no-HTML-file mode honors `title` / `lang` / `theme`; anything else, and any option at all in HTML-file mode, raises a `TypeError` naming it - `shinyreact.page_react(*args, src_dir=None, js_file="ui.js", css_file="ui.css", title=None, lang="en", **kwargs)` — Core-mode zero-config page: discovers `www/ui.js` / `www/ui.css` next to the calling module, serves them as an mtime-versioned dependency (cache-busted), title defaults to the app folder name; the client appends its own mount container to `` - `shinyreact.ReactApp(server, *, ui=None, static_assets=MISSING, bookmark_store="disable", **kwargs)` — `shiny.App` for the ui.tsx pattern with the UI discovered next to the calling module: `www/index.html` present → `page_react_html()`, else → `page_react()`. The discovered UI is a per-request function, so bookmark restore works with no wiring (`ReactApp(server, bookmark_store="url")`); `ui=page_react_html(...)` + a bookmark store raises, since one already-built document can't restore. The React asset dir is mounted at `/`, and a passed `static_assets` mapping is **merged with** that mount rather than replacing it — the author wins only on collision (`"/"` key, a bare path, or `None` for nothing). `static_assets` defaults to `MISSING`, not `None`, so `None` can mean "mount nothing". `ui=` overrides discovery (a `page_react_html()` document still gets its dir mounted); discovery reads the *immediate* calling frame, so helpers wrapping `ReactApp(...)` must pass `ui=` -- `shinyreact.page_react_html(path="www/index.html")` — Core-mode helper for apps that own a complete HTML document containing `` (py-shiny's `ui.page_html()` default `deps_replace_pattern=`); Shiny's and shinyreact's tags render in its place. Rarely called directly — `ReactApp` discovers it (plain `shiny.App` works too via `ui.page_html()`, consumed as a git dep on py-shiny `main` until py-shiny#2475 releases — issue #216). Does not auto-discover renderer dependencies +- `shinyreact.page_react_html(path="www/index.html")` — Core-mode helper for apps that own a complete HTML document containing `` (py-shiny's `ui.page_html()` default `deps_replace_pattern=`); Shiny's and shinyreact's tags render in its place. Rarely called directly — `ReactApp` discovers it (plain `shiny.App` works too via `ui.page_html()`, which needs `shiny>=1.8.0`). Does not auto-discover renderer dependencies - `shinyreact.page_bare(*args, title=None, lang="en", **kwargs)` / `shinyreact.page_react_dep(*, src_dir=None, js_file="ui.js", css_file="ui.css", name=None)` — escape-hatch page builder and app-bundle `HTMLDependency` helper. Neither takes `theme=` or `version=`: styling belongs to the React client, not Bootstrap, and a package needing a fixed version builds its own `HTMLDependency`. `**kwargs` / R's `...` still reach `page_bootstrap()` / `bootstrapPage()`. With no `theme`, `page_bare()` (and so `page_react()`) attaches **no Bootstrap** — jQuery, Shiny's own JS/CSS, and a viewport meta tag, nothing else (#285). Passing a theme restores the plain passthrough - Bookmark restore + protocol handshake: page entry points emit a `