@ydtb/tk-scope-data-workbench
v0.24.0
Published
Saved-view-driven data workbench primitives for tk-scope tools.
Readme
@ydtb/tk-scope-data-workbench
Primitive family for saved-view-driven record exploration surfaces.
The package intentionally starts with contracts and state hooks rather than a monolithic <DataWorkbench /> component. Tools keep domain-specific APIs, row renderers, permissions, and export implementations.
Current exports
Contracts
WorkbenchFieldWorkbenchFieldTypeWorkbenchSavedViewWorkbenchColumnStateWorkbenchSortStateWorkbenchPaginationStateWorkbenchSelectionStateFieldManagementCapability
Saved view state
useWorkbenchViewState(...)isWorkbenchStateDirty(...)cloneWorkbenchState(...)
Use this to hydrate local working state from an active saved view, compare against a saved snapshot, expose dirty state, save, and reset.
Field registry adapters
adaptWorkbenchColumns(...)fieldsToFilterFields(...)fieldsToExportFields(...)dedupeWorkbenchFields(...)persistWorkbenchColumns(...)normalizePersistedColumns(...)defaultIconKeyForFieldType(...)
Use these to map a dataset field registry into column/filter/export surfaces. The column adapter preserves saved visibility/order, appends newly available fields hidden by default, and keeps orphaned saved columns as hidden unavailable fields.
Optional managed context
DataWorkbenchProvideruseDataWorkbench()useOptionalDataWorkbench()createDataWorkbenchContextValue(...)
Use this when a tool wants shared children (headers, sidebars, tables, drawers) to read the same active view, working state, dirty/save status, fields, pagination, selection, and field-management capability without prop-drilling. The lower-level hooks remain direct exports and can still be used without the provider.
Field management capability
FieldManagementCapabilitycanCreateWorkbenchField(...)canEditWorkbenchField(...)canDeleteWorkbenchField(...)canCreateWorkbenchFieldOption(...)disabledFieldManagementCapability()
Use this to describe whether a dataset supports user-managed fields. Contacts enables creation/options; fixed datasets like Signals can use the disabled capability.
Export panel
WorkbenchExportPanelcountWorkbenchFilterConditions(...)getWorkbenchExportFilterSummary(...)getWorkbenchExportTabs(...)
Use this as the shared TabbedPanel shell for contacts-style exports. Tools own the actual export form, API call, file download, and domain-specific filter visualization; the workbench shell owns canonical Export / Filters tabs, heading chrome, and filter-count summary helpers.
Filter panel
WorkbenchFilterPanelformatWorkbenchFilterResultCount(...)
Use this to wrap the shared UI FilterPanel in a workbench-shaped layout with optional narrowing content (for example source selection), empty-fields messaging, and a result-count footer.
Column panel
WorkbenchColumnPaneltoUiColumnConfig(...)toWorkbenchColumnConfig(...)mergeUiColumnChanges(...)WORKBENCH_COLUMN_ICON_MAP
Use this to render the shared column visibility/order/search UI from workbench column configs while preserving workbench-only metadata such as iconKey, unavailable, and dataset source.
Saved views sidebar section
WorkbenchSavedViewsSidebarSectiongetSavedViewsSidebarSectionState(...)
Use this inside a tool-owned sidebar to render saved-view navigation without giving the package ownership of the entire tool sidebar. It supports active view highlighting, loading/empty/count states, optional create action, optional badges, and optional pin/favorite preference controls.
Header controls
WorkbenchSaveResetControlsgetWorkbenchSaveResetDisabledState(...)
Use these inside a tool's ToolPageHeader actions to keep dirty view Save/Reset behavior consistent across workbenches.
Pagination
useWorkbenchOffsetPagination(...)useWorkbenchCursorPagination(...)- offset helpers:
normalizeOffsetPage,offsetForPage,totalPagesFor - cursor helpers:
createInitialCursorPagerState,advanceCursorPager,retreatCursorPager
Default behavior for consumers:
- pagination is session UI state, not saved-view identity
- reset pagination when view/filter/sort/source changes
- offset mode uses
page,pageSize, and optionaltotal - cursor mode tracks current cursor, next cursor, page index, and previous-page history
Selection
useWorkbenchSelection(...)toggleSelectionId(...)clearSelection(...)
Default behavior for consumers:
- selection is page-local
- clear selection on page/view changes
- cross-page selection should be an explicit future capability, not default behavior
Umbrella docs
docs/data-workbench.mddocs/data-workbench-mission-control.mdplans/data-workbench-roadmap.mdplans/data-workbench-slices.md
Usage examples
Fixed/source-derived dataset (Case Scouting Signals)
const workbenchView = useWorkbenchViewState({
viewKey: resolvedViewId,
savedView: activeView,
getStateFromSavedView: savedConfigFromView,
saveState: saveWorkbenchState,
serializeState: comparableViewConfig,
})
const pagination = useWorkbenchOffsetPagination({
pageSize: 50,
resetKeys: [filters, selectedSources, sorts, resolvedViewId],
})
const selection = useWorkbenchSelection({
resetKeys: [resolvedViewId, pagination.page],
})
<WorkbenchSaveResetControls
isDirty={workbenchView.isDirty}
isSaving={workbenchView.isSaving}
onSave={() => void workbenchView.save()}
onReset={workbenchView.reset}
/>Signals keeps source registry construction, row rendering, bulk actions, and export execution in the Case Scouting tool.
Editable-field dataset (Contacts)
const fieldManagement: FieldManagementCapability<CreateFieldInput> = {
enabled: true,
canCreate: true,
createField,
}
if (canCreateWorkbenchField(fieldManagement)) {
await fieldManagement.createField(input)
}
<WorkbenchColumnPanel
columns={toWorkbenchColumns(columns)}
onColumnsChange={(updated) => onColumnsChange(mergeColumns(updated, columns))}
footer={<CreateFieldButton />}
/>Contacts keeps custom-field creation forms, option colors, inline edits, and permissions in the Contacts tool.
Optional provider
const value = createDataWorkbenchContextValue({
activeView,
activeViewId,
fields,
viewState,
pagination,
selection,
fieldManagement,
})
return <DataWorkbenchProvider value={value}>{children}</DataWorkbenchProvider>The provider is optional. Direct hooks/adapters remain first-class.
