@wordpress/dataviews is a bundled package — it declares neither wpScript nor wpModuleExports in its package.json. Per AGENTS.md:
Avoid using private APIs in bundled packages (packages without wpScript or wpModuleExports). Private APIs are intended for Core usage; bundled packages may also be imported via npm into plugin scripts, causing incompatibilities.
Concretely: lockedData is a module-scoped WeakMap and __private is a plain Symbol() — not Symbol.for() (implementation.ts#L187-L193). Two copies of @wordpress/private-apis in one runtime cannot unlock each other's objects, so a plugin that loads wp.components from the WP global alongside a bundled DataViews throws Cannot unlock an object that was not locked before at module-eval time, before anything renders.
Secondary cost: unlock() is typed <T = any>( object: unknown ): T, so every unlocked symbol lands as any. All 23 call sites below are effectively unchecked by TypeScript — swapping any of them for a public equivalent tends to surface pre-existing type mismatches.
@wordpress/components
18 of the 25 symbols in components/src/private-apis.ts, across 21 production files:
| Symbol |
Where |
Why it's private |
Menu |
add-filter.tsx:22, dataviews-view-config/index.tsx:37, dataviews-item-actions/index.tsx:27, column-header-menu.tsx:33, list/index.tsx:62 |
Ariakit-based menu; no public replacement exists yet — @wordpress/ui has no menu |
Badge |
picker-grid/index.tsx:36, composite-grid.tsx:45 |
A public Badge already ships in @wordpress/ui and DataViews uses it in validation-badge.tsx — this one is a stale holdout |
kebabCase |
dataviews-item-actions/index.tsx:27 |
String util, private to avoid committing to a public utils surface |
DateCalendar, DateRangeCalendar |
date.tsx:57, datetime.tsx:24 |
New calendar components still stabilizing |
withIgnoreIMEEvents |
richtext/control.tsx:47 |
IME keydown wrapper |
Validated* × 12 |
one per control in dataform-controls/ — InputControl, Checkbox, Combobox, Number, Select, Radio, ContentEditable, Textarea, Toggle, ToggleGroup, FormTokenField (+Text in a story) |
The whole validated-form-controls layer is private; DataForm is its only real consumer |
@wordpress/rich-text
5 of the 9 symbols in rich-text/src/private-apis.js, all in one file — dataform-controls/richtext/control.tsx:
| Symbol |
Where |
Why it's private |
useRichText |
richtext/control.tsx:61 |
Core editing hook; the public surface is RichText in @wordpress/block-editor, which DataViews can't depend on |
KeyboardShortcutContext, InputEventContext |
richtext/control.tsx:61 |
The same context objects that format types' RichTextShortcut / RichTextInputEvent read |
shortcutsListener, inputEventsListener |
richtext/control.tsx:61 |
Dispatch the registered callbacks from the editable element's own events |
Exposed by DataViews
Todo
Ordered by effort — the first three are unblocked today.
@wordpress/dataviewsis a bundled package — it declares neitherwpScriptnorwpModuleExportsin itspackage.json. PerAGENTS.md:Concretely:
lockedDatais a module-scopedWeakMapand__privateis a plainSymbol()— notSymbol.for()(implementation.ts#L187-L193). Two copies of@wordpress/private-apisin one runtime cannot unlock each other's objects, so a plugin that loadswp.componentsfrom the WP global alongside a bundled DataViews throwsCannot unlock an object that was not locked beforeat module-eval time, before anything renders.Secondary cost:
unlock()is typed<T = any>( object: unknown ): T, so every unlocked symbol lands asany. All 23 call sites below are effectively unchecked by TypeScript — swapping any of them for a public equivalent tends to surface pre-existing type mismatches.@wordpress/components18 of the 25 symbols in
components/src/private-apis.ts, across 21 production files:Menu@wordpress/uihas nomenuBadgeBadgealready ships in@wordpress/uiand DataViews uses it in validation-badge.tsx — this one is a stale holdoutkebabCaseDateCalendar,DateRangeCalendarwithIgnoreIMEEventsValidated*× 12InputControl,Checkbox,Combobox,Number,Select,Radio,ContentEditable,Textarea,Toggle,ToggleGroup,FormTokenField(+Textin a story)@wordpress/rich-text5 of the 9 symbols in
rich-text/src/private-apis.js, all in one file —dataform-controls/richtext/control.tsx:useRichTextRichTextin@wordpress/block-editor, which DataViews can't depend onKeyboardShortcutContext,InputEventContextRichTextShortcut/RichTextInputEventreadshortcutsListener,inputEventsListenerExposed by DataViews
RichTextControldataviews/src/private-apis.ts, unlocked by editornote-form.js:28Todo
Ordered by effort — the first three are unblocked today.
Badge— DataViews: Use the public@wordpress/uiBadge instead of the private one #81236kebabCase— DataViews: removekebabCaseprivate import by inlining it #81284 and Newkebab-casepackage: extract utility and migrate private API calls #81294withIgnoreIMEEvents— Keycodes: MakewithIgnoreIMEEventsa public API #81343Validated*— @mirkaSpinnercomponent to wp-ui UI: Add Spinner component #81358ValidatedTextControlComponents: Remove ValidatedTextControl private API #80680ControlWithErrorandValidityIndicatorto wp-ui (depends onSpinner)TextareaControlin wp-ui UI: Add TextareaControl component #81359ValidatedInputControlandValidatedTextareaControlin wp-ui (with new components)ValidatedNumberControl#81433ValidatedCheckboxControl#81435ValidatedSelectControl#81391ValidatedRadioControl#81434ValidatedComboboxControl#81449ValidatedToggleGroupControl#81450ValidatedFormTokenField#81451ValidatedContentEditableControl: no longer necessary, richtext dependency removed.ValidatedToggleControlas a private API in wp-components for wp-content-types usage, to be replaced later by a new version in wp-uiDateCalendar/DateRangeCalendar— UI: AddCalendarandRangeCalendar, moved fromcomponentsprivate APIs #81337Menu(5 sites) — @ciampo Menu: Add UI component #79560rich-text× 5 (1 site) — needs a public way to build a rich-text field outside@wordpress/block-editor. The largest single item; likely its own issue once the shape is known.RichTextControl— make it a public DataViews export, or move it into@wordpress/editoralongside its only consumer.@wordpress/private-apisfrompackages/dataviews/package.jsonand deletelock-unlock.tsandprivate-apis.ts.