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.

by Pew Research Center · github.com/pewresearch/prc-scripts · website

0stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/pewresearch/prc-scripts/archive/refs/heads/trunk.zip

Readme

PRC Scripts

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().

Read the full README on GitHub →