This release completes the plotting, interface, statistics, and reporting work started in 0.3.3. Every analysis family now has a chart, every effect size ships with a confidence interval, reports accept written interpretations and print to PDF, both dashboards gain quality and correlation panels, date questions gain bounds, and the builder and vignettes pass a WCAG 2.2 AA accessibility audit. Hard dependencies are unchanged. naniar and pagedown join Suggests.
bootstrap_ci() (percentile
bootstrap for any statistic), cohens_d_ci(), cramers_v_ci(), and
eta_sq_ci().d_ci on the t-tests, r_ci on Mann-Whitney and
Wilcoxon, eta_ci on ANOVA and Kruskal-Wallis, ci on the correlations
(analytic Fisher z for Pearson, bootstrap for the rank methods), and
v_ci on chi-square and cross-tabulation.d = 0.62 [0.18, 1.05]. Data too small for an interval keeps the
previous string.validity_report() computes the Henseler heterotrait-monotrait ratio
when item-level data is supplied through the new items_by_construct
argument. Without it, the previous correlation-based fallback applies
and the htmt_method element records which was used.missing_data_report() runs Little's MCAR test when naniar is
installed. Without naniar the result is unchanged.reliability_report() records why omega is unavailable for a scale in
an omega_note, and the reliability chart names those scales in its
subtitle.efa_solution() adds three tidy data frames ready for plotting and
reporting: loadings_long, communalities_table, and
variance_table.render_report(format = "pdf") prints the HTML report to PDF through
pagedown, which requires a local Chrome or Chromium. HTML output is
unchanged and remains the default.interpretations argument on render_report() and
render_results(). Pass a named list keyed by analysis-plan block id to
add a written interpretation to each research question after the results
are known. The report shows it beside the pre-declared decision rule, so
the prospective plan stays visible next to the post-hoc narrative.
Interpretations are report content only and are never written into the
instrument file.run_analysis_plan(plots = TRUE) now attaches a chart to every
supported family: regression diagnostics (4 panels), EFA scree and
loadings heatmap, reliability bars, mosaic and crosstab, correlation
heatmap, quality flag rates, group-comparison boxplots, paired slope
charts, raw-variable distributions, repeated-measures profiles, a
partial-correlation residual scatter, logistic-regression odds-ratio
forest plots, a moderation interaction plot, and a mediation effect
chart. Every analysis-plan block now returns a table, a chart, or
generated syntax.plot() methods for descriptives, EFA, quality, reliability,
validity, missing-data, and analysis-results objects. plot(results)
draws every attached chart, and plot(results, which = "rq_id") returns
one.plot_palette argument on run_analysis_plan() and
render_report(): "web" for brand colour on screen, "print" for
black and white suitable for print and journal submission. SurveyStudio
exposes the choice as a Chart theme option on the Export screen.date_min and date_max bounds in sf_item(),
the SurveyBuilder, and the exported survey. The date picker enforces the
bounds and typed dates outside them show a clear message.read_responses() produces.sf_item()'s date_min and date_max no longer accept an ambiguous
date string (for example "01/02/2024"); only "YYYY-MM-DD" or a
Date object is accepted, and anything else is a validation error
rather than a silently misparsed date.bootstrap_ci(), cohens_d_ci(), cramers_v_ci(), and eta_sq_ci()
no longer alter the random-number seed for code that runs after a
reproducible, seeded call.This release adds an opt-in plotting layer, fixes bugs surfaced by the package's first field deployment, and redesigns the survey-taking experience. ggplot2 joins Suggests; hard dependencies are unchanged.
plots argument on run_analysis_plan() (default FALSE). When
TRUE, supported analysis blocks return a ggplot object in $plot: bar
charts for frequency and chi-square blocks, and scatter plots with a
regression overlay for correlation and regression blocks.theme_surveyframe(), a publication-oriented ggplot2 theme
with an accessible fixed-order series palette. All plots use it.$table data frame ready for
knitr::kable(); the HTML report shows these tables automatically.item__option = 1 for the top choice), so ranks are directly analysable.
Multiple-choice items likewise export one 0/1 column per option instead
of a single comma-joined column. read_responses() accepts the expanded
columns for ranking, matrix, and multiple-choice items without warnings.render_report() now attaches each analysis block's chart directly under
its result table, in both the Quarto and internal HTML report paths,
instead of tables and plots appearing in separate places.read_sheet_responses() gains a meta_cols argument for extra sheet
columns a host application appends, and SurveyStudio's dashboard now
computes completion times from imported sheet responses.sem_lavaan_syntax() turns free-text path labels into valid lavaan
parameter names (a label starting "H1:" becomes the parameter H1).seminr_syntax() output loads seminr and uses summary() accessors, so
the generated code runs as pasted.run_analysis_plan() accepts pls_sem as an alias for seminr_syntax..sframe verifies and reports its SHA-256 integrity status.This release corrects the package citation, completes the S3 method surface for the component classes, and improves the graphical tools and the HTML report. It adds no new exported functions, no new statistical methods, and no new bundled datasets.
inst/CITATION now reports the correct package title and reads the version
dynamically from the package metadata, so the citation no longer pins an old
version or an outdated title.print(), format(), and summary() methods for the component
classes sf_choices, sf_item, sf_scale, sf_branch, sf_check, and
sf_model, so each class now has a visible, documented S3 surface.lavaan is declared in Suggests. It is used only to fit the syntax produced
by cfa_syntax(). The package itself generates syntax and never requires
lavaan to be installed.export_static_survey() and export_google_sheet().render_report() renders reliably through Quarto when it is installed. A path
defect that made the Quarto render fail and fall back to the plain internal
output is fixed.This is a patch release. It fixes the static-survey to Google Sheets to R collection loop, repairs a serialisation defect, and improves the first-time user experience. There are no new exported functions, no new statistical methods, and no new bundled datasets.
export_static_survey() now renders the header logo and institution name
from render$header, so exported surveys match the Shiny renderer and
the builder preview.export_static_survey() now falls back to the instrument's
render$google_sheets_endpoint when endpoint_url is not supplied, so
a Google Sheets endpoint set in the builder is honoured on export.respondent_id, matching the Google Apps Script collector and
read_responses(). The collection round-trip now preserves the identifier.export_google_sheet() now includes matrix sub-item columns
(item_id__sub) in the Apps Script header row, so matrix answers are
stored in the Sheet.read_sheet_responses() now declares started_at as a meta column and
no longer raises a warning on every read.image/png, image/jpeg,
image/gif), so JPEG and GIF logos display correctly in the builder,
the Shiny renderer, and the static export.write_sframe() now strips list-level names from the item, choice, scale,
branching, check, and model collections before serialisation. Instruments
built with Map() or other helpers that attach element names (for example,
using item IDs as names) previously serialised those collections as keyed
JSON objects rather than arrays. This produced a hash mismatch and an
integrity error on read_sframe(). Saved instruments now round-trip
correctly regardless of how the component lists were constructed.sframe object.
The message points the user to sf_instrument() and read_sframe()
instead of showing a raw inherits() assertion failure.reliability_report() no longer prints psych internal warnings to the
console. McDonald's omega is skipped silently for scales with fewer than
three items, where the statistic is not meaningful.run_analysis_plan() when no analysis plan is
present now describes both the programmatic route
(instrument$analysis_plan) and the visual SurveyBuilder route.surveyframe.Rmd) as an end-to-end worked
example: design the questionnaire, export it as a hosted survey with a
Google Sheets backend, collect responses, score them, run the analysis
plan, and render a report. The results section uses simulated responses so
the vignette builds offline; a single read_sheet_responses() call
connects the same workflow to live responses. The questionnaire and concept
are adopted from Sharafuddin, Madhavan, and Wangtueai (2024,
Administrative Sciences, 14(11), 273,
), with generic destination wording so the
example transfers to any tourism services context.sf_instrument() examples now include a complete analysis_plan block.install.packages("surveyframe"), adds a short
path for users who already have a response CSV, and points to
browseVignettes("surveyframe").The first CRAN release of the full workflow: a typed instrument object carrying the questions, the analysis plan, and the measurement model, with deployment, collection, analysis, and reporting built around it.
variables/test analysis blocks. New plans can store family, method,
roles, options, hypotheses, decision_rule,
reporting_references, status, and requires_data.descriptives_report(),
missing_data_report(), assumption_report(), posthoc_report(),
validity_report(), and sample_size_plan().run_analysis_plan() to dispatch the v0.3 method registry,
including descriptives, missing data, sparse-table tests, related-sample
tests, Kendall and partial correlations, two-way ANOVA, ANCOVA, repeated
ANOVA, ordinal and multinomial logistic regression, mediation, moderation,
and model-syntax output.sf_construct(), sf_path(),
sf_covariance(), sf_indirect(), sf_model(), validate_model(),
model_json(), add_model(), efa_solution(), efa_syntax(),
cfa_lavaan_syntax(), sem_lavaan_syntax(), seminr_syntax(), and
model_report_template(). Syntax generation does not require lavaan or
seminr.cfa_syntax() remains available as a backward-compatible wrapper around
cfa_lavaan_syntax().export_static_survey(). This produces a single, self-contained
HTML file that runs the survey in any modern browser without a Shiny
server or an internet connection. All thirteen item types are fully
rendered (Likert, single choice, multiple choice, matrix, numeric, text,
long text, date, slider, rating, ranking, section break, text block).
Branching logic, required-field validation, a progress bar, welcome and
thank-you pages are all handled in client-side JavaScript. On submission
the browser downloads a per-respondent CSV file. An optional
endpoint_url argument adds a parallel JSON POST to any serverless
endpoint (Google Apps Script, Netlify function, etc.).The exported file is suitable for hosting on GitHub Pages, Netlify, or any static file server, and can also be shared directly as an e-mail attachment and opened from disk.
The SHA-256 hash written into .sframe files by write_sframe() and by
the SurveyBuilder HTML is computed using the same canonicalisation
algorithm, so instruments round-trip correctly between the browser and R.
launch_dashboard(). Opens a five-panel Shiny dashboard for
exploring collected response data alongside the instrument definition,
without modifying either. The panels are: Overview (response count, date
range, instrument metadata), Items (per-item bar charts, histograms, and
frequency tables), Scales (scale score distributions with mean overlay),
Quality (attention-check pass rates), and Raw data (a scrollable response
table with CSV download).When called without arguments the dashboard loads the bundled tourism
services demo. When called with a user-supplied instrument and no
responses argument, it opens in metadata-only mode showing instrument
structure.
Added sframe_demo_data(), sframe_input_types_demo_data(),
launch_builder_demo(), launch_studio_demo(), and
launch_dashboard_demo() for CRAN-safe examples, training, and local GUI
testing.
Added a bundled input-types demo instrument and simulated response dataset for testing SurveyBuilder, SurveyStudio, the dashboard, and all supported item controls.
launch_studio() now accepts preloaded instruments, response data frames,
CSV response paths, initial screen selection, host, port, and browser
control. SurveyStudio reads these preloaded values during startup.
survey_module_ui() and survey_module_server(). These allow a
survey to be embedded inside a larger Shiny application as a first-class
module. survey_module_server() returns a reactive that holds NULL
until the form is submitted, then returns the response as a named list
keyed by item ID.r
ui <- fluidPage(survey_module_ui("s1"))
server <- function(input, output, session) {
resp <- survey_module_server("s1", instrument = instr)
observeEvent(resp(), { saveRDS(resp(), "response.rds") })
}
An optional on_submit callback fires immediately on submission, before
any observeEvent() elsewhere in the app.
run_analysis_plan() now implements four additional tests used by the
SurveyBuilder's test dropdown:
anova_one: One-way ANOVA with eta-squared effect size. When the
result is significant and there are more than two groups, Tukey HSD
post-hoc output is included in the result object.t_test_pair: Paired-samples t-test with Cohen's d_z.wilcoxon_pair: Wilcoxon signed-rank test with r effect size.regression_logistic_binary: Binary logistic regression with
McFadden R-squared and an overall model chi-square test. The full
coefficient table is returned for interpretation.All four runners produce an APA-formatted summary string and an
interpretation prompt field to guide write-up.
write_sframe() validates the instrument and writes the validated object,
preserving meta$validated = TRUE in the saved .sframe file..sframe serialisation now includes a models field and continues to read
older .sframe files where models is absent.read_responses() no longer requires display-only items such as
section_break and text_block to appear as response columns.validate_sframe() now checks model references, analysis-plan roles,
invalid model IDs, duplicate model IDs, and model indicator/path integrity.
launch_builder(open = TRUE) opens the SurveyBuilder HTML in the system's
default browser via utils::browseURL().
R/studio_builder.R contains three fully implemented internal
functions (sframe_builder_empty_state, sframe_builder_state_from_instrument,
sframe_builder_validate_draft) used by SurveyStudio startup and draft
validation.crypto.subtle is unavailable on
file:// origins, including common Firefox file:// configurations.
Saving a .sframe file from the builder now always succeeds.rqSuggest box now appears with an icon and a
plain-language recommendation when two or more variables are selected in
the RQ modal.export_google_sheet() now writes Google Apps Script using JSON-encoded
JavaScript literals instead of interpolating instrument metadata directly
into executable code. The generated endpoint also rejects missing,
over-large, and non-object JSON POST bodies..sframe and .csv
files by extension, size, and text-content checks before passing them to
import functions.read_sframe() now validates the top-level .sframe payload structure
before hash verification and object reconstruction.on.exit() even when rendering fails.validate_sframe(), score_scales(), codebook_report(), cfa_syntax(),
and launch_builder(open = FALSE) have fully runnable examples.launch_builder_demo(), launch_studio_demo(), and
launch_dashboard_demo()) open in the browser with the demo instrument,
scales, and analysis plan preloaded, so no manual file loading is needed.demo("survey")) walks through the whole
workflow with step-by-step prompts.sf_instrument(), sf_item(), sf_choices(),
sf_scale().write_sframe(), read_sframe() with SHA-256 integrity
checking.render_survey().launch_builder().read_responses().Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.