Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG-WIP.md
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,8 @@ Craft 6 now uses [Laravel's authorization system](https://laravel.com/docs/12.x/
- Removed the `Craft.FocalPoint` and `Craft.Updater` control panel JavaScript classes. The image preview and the updater now start themselves from their markup.
- `craft\web\assets\focalpoint\FocalPointAsset` now does nothing.
- Added `AuthChallengeForm`, `AssetSelectorController`, `ElementSelectorController`, `Uploads`, `createElementSelectorModal`, `highlighter`, and `registerElementSelectorController` to the `@craftcms/cp` import-map module. Control panel plugin code should import them from there; they’re no longer `Craft.*` globals, except `Craft.createElementSelectorModal` and `Craft.highlighter`, which the Yii2 adapter still provides.
- Added `t()`, `escapeHtml()`, `appendHeadHtml()`, `appendBodyHtml()`, `appendElementHtml()`, `actionClient`, `http`, `getUrl()`, `getCpUrl()`, `getActionUrl()`, `cpConfig()`, `openSlideout()`, `createElementEditor()`, `addActionsToChip()`, `loadElementThumbs()`, `openAssetImageEditor()`, and `Uploader` to the `@craftcms/cp` import-map module, replacing the `Craft.*` globals of the same names. Importing them from there keeps a plugin bundle on the control panel’s own instances rather than bundling second copies.
- The control panel's import map now publishes `@craftcms/garnish`, so plugin bundles can import its drag-and-drop, modals and menus rather than relying on the Yii2 adapter's `window.Garnish`.
- Removed the classic (pre-3.2) `Craft.LivePreview` control panel JavaScript class, which Craft hasn’t used since 3.2. ([#19964](https://github.com/craftcms/cms/pull/19964))
- Deprecated the `Craft.LightSwitch`, `Craft.InfoIcon`, `Craft.ColorInput`, `Craft.PasswordInput`, `Craft.IconPicker`, `Craft.SlidePicker`, `Craft.SlideRuleInput`, and `Craft.Tooltip` control panel JavaScript classes, along with the `.infoicon` jQuery plugin. The corresponding `@craftcms/ui` web components should be used instead.
- Deprecated the `Craft.SortableCheckboxSelect` control panel JavaScript class. `<craft-checkbox-select>` should be used instead. ([#20036](https://github.com/craftcms/cms/pull/20036))
Expand Down
36 changes: 36 additions & 0 deletions resources/js/cp-module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {defineAsyncComponent} from 'vue';
import {ConfigService} from '@craftcms/ui/services/Config';
import {FileUpload, UploadError, registerTransport} from './upload-client';
import {
closeCommandPalette,
Expand Down Expand Up @@ -192,3 +193,38 @@ export const CommandPalette = {

export type * from './modules/command-palette/types';
export type {CommandPaletteRegistration} from './modules/command-palette/registry';

/**
* The utilities a plugin's own bundle needs to behave like control panel code:
* translating, talking to controller actions, and appending markup the server
* returned. They're re-exported here, rather than left to be imported from
* `@craftcms/ui`, so a plugin bundle shares the control panel's instances
* instead of bundling second copies.
*/
export {t} from '@craftcms/ui/utilities/translate';
export {escapeHtml} from '@craftcms/ui/utilities/escapeHtml';
export {
appendBodyHtml,
appendElementHtml,
appendHeadHtml,
type AppendHtmlDisposer,
} from '@craftcms/ui/utilities/dom';
export {actionClient, http} from '@craftcms/ui';
export {getActionUrl, getCpUrl, getUrl} from './common/craft/url';

/**
* The control panel's own config — `siteId`, `sites`, `userIsAdmin`,
* `elementTypeNames`, `orientation` and the rest of the payload the control
* panel boots with.
*/
export function cpConfig(): ConfigService {
return ConfigService.getInstance();
}

/** Slideouts, element editors, chip actions and thumbnails. */
export {openSlideout, createElementEditor} from './common/slideouts';
export type {ElementEditorPanel} from './common/slideouts';
export {addActionsToChip, type ChipAction} from './common/craft/chip-actions';
export {loadElementThumbs} from './modules/element-thumb-loader';
export {openAssetImageEditor} from './modules/image-editor/open-asset-image-editor';
export {Uploader} from './modules/uploader/uploader';
6 changes: 6 additions & 0 deletions resources/js/garnish.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* Garnish, published to plugin bundles through the import map (see
* `Cp::sharedModules()`) so a plugin's drag-and-drop, modals and menus share
* the control panel's instance rather than bundling their own copy.
*/
export * from '@craftcms/garnish';
1 change: 1 addition & 0 deletions src/Cp/Cp.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ public static function sharedModules(): array
return [
'vue' => static::vite()->asset('resources/js/vue.ts'),
'@craftcms/cp' => static::vite()->asset('resources/js/cp-module.ts'),
'@craftcms/garnish' => static::vite()->asset('resources/js/garnish.ts'),
];
}

Expand Down
5 changes: 3 additions & 2 deletions tests/Unit/Http/Middleware/HandleInertiaRequestsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@

File::deleteDirectory($publicPath);
File::ensureDirectoryExists("{$publicPath}/vendor/craft/build");
File::put("{$publicPath}/vendor/craft/build/manifest.json", '{"resources/js/vue.ts":{"file":"assets/vue-abc123.js","isEntry":true},"resources/js/cp-module.ts":{"file":"assets/cp-module-def456.js","isEntry":true}}');
File::put("{$publicPath}/vendor/craft/build/manifest.json", '{"resources/js/vue.ts":{"file":"assets/vue-abc123.js","isEntry":true},"resources/js/cp-module.ts":{"file":"assets/cp-module-def456.js","isEntry":true},"resources/js/garnish.ts":{"file":"assets/garnish-ghi789.js","isEntry":true}}');
app()->usePublicPath($publicPath);

try {
expect(Cp::sharedModules())->toHaveKey('vue')
->and(Cp::sharedModules()['vue'])->toEndWith('/vendor/craft/build/assets/vue-abc123.js')
->and(Cp::sharedModules()['@craftcms/cp'])->toEndWith('/vendor/craft/build/assets/cp-module-def456.js');
->and(Cp::sharedModules()['@craftcms/cp'])->toEndWith('/vendor/craft/build/assets/cp-module-def456.js')
->and(Cp::sharedModules()['@craftcms/garnish'])->toEndWith('/vendor/craft/build/assets/garnish-ghi789.js');
} finally {
app()->usePublicPath($originalPublicPath);
File::deleteDirectory($publicPath);
Expand Down
5 changes: 3 additions & 2 deletions vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -401,8 +401,8 @@ export default defineConfig(async ({mode}) => {
emptyOutDir: true,
rollupOptions: {
// App builds drop entry exports by default, which would empty the
// `vue.ts`/`cp-module.ts` entries that plugin bundles import through
// the import map.
// `vue.ts`/`cp-module.ts`/`garnish.ts` entries that plugin bundles
// import through the import map.
preserveEntrySignatures: 'exports-only',
},
},
Expand Down Expand Up @@ -482,6 +482,7 @@ export default defineConfig(async ({mode}) => {
'yii2-adapter/resources/js/cp-compat.ts',
'yii2-adapter/resources/js/element-editor.ts',
'resources/js/cp-module.ts',
'resources/js/garnish.ts',
'resources/js/legacy.ts',
'resources/js/uploads.ts',
'resources/js/vue.ts',
Expand Down
Loading