WP Manifestindependent plugin directory
manifest / developer / prc-scripts

PRC Scripts

Shared first-party (@prc/*) and third-party JavaScript, stylesheets, and script modules for the PRC Platform. Registers Scripts and Script_Modules so leaf plugins can Requires Plugins: prc-scripts and consume the handles.

★ 0stars

Install

Download source zip No release zip yet

This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/pewresearch/prc-scripts/archive/refs/heads/trunk.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

Canonical docs: docs/plugins/prc-scripts/

Shared first-party (@prc/*) and third-party JavaScript, stylesheets, and script modules for all PRC Platform plugins.

This plugin owns the Scripts and Script_Modules registration classes that were previously bundled inside prc-platform-core. Every leaf prc-* plugin that consumes shared script handles (e.g. prc-components, prc-controls, prc-charting-utilities) declares Requires Plugins: prc-scripts in its main plugin file header.

PHP namespaces (PRC\Platform\Scripts, PRC\Platform\Script_Modules) are unchanged from the previous home so REST API endpoint classes that hardcode them keep working.

Layout

  • includes/scripts/ — first-party @prc/* and third-party JavaScript / CSS source + build artifacts.
  • includes/script-modules/ — @prc/d3 and @prc/topojson script modules.
  • includes/scripts/src/third-party/d3/ and d3-v7/ — UMD bundles exposed as window.d3 and window.d3v7 for webpack externals.
  • includes/class-bootstrap.php — wires the moved classes into the new plugin's Loader.

Third-party D3 globals

Legacy chart and interactive bundles externalize D3 to script handles built from the UMD d3/dist/d3.js entry (not d3/src, which breaks under npm workspaces). Each webpack build must export the populated UMD global as the library default:

Build output Global Typical consumer import
build/third-party/d3/ window.d3 d3 external in older interactives
build/third-party/d3-v7/ window.d3v7 import * as d3 from 'd3v7'

A bare export * from 'd3' against the UMD file produced an empty module object and overwrote window.d3 / window.d3v7 with {}, breaking d3.select at runtime. The entry files re-export globalThis.d3 after importing the UMD bundle (see comments in includes/scripts/src/third-party/d3/index.js).

Rebuild both vendors after changing D3 versions:

npx turbo build --filter=@prc/scripts

Load order

prc-scripts is registered in client-mu-plugins/plugin-loader.php after prc-icon-library / prc-post-publish-pipeline and immediately before prc-block-library, ensuring its handles are available before any plugin that lists it in Requires Plugins:.

Storybook

The monorepo ships a root Storybook (.storybook/) that discovers stories colocated with @prc/* modules under plugins/prc-scripts/includes/scripts/src/@prc/ and chart stories under plugins/prc-charting-library/src/. This mirrors the centralized Playwright setup — one config at the repo root, stories next to the components they document.

# Dev server (http://localhost:6006)
npm run storybook

# Static build
npm run build-storybook

How it differs from production builds

Production webpack builds externalize every @prc/* import to window.* globals via dependency-extraction.js. Storybook inverts that: .storybook/main.ts aliases @prc/components, @prc/controls, @prc/hooks, @prc/icons, @prc/functions, @prc/charting-utilities, and @prc/charting-library to their source trees so components render with real imports.

Charting-library stories additionally alias useChartStore to its editor stub (useChartStore.editor.ts) so Interactivity API state is not pulled into the browser bundle.

Mocks and decorators

Path Purpose
.storybook/mocks/api-fetch-handlers.ts Offline REST fixtures for apiFetch (terms, posts, Mailchimp segments, etc.)
.storybook/mocks/window-globals.ts Seeds window.prc* globals when a story needs production-style externals
.storybook/decorators/with-editor.tsx Minimal block-editor shell
.storybook/decorators/with-block-editor.tsx Full inserter + block canvas for editor-dependent components

Import decorators via the @prc-storybook alias (e.g. import { withBlockEditor } from '@prc-storybook/decorators/with-block-editor').

Adding a story

  1. Colocate *.stories.tsx (or *.mdx) next to the component under plugins/prc-scripts/includes/scripts/src/@prc/<package>/.
  2. For editor-dependent UI, wrap with withBlockEditor or withEditor.
  3. For REST-backed controls, add or extend fixtures in .storybook/mocks/api-fetch-handlers.ts.
  4. Icon stories rely on committed FontAwesome sprites served from .storybook/main.ts staticDirs at the same /wp-content/plugins/prc-icon-library/... path production uses.

Charting-library chart type stories live under plugins/prc-charting-library/src/ and are picked up by the same root config.

@prc/components (selected exports)

Shared React UI under includes/scripts/src/@prc/components/, exported from @prc/components (handle prc-components). Documented here when multiple plugins consume the same primitive.

CalendarHeatmap + AnalyticsPeriodControls

Year/month analytics picker used by dataset and quiz inspector panels (prc-datasets stats sidebar, prc-quiz-builder quiz analytics).

import {
  AnalyticsPeriodControls,
  CalendarHeatmap,
  MONTH_LABELS,
  monthKeyFromIndex,
} from '@prc/components';

// Month grid: click a cell to drill into daily breakdown for that month.
<CalendarHeatmap
  values={monthlyTotals}          // length 12 (Jan–Dec)
  onCellClick={(index) => setMonth(monthKeyFromIndex(index))}  // "01"–"12"
  highlightIndex={selectedMonth ? Number(selectedMonth) - 1 : null}
  getTooltipText={(v) => v.toLocaleString()}
  renderValue={(v) => formatCompactNumber(v)}
/>

<AnalyticsPeriodControls
  years={availableYears}
  selectedYear={year}
  onYearChange={setYear}
  selectedMonth={month}             // "" = all months
  onMonthChange={setMonth}
/>

monthKeyFromIndex(0) → "01" (January). onCellClick and highlightIndex are optional; without them cells are display-only.

AudienceBuildPanel

DataForm-backed audience cards for Firebase audience builds. Used by prc-datasets, prc-quiz-builder, and prc-email-builder transactional hub.

Props surface audiences: AudienceSnapshot[] (verified / unverified / all counts, builtAt, optional job stats), async status, and callbacks onBuild, onRebuild, onDelete, plus optional onCreateDraft. Each card renders read-only DataForm fields and an Update action that calls onRebuild for that verification mode. In-flight job states (queued, scanning, building) disable actions via isAudienceJobInFlight().