feat(enterprise): split dockview-modules into published dockview-enterprise

Turn the enterprise tier on by making the feature-module package a
separately-published, self-activating package, and decoupling it from the
free `dockview` package.

Package:
- Rename dockview-modules -> dockview-enterprise (directory + manifest);
  drop `private`, set `sideEffects: true`, depend ONLY on `dockview` at an
  exact version, re-export it (`export * from 'dockview'`) so the package
  is a drop-in superset (mirrors ag-grid-enterprise -> ag-grid-community).
- Repoint all source off `dockview-core` onto `dockview`; rollup now
  externalizes `dockview`.
- Add LicenseModule to the Modules bundle and self-register on import
  (registerModules(Modules)) — importing the package activates the feature
  modules and the license watermark-unless-licensed check.

Free dockview:
- Remove `registerModules(Modules)` and the dockview-modules devDep +
  rollup bundling. `dockview` is now a thin re-export of `dockview-core`;
  the feature modules ship only via `dockview-enterprise`.

Consumers/config:
- Rename across nx.json, root scripts, tsconfig(s), sonar, jest configs
  (+ a new `^dockview$` mapper), vite, docusaurus, systemjs, playwright.
- Rewire the e2e fixture to load dockview.js + self-registering
  dockview-enterprise.js.
- Repoint the demo with a side-effect `import 'dockview-enterprise'`.

Verified: core+dockview+react 1171/1171, enterprise 285/285, e2e green;
enterprise bundle stamps the release date + externalizes dockview; the
free dockview bundle no longer contains the enterprise modules.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
mathuo
2026-07-02 19:56:11 +01:00
co-authored by Claude Opus 4.8
parent f03fda1827
commit 0c96bf2452
59 changed files with 214 additions and 162 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ main document, so a popout there is not a genuine second window.)
The fixture loads the UMD bundles from `dist/`, so build them first:
```bash
yarn nx run-many -t build:bundle -p dockview-core dockview-modules
yarn nx run-many -t build:bundle -p dockview-core dockview-enterprise
yarn playwright install chromium # first time only
yarn test:e2e
```
+12 -17
View File
@@ -28,25 +28,20 @@
href="/packages/dockview-core/dist/styles/dockview.css"
/>
<!-- Built UMD bundles. dockview-core exposes the global "dockview-core";
dockview-modules expects it aliased as DockviewCore. -->
<script src="/packages/dockview-core/dist/dockview-core.js"></script>
<script>
window.DockviewCore = window['dockview-core'];
</script>
<script src="/packages/dockview-modules/dist/dockview-modules.js"></script>
<!-- Built UMD bundles. `dockview` (self-contained — bundles core in)
exposes the global `dockview`; `dockview-enterprise` externalizes it
and, when it loads, self-registers its feature modules + the license
check into that same core registry. -->
<script src="/packages/dockview/dist/dockview.js"></script>
<script src="/packages/dockview-enterprise/dist/dockview-enterprise.js"></script>
<script>
(function () {
const core = window['dockview-core'];
const modules = window['dockview-modules'];
const lib = window['dockview'];
// Register the full module set plus the optional keyboard-docking
// module so the harness can exercise cross-window keyboard work.
core.registerModules([
...modules.Modules,
modules.KeyboardDockingModule,
]);
// The enterprise feature modules (incl. keyboard docking + the
// license check) self-register when dockview-enterprise.js loads
// above, so no explicit registerModules call is needed here.
const el = document.getElementById('app');
const params = new URLSearchParams(location.search);
@@ -60,7 +55,7 @@
// to exercise the 2-D cross-row wrap reorder path).
const theme =
params.get('smooth') === '1'
? { ...core.themeAbyss, tabAnimation: 'smooth' }
? { ...lib.themeAbyss, tabAnimation: 'smooth' }
: undefined;
// `?pinned=separate-row` exercises the two-row pinned layout;
// `?compact=1` opts into icon-only pinned tabs.
@@ -68,7 +63,7 @@
params.get('pinned') === 'separate-row'
? 'separate-row'
: 'inline';
const dockview = new core.DockviewComponent(el, {
const dockview = new lib.DockviewComponent(el, {
keyboardNavigation: true,
overflow,
theme,
+1 -1
View File
@@ -44,7 +44,7 @@
"release": {
"projects": [
"dockview-core",
"dockview-modules",
"dockview-enterprise",
"dockview",
"dockview-vue",
"dockview-react",
+2 -2
View File
@@ -16,8 +16,8 @@
"packages/*"
],
"scripts": {
"build": "nx run-many -t build --projects=dockview-core,dockview-modules,dockview,dockview-vue,dockview-react,dockview-angular",
"build:bundle": "nx run-many -t build:bundle --projects=dockview-core,dockview-modules,dockview,dockview-vue,dockview-react,dockview-angular",
"build": "nx run-many -t build --projects=dockview-core,dockview-enterprise,dockview,dockview-vue,dockview-react,dockview-angular",
"build:bundle": "nx run-many -t build:bundle --projects=dockview-core,dockview-enterprise,dockview,dockview-vue,dockview-react,dockview-angular",
"clean": "nx run-many -t clean",
"docs": "typedoc && node scripts/docs.mjs",
"lint": "nx run-many -t lint",
+5 -7
View File
@@ -13,14 +13,14 @@ const config: JestConfigWithTsJest = {
'!<rootDir>/packages/dockview-angular/src/public-api.ts',
],
setupFilesAfterEnv: [
'<rootDir>/packages/dockview-angular/src/__tests__/setup-jest.ts'
'<rootDir>/packages/dockview-angular/src/__tests__/setup-jest.ts',
],
coveragePathIgnorePatterns: ['/node_modules/'],
moduleNameMapper: {
'^dockview$': '<rootDir>/packages/dockview/src/index.ts',
'^dockview-core$': '<rootDir>/packages/dockview-core/src/index.ts',
'^dockview-modules$':
'<rootDir>/packages/dockview-modules/src/index.ts',
'^dockview-enterprise$':
'<rootDir>/packages/dockview-enterprise/src/index.ts',
},
modulePathIgnorePatterns: [
'<rootDir>/packages/dockview-angular/src/__tests__/__mocks__',
@@ -31,11 +31,9 @@ const config: JestConfigWithTsJest = {
testEnvironment: 'jsdom',
testMatch: [
'<rootDir>/packages/dockview-angular/src/**/*.spec.ts',
'<rootDir>/packages/dockview-angular/src/**/*.test.ts'
],
transformIgnorePatterns: [
'node_modules/(?!(.*\\.mjs$|@angular|rxjs))'
'<rootDir>/packages/dockview-angular/src/**/*.test.ts',
],
transformIgnorePatterns: ['node_modules/(?!(.*\\.mjs$|@angular|rxjs))'],
transform: {
'^.+\\.(ts|mjs|js|html)$': [
'jest-preset-angular',
@@ -30,7 +30,7 @@ class TestContentPart implements IContentRenderer {
/**
* The free seam the `MultiRowTabsModule` consumes (PR-A): the tab-list element
* exposed up through the group model + host, and the `relayoutGroup` host hook.
* The module itself (wrap layout) is tested in `dockview-modules`.
* The module itself (wrap layout) is tested in `dockview-enterprise`.
*/
describe('multi-row tabs seam', () => {
function createComponent() {
@@ -1,4 +1,4 @@
# AGENTS.md - dockview-modules
# AGENTS.md - dockview-enterprise
A separately-published home for a subset of dockview's feature modules. Depends
on `dockview-core`; consumed by `dockview` (which registers these modules so the
@@ -42,4 +42,4 @@ batteries-included entry point keeps its full feature set).
## Dependencies
- Depends on: `dockview-core` (build chain: `dockview-core` -> `dockview-modules` -> `dockview`)
- Depends on: `dockview-core` (build chain: `dockview-core` -> `dockview-enterprise` -> `dockview`)
+45
View File
@@ -0,0 +1,45 @@
# AGENTS.md - dockview-enterprise
A separately-published home for a subset of dockview's feature modules. Depends
on `dockview-core`; consumed by `dockview` (which registers these modules so the
batteries-included entry point keeps its full feature set).
> Neutral alias — keep commercial/tier language out of this package, its code,
> and commit messages.
## Modules hosted here
- `TabGroupChipsModule` (`tabGroupChipsService.ts`)
- `ContextMenuModule` (`contextMenu.ts`)
- `AdvancedDnDModule` (`advancedDnDService.ts`)
- `AccessibilityModule` (`accessibilityService.ts`) — `dependsOn` AdvancedDnD
(here) and LiveRegion (stays in core)
`src/index.ts` exports each module plus a `Modules` bundle array.
## How it fits the module system
- Core owns the contracts: the `ServiceCollection` slots and the `IFooService`
/ `IFooHost` interfaces in `dockview-core` (`dockview/moduleContracts.ts`).
Core code only ever touches `services.fooService?.` — never an implementation
here. Option types also stay in core (`dockview/options.ts`).
- These files import what they need from the `dockview-core` **main entry**
(`'dockview-core'`); the few internals they require (`defineModule`, the
contracts, `resolveMessages`, `findRelativeZIndexParent`, `IDragGhostSpec`,
`LiveRegionModule`) are exported from core's public index. No `dist/` deep
imports.
- Registration is global: `dockview` calls `registerModules(Modules)` at import
time. `DockviewComponent` appends globally-registered modules to its built-in
set at construction.
## Build / Test
- `build` - tsc CJS + ESM (no CSS; styles live in core)
- `build:bundle` - rollup; externalizes `dockview-core`
- `test` - Jest (jsdom). `src/__tests__/registerModules.ts` registers `Modules`
globally so a default `DockviewComponent` in tests has the full feature set;
ResizeObserver/PointerEvent jsdom mocks are reused from core.
## Dependencies
- Depends on: `dockview-core` (build chain: `dockview-core` -> `dockview-enterprise` -> `dockview`)
@@ -1,4 +1,4 @@
# dockview-modules
# dockview-enterprise
Separable feature modules for [dockview](https://github.com/mathuo/dockview).
@@ -10,7 +10,7 @@ feature set out of the box.
```ts
// dockview (the batteries-included entry) does this for you:
import { registerModules } from 'dockview-core';
import { Modules } from 'dockview-modules';
import { Modules } from 'dockview-enterprise';
registerModules(Modules);
```
@@ -2,12 +2,12 @@ import { JestConfigWithTsJest } from 'ts-jest';
const config: JestConfigWithTsJest = {
preset: 'ts-jest',
roots: ['<rootDir>/packages/dockview-modules'],
modulePaths: ['<rootDir>/packages/dockview-modules/src'],
displayName: { name: 'dockview-modules', color: 'blue' },
roots: ['<rootDir>/packages/dockview-enterprise'],
modulePaths: ['<rootDir>/packages/dockview-enterprise/src'],
displayName: { name: 'dockview-enterprise', color: 'blue' },
rootDir: '../../',
collectCoverageFrom: [
'<rootDir>/packages/dockview-modules/src/**/*.{js,jsx,ts,tsx}',
'<rootDir>/packages/dockview-enterprise/src/**/*.{js,jsx,ts,tsx}',
],
setupFiles: [
// ResizeObserver / PointerEvent are not implemented in jsdom; reuse the
@@ -17,18 +17,21 @@ const config: JestConfigWithTsJest = {
],
setupFilesAfterEnv: [
'<rootDir>/jest-setup.ts',
'<rootDir>/packages/dockview-modules/src/__tests__/registerModules.ts',
'<rootDir>/packages/dockview-enterprise/src/__tests__/registerModules.ts',
],
coveragePathIgnorePatterns: ['/node_modules/'],
moduleNameMapper: {
'^dockview-core$': '<rootDir>/packages/dockview-core/src/index.ts',
'^dockview-modules$':
'<rootDir>/packages/dockview-modules/src/index.ts',
// The enterprise source imports the base API from `dockview` (not
// `dockview-core`), so map it to the dockview source too.
'^dockview$': '<rootDir>/packages/dockview/src/index.ts',
'^dockview-enterprise$':
'<rootDir>/packages/dockview-enterprise/src/index.ts',
},
modulePathIgnorePatterns: [
'<rootDir>/packages/dockview-modules/src/__tests__/registerModules.ts',
'<rootDir>/packages/dockview-enterprise/src/__tests__/registerModules.ts',
],
coverageDirectory: '<rootDir>/packages/dockview-modules/coverage/',
coverageDirectory: '<rootDir>/packages/dockview-enterprise/coverage/',
// testResultsProcessor inherited from root config
testEnvironment: 'jsdom',
transform: {
@@ -1,14 +1,13 @@
{
"name": "dockview-modules",
"name": "dockview-enterprise",
"version": "7.0.2",
"private": true,
"description": "Separable feature modules for dockview",
"description": "Enterprise feature modules and licensing for dockview",
"keywords": [
"dockview",
"layout",
"layout manager",
"docking",
"modules"
"enterprise"
],
"homepage": "https://github.com/mathuo/dockview",
"bugs": {
@@ -23,7 +22,7 @@
"main": "./dist/package/main.cjs.js",
"module": "./dist/package/main.esm.mjs",
"types": "./dist/cjs/index.d.ts",
"sideEffects": false,
"sideEffects": true,
"files": [
"dist",
"README.md"
@@ -35,14 +34,14 @@
"build": "npm run build:cjs && npm run build:esm",
"clean": "rimraf dist/ .build/ .rollup.cache/",
"rebuild": "npm run clean && npm run build",
"test": "jest --selectProjects dockview-modules",
"test:cov": "jest --selectProjects dockview-modules --coverage",
"test": "jest --selectProjects dockview-enterprise",
"test:cov": "jest --selectProjects dockview-enterprise --coverage",
"lint": "eslint 'src/**/*.{ts,tsx,js,jsx}'",
"lint:fix": "eslint 'src/**/*.{ts,tsx,js,jsx}' --fix",
"format": "prettier --write 'src/**/*.{ts,tsx,js,jsx}'",
"format:check": "prettier --check 'src/**/*.{ts,tsx,js,jsx}'"
},
"dependencies": {
"dockview-core": "^7.0.2"
"dockview": "7.0.2"
}
}
@@ -48,10 +48,9 @@ function outputFile(format, isMinified) {
return `${filename}.${ext}`;
}
// dockview-core (and its deep internal paths) is a declared dependency and is
// always externalized — the bundle ships only the module implementations.
const isCoreExternal = (id) =>
id === 'dockview-core' || id.startsWith('dockview-core/');
// `dockview` (the free package, this package's sole base dependency) is always
// externalized — the bundle ships only the enterprise module implementations.
const isBaseExternal = (id) => id === 'dockview' || id.startsWith('dockview/');
function createBundle(format, options) {
const { isMinified } = options;
@@ -61,7 +60,7 @@ function createBundle(format, options) {
file,
format,
sourcemap: isMinified && format === 'umd',
globals: { 'dockview-core': 'DockviewCore' },
globals: { dockview: 'dockview' },
banner: [
`/**`,
` * ${name}`,
@@ -94,7 +93,7 @@ function createBundle(format, options) {
input,
output,
plugins,
external: isCoreExternal,
external: isBaseExternal,
};
}
@@ -1,8 +1,8 @@
import { DockviewCompositeDisposable as CompositeDisposable } from 'dockview-core';
import { DockviewGroupPanel } from 'dockview-core';
import { DockviewKeybindings, KeyboardNavigationOptions } from 'dockview-core';
import { defineModule } from 'dockview-core';
import { IAccessibilityHost, IAccessibilityService } from 'dockview-core';
import { DockviewCompositeDisposable as CompositeDisposable } from 'dockview';
import { DockviewGroupPanel } from 'dockview';
import { DockviewKeybindings, KeyboardNavigationOptions } from 'dockview';
import { defineModule } from 'dockview';
import { IAccessibilityHost, IAccessibilityService } from 'dockview';
import {
bindDocumentListeners,
KEYBOARD_MOVE_ATTRIBUTE,
@@ -1,20 +1,17 @@
import { DockviewCompositeDisposable as CompositeDisposable } from 'dockview-core';
import { DockviewGroupPanel } from 'dockview-core';
import { IDockviewPanel } from 'dockview-core';
import { EdgeGroupPosition } from 'dockview-core';
import { AutoHideEdgeGroupOptions } from 'dockview-core';
import { defineModule, EdgeGroupModule } from 'dockview-core';
import { DockviewCompositeDisposable as CompositeDisposable } from 'dockview';
import { DockviewGroupPanel } from 'dockview';
import { IDockviewPanel } from 'dockview';
import { EdgeGroupPosition } from 'dockview';
import { AutoHideEdgeGroupOptions } from 'dockview';
import { defineModule, EdgeGroupModule } from 'dockview';
import {
createCloseButton,
createDismissableLayer,
createPinButton,
prefersReducedMotion,
resolveOpaqueBackground,
} from 'dockview-core';
import {
IAutoHideEdgeGroupHost,
IAutoHideEdgeGroupService,
} from 'dockview-core';
} from 'dockview';
import { IAutoHideEdgeGroupHost, IAutoHideEdgeGroupService } from 'dockview';
/** Height (px) of the title bar; the content/`always` overlay is inset below it
* so nothing paints under the bar. The title bar's own height is set inline to
@@ -1,15 +1,15 @@
import { findRelativeZIndexParent } from 'dockview-core';
import { DockviewGroupPanel } from 'dockview-core';
import { IDockviewPanel } from 'dockview-core';
import { findRelativeZIndexParent } from 'dockview';
import { DockviewGroupPanel } from 'dockview';
import { IDockviewPanel } from 'dockview';
import {
BuiltInChipContextMenuItem,
ContextMenuItemConfig,
ContextMenuItem,
} from 'dockview-core';
import { ITabGroup } from 'dockview-core';
import { TabGroupColorPalette } from 'dockview-core';
import { defineModule } from 'dockview-core';
import { IContextMenuHost, IContextMenuService } from 'dockview-core';
} from 'dockview';
import { ITabGroup } from 'dockview';
import { TabGroupColorPalette } from 'dockview';
import { defineModule } from 'dockview';
import { IContextMenuHost, IContextMenuService } from 'dockview';
function popoverZIndexFor(target: EventTarget | null): string | undefined {
if (!(target instanceof HTMLElement)) {
@@ -1,7 +1,7 @@
import {
DockviewCompositeDisposable as CompositeDisposable,
DockviewIDisposable as IDisposable,
} from 'dockview-core';
} from 'dockview';
import {
DockviewGroupPanel,
DockviewWillShowOverlayLocationEvent,
@@ -9,10 +9,10 @@ import {
PositionResolver,
PositionResolverArgs,
PositionResolverResult,
} from 'dockview-core';
import { defineModule } from 'dockview-core';
import { IDropGuideHost, IDropGuideService } from 'dockview-core';
import { AdvancedDnDModule } from 'dockview-core';
} from 'dockview';
import { defineModule } from 'dockview';
import { IDropGuideHost, IDropGuideService } from 'dockview';
import { AdvancedDnDModule } from 'dockview';
/** Size (px) of each compass cell + the gap between them. */
const CELL = 38;
@@ -1,4 +1,4 @@
import { DockviewModule } from 'dockview-core';
import { DockviewModule, registerModules } from 'dockview';
import { TabGroupChipsModule } from './tabGroupChipsService';
import { ContextMenuModule } from './contextMenu';
import { AccessibilityModule } from './accessibilityService';
@@ -9,6 +9,13 @@ import { AutoHideEdgeGroupModule } from './autoHideEdgeGroupService';
import { MultiRowTabsModule } from './multiRowTabsService';
import { PinnedTabsModule } from './pinnedTabsService';
import { KeyboardDockingModule } from './keyboardDockingService';
import { LicenseModule } from './licenseService';
// Re-export the full dockview (free) API so `dockview-enterprise` is a drop-in
// superset — mirrors AG Grid's `ag-grid-enterprise` re-exporting
// `ag-grid-community`. Also runs dockview's own load-time side effects
// (e.g. markDockviewPackageLoaded) via the re-exported module.
export * from 'dockview';
export {
TabGroupChipsService,
@@ -49,8 +56,10 @@ export type {
export type { LicenseState } from './licenseValidator';
/**
* The set of modules provided by this package. `dockview` registers these via
* `registerModules(Modules)` so they are available to every component.
* The enterprise feature modules, including the license gate. Registered
* automatically on import (below), so merely importing `dockview-enterprise`
* activates these modules and the license watermark-unless-licensed check
* for every component in the process.
*/
export const Modules: DockviewModule<any>[] = [
TabGroupChipsModule,
@@ -63,4 +72,10 @@ export const Modules: DockviewModule<any>[] = [
MultiRowTabsModule,
PinnedTabsModule,
KeyboardDockingModule,
LicenseModule,
];
// Self-register on import (a side effect — hence `sideEffects: true` in
// package.json). This makes the package batteries-included: no explicit
// registerModules() call is required of the consumer.
registerModules(Modules);
@@ -1,15 +1,15 @@
import {
DockviewCompositeDisposable as CompositeDisposable,
DockviewIDisposable as IDisposable,
} from 'dockview-core';
import { Position } from 'dockview-core';
import { DockviewGroupPanel } from 'dockview-core';
import { IDockviewPanel } from 'dockview-core';
import { resolveMessages } from 'dockview-core';
import { defineModule } from 'dockview-core';
import { AdvancedDnDModule } from 'dockview-core';
import { LiveRegionModule } from 'dockview-core';
import { IAccessibilityHost, IKeyboardDockingService } from 'dockview-core';
} from 'dockview';
import { Position } from 'dockview';
import { DockviewGroupPanel } from 'dockview';
import { IDockviewPanel } from 'dockview';
import { resolveMessages } from 'dockview';
import { defineModule } from 'dockview';
import { AdvancedDnDModule } from 'dockview';
import { LiveRegionModule } from 'dockview';
import { IAccessibilityHost, IKeyboardDockingService } from 'dockview';
import {
bindDocumentListeners,
KEYBOARD_MOVE_ATTRIBUTE,
@@ -2,7 +2,7 @@ import {
DockviewComponentOptions,
DockviewIDisposable as IDisposable,
KeyboardNavigationOptions,
} from 'dockview-core';
} from 'dockview';
/**
* Marks (on the dockview root element) that a keyboard move is in progress, so
@@ -2,20 +2,20 @@ import {
DockviewCompositeDisposable as CompositeDisposable,
DockviewEmitter as Emitter,
DockviewEvent as Event,
} from 'dockview-core';
} from 'dockview';
import {
DockviewComponentOptions,
DockviewLayoutMutationEvent,
DockviewLayoutMutationKind,
SerializedDockview,
} from 'dockview-core';
import { defineModule } from 'dockview-core';
} from 'dockview';
import { defineModule } from 'dockview';
import {
ILayoutHistoryHost,
ILayoutHistoryService,
LayoutHistoryChangeEvent,
LayoutHistoryKind,
} from 'dockview-core';
} from 'dockview';
interface HistoryEntry {
readonly kind: LayoutHistoryKind;
@@ -11,7 +11,7 @@
* license.md` §5.
*/
import { DockviewEmitter, DockviewEvent } from 'dockview-core';
import { DockviewEmitter, DockviewEvent } from 'dockview';
class LicenseRegistryImpl {
private _key: string | undefined;
@@ -13,10 +13,7 @@
* contracts live in this package. See `enterprise-modules/license.md`.
*/
import {
defineModule,
DockviewIDisposable as IDisposable,
} from 'dockview-core';
import { defineModule, DockviewIDisposable as IDisposable } from 'dockview';
import {
LicenseState,
isLocalhostHostname,
@@ -26,10 +23,12 @@ import {
import { LicenseRegistry } from './licenseRegistry';
import { DOCKVIEW_RELEASE_DATE } from './releaseDate';
// The `ServiceCollection` slot is added HERE, not in core — so `dockview-core`
// never names `licenseService`. Compile-time only; the module system stores /
// reads services by string key at runtime.
declare module 'dockview-core' {
// The `ServiceCollection` slot is added HERE, not in core — so core never names
// `licenseService`. Augmenting `dockview` (which re-exports core's
// `ServiceCollection`) keeps the package free of any `dockview-core` reference.
// Compile-time only; the module system stores/reads services by string key at
// runtime.
declare module 'dockview' {
interface ServiceCollection {
licenseService?: ILicenseService;
}
@@ -2,7 +2,7 @@
* License key validation pure, dependency-free, synchronous.
*
* This is a re-implementation of the issuer's scheme
* (`dockview-licencing/src/lib/{checksum,licence}.ts`) so `dockview-modules`
* (`dockview-licencing/src/lib/{checksum,licence}.ts`) so `dockview-enterprise`
* can verify a key entirely offline. It MUST stay byte-compatible with the
* issuer the cross-repo golden fixture in the spec (a real minted key) is
* the guard against drift.
@@ -4,8 +4,8 @@ import {
DockviewOverflowOptions,
OVERFLOW_WRAP_TABS_CLASS as WRAP_CLASS,
defineModule,
} from 'dockview-core';
import { IMultiRowTabsHost, IMultiRowTabsService } from 'dockview-core';
} from 'dockview';
import { IMultiRowTabsHost, IMultiRowTabsService } from 'dockview';
function isWrapMode(overflow: DockviewOverflowOptions | undefined): boolean {
return typeof overflow === 'object' && overflow?.mode === 'wrap';
@@ -2,7 +2,7 @@ import {
DockviewCompositeDisposable as CompositeDisposable,
DockviewEmitter as Emitter,
DockviewEvent as Event,
} from 'dockview-core';
} from 'dockview';
import {
Box,
DockviewGroupPanel,
@@ -13,9 +13,9 @@ import {
SmartGuidesSnapPosition,
SmartGuidesSnapTogetherEvent,
SnapModifier,
} from 'dockview-core';
import { defineModule, FloatingGroupModule } from 'dockview-core';
import { ISmartGuidesHost, ISmartGuidesService } from 'dockview-core';
} from 'dockview';
import { defineModule, FloatingGroupModule } from 'dockview';
import { ISmartGuidesHost, ISmartGuidesService } from 'dockview';
/** Fraction of the perpendicular extents that must overlap for an edge to read
* as an adjacency (dock-beside) rather than a glancing touch. */
@@ -1,10 +1,10 @@
import {
DockviewCompositeDisposable as CompositeDisposable,
DockviewIDisposable as IDisposable,
} from 'dockview-core';
import { DockviewGroupPanel } from 'dockview-core';
import { defineModule } from 'dockview-core';
import { ITabGroupChipsHost, ITabGroupChipsService } from 'dockview-core';
} from 'dockview';
import { DockviewGroupPanel } from 'dockview';
import { defineModule } from 'dockview';
import { ITabGroupChipsHost, ITabGroupChipsService } from 'dockview';
export class TabGroupChipsService implements ITabGroupChipsService {
private readonly _host: ITabGroupChipsHost;
-1
View File
@@ -1 +0,0 @@
AGENTS.md
+2 -2
View File
@@ -17,8 +17,8 @@ const config: JestConfigWithTsJest = {
moduleNameMapper: {
'^dockview-core$': '<rootDir>/packages/dockview-core/src/index.ts',
'^dockview$': '<rootDir>/packages/dockview/src/index.ts',
'^dockview-modules$':
'<rootDir>/packages/dockview-modules/src/index.ts',
'^dockview-enterprise$':
'<rootDir>/packages/dockview-enterprise/src/index.ts',
},
modulePathIgnorePatterns: [
'<rootDir>/packages/dockview-react/src/__tests__/__mocks__',
+7 -6
View File
@@ -12,15 +12,16 @@ export default defineConfig({
include: ['src/__tests__/**/*.spec.ts'],
alias: {
dockview: resolve(__dirname, '../dockview/src/index.ts'),
'dockview-core': resolve(__dirname, '../dockview-core/src/index.ts'),
'dockview-modules': resolve(
'dockview-core': resolve(
__dirname,
'../dockview-modules/src/index.ts'
'../dockview-core/src/index.ts'
),
'dockview-enterprise': resolve(
__dirname,
'../dockview-enterprise/src/index.ts'
),
},
setupFiles: [
'src/__tests__/__mocks__/resizeObserver.vitest.ts',
],
setupFiles: ['src/__tests__/__mocks__/resizeObserver.vitest.ts'],
},
build: {
+2 -2
View File
@@ -14,8 +14,8 @@ const config: JestConfigWithTsJest = {
coveragePathIgnorePatterns: ['/node_modules/'],
moduleNameMapper: {
'^dockview-core$': '<rootDir>/packages/dockview-core/src/index.ts',
'^dockview-modules$':
'<rootDir>/packages/dockview-modules/src/index.ts',
'^dockview-enterprise$':
'<rootDir>/packages/dockview-enterprise/src/index.ts',
},
modulePathIgnorePatterns: [],
coverageDirectory: '<rootDir>/packages/dockview/coverage/',
-3
View File
@@ -75,8 +75,5 @@
},
"dependencies": {
"dockview-core": "^7.0.2"
},
"devDependencies": {
"dockview-modules": "^7.0.2"
}
}
+8 -9
View File
@@ -50,9 +50,10 @@ function createBundle(format, options) {
const isUMD = format === 'umd';
// dockview-modules is a private, unpublished package — always bundle its
// code in. dockview-core is published: externalize it in the package
// builds, but inline it in the UMD bundle so the CDN build is self-contained.
// dockview-core is published: externalize it in the package builds, but
// inline it in the UMD bundle so the CDN build is self-contained. (The
// enterprise feature modules now live in the separately-published
// dockview-enterprise package and are no longer bundled here.)
const external = isUMD
? ['react', 'react-dom']
: ['react', 'react-dom', 'dockview-core', /^dockview-core\//];
@@ -77,12 +78,10 @@ function createBundle(format, options) {
const plugins = [
nodeResolve({
include: isUMD
? [
'node_modules/dockview-core/**',
'node_modules/dockview-modules/**',
]
: ['node_modules/dockview-modules/**'],
// UMD is self-contained: bundle dockview-core in. Package builds
// externalize dockview-core, so nothing needs bundling from
// node_modules there.
include: isUMD ? ['node_modules/dockview-core/**'] : [],
}),
typescript({
tsconfig: 'tsconfig.esm.json',
+5 -7
View File
@@ -1,15 +1,13 @@
import { markDockviewPackageLoaded, registerModules } from 'dockview-core';
import { Modules } from 'dockview-modules';
import { markDockviewPackageLoaded } from 'dockview-core';
export * from 'dockview-core';
/**
* `dockview` is the batteries-included entry point: it re-exports the core API
* and registers the separable feature modules so every component gets the full
* feature set out of the box. Consumers who want only the core can depend on
* `dockview-core` directly.
* `dockview` is the recommended free entry point: a thin re-export of
* `dockview-core`. The separable enterprise feature modules now live in the
* separately-published `dockview-enterprise` package (which depends on and
* re-exports `dockview`); install that to opt into them.
*/
registerModules(Modules);
// Mark the public package as loaded so `dockview-core` doesn't warn about
// direct usage. Purely drives that developer warning — no functional effect.
+3 -3
View File
@@ -91,13 +91,13 @@ const config = {
__dirname,
'../dockview/src'
),
// Without this, dockview-modules resolves to
// Without this, dockview-enterprise resolves to
// its built dist/, so editing module source
// (e.g. auto-hide edge groups) does nothing
// until a rebuild + dev-server restart.
'dockview-modules$': path.join(
'dockview-enterprise$': path.join(
__dirname,
'../dockview-modules/src'
'../dockview-enterprise/src'
),
}),
react: path.join(
@@ -13,6 +13,14 @@ import {
GetTabGroupChipContextMenuItemsParams,
DEFAULT_TAB_GROUP_COLORS,
} from 'dockview-react';
// Side-effect import: registers the enterprise feature modules (pinned tabs,
// smart guides, drop guide, auto-hide, context menu, tab-group chips, …) and
// the license check into the global registry. Required now that the free
// `dockview`/`dockview-react` packages no longer bundle them.
// NOTE: on a deployed (non-localhost) origin this shows a license watermark
// until `LicenseManager.setLicenseKey('<vendor key>')` is called; localhost
// (the sandbox/dev preview) suppresses it.
import 'dockview-enterprise';
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
import './app.scss';
@@ -52,7 +52,7 @@
// exports from a CJS module when that flag is present). `dockview`
// is consumed only via `require()` from dockview-react, so it can
// use the inlined `dist/package` bundle — which avoids the dangling
// `require('dockview-modules')` present in its tsc `dist/cjs` build.
// `require('dockview-enterprise')` present in its tsc `dist/cjs` build.
'dockview-core': {
main: './dist/cjs/index.js',
format: 'cjs',
+1 -1
View File
@@ -8,7 +8,7 @@ import { defineConfig, devices } from '@playwright/test';
* static fixture page (built UMD bundles) in headless Chromium.
*
* Prerequisite: the UMD bundles must exist —
* yarn nx run-many -t build:bundle -p dockview-core dockview-modules
* yarn nx run-many -t build:bundle -p dockview-core dockview-enterprise
* then `yarn test:e2e`.
*/
export default defineConfig({
+3 -3
View File
@@ -1,9 +1,9 @@
sonar.projectKey=mathuo_dockview
sonar.organization=dockview
sonar.inclusions=packages/dockview/src/**/*,packages/dockview-core/src/**/*,packages/dockview-vue/src/**/*,packages/dockview-react/src/**/*,packages/dockview-angular/src/**/*,packages/dockview-modules/src/**/*
sonar.exclusions=packages/dockview/docs/**/*,packages/dockview/src/__tests__/**/*,packages/dockview-core/src/__tests__/**/*,packages/dockview-vue/src/__tests__/**/*,packages/dockview-react/src/__tests__/**/*,packages/dockview-angular/src/__tests__/**/*,packages/dockview-modules/src/__tests__/**/*
sonar.tests=packages/dockview/src/__tests__,packages/dockview-core/src/__tests__,packages/dockview-vue/src/__tests__,packages/dockview-react/src/__tests__,packages/dockview-angular/src/__tests__,packages/dockview-modules/src/__tests__
sonar.inclusions=packages/dockview/src/**/*,packages/dockview-core/src/**/*,packages/dockview-vue/src/**/*,packages/dockview-react/src/**/*,packages/dockview-angular/src/**/*,packages/dockview-enterprise/src/**/*
sonar.exclusions=packages/dockview/docs/**/*,packages/dockview/src/__tests__/**/*,packages/dockview-core/src/__tests__/**/*,packages/dockview-vue/src/__tests__/**/*,packages/dockview-react/src/__tests__/**/*,packages/dockview-angular/src/__tests__/**/*,packages/dockview-enterprise/src/__tests__/**/*
sonar.tests=packages/dockview/src/__tests__,packages/dockview-core/src/__tests__,packages/dockview-vue/src/__tests__,packages/dockview-react/src/__tests__,packages/dockview-angular/src/__tests__,packages/dockview-enterprise/src/__tests__
sonar.testExecutionReportPaths=test-report.xml
sonar.javascript.lcov.reportPaths=coverage/lcov.info
+1 -1
View File
@@ -8,7 +8,7 @@
"path": "./packages/dockview-core"
},
{
"path": "./packages/dockview-modules"
"path": "./packages/dockview-enterprise"
},
{
"path": "./packages/dockview-vue"
+1 -1
View File
@@ -6,7 +6,7 @@
"dockview-core": ["packages/dockview-core/src/index.ts"],
"dockview": ["packages/dockview/src/index.ts"],
"dockview-react": ["packages/dockview-react/src/index.ts"],
"dockview-modules": ["packages/dockview-modules/src/index.ts"]
"dockview-enterprise": ["packages/dockview-enterprise/src/index.ts"]
},
"jsx": "react-jsx",
"noImplicitAny": false,