Files
directus/app/src/extensions.ts
Rijk van Zanten 5f899012c7 Make themes an extension type (#20423)
* Enable theme fields

* Start adding more default themes

* WIP add theme selector interface

* Restructure, add rules-to-vars util

* Render used vars in local overrides

* Use local theme vars in theme preview

* Render theme option full-width

* Add more test colors

* Only override used variables

* Fix rendering bugs in preview

* Remove test theme

* Add small border to preview

* Add organic theme

* Add changeset

* Don't crash color interface on complex input bg

* Use themable color for disabled input

* Use nav-sidebar theme in v-drawer

* Use border width from the theme in panels

* Use theme border width for panel borders

* Use page background for panel edit buttons

* Fix Active state forselected panel

* Don't use primary for logout hover state

* Fix background color of item duplication fields

* Use form border/background in v-list block

* Use theme border width in hardcoded 2px sections

* fix chip padding

* Rename background-page to background,

rename background to background-normal

* Fix search input styling

* Tweak search input themability

* update icons

* Add border on sidebar section content

* Add color match, start on minimal

* Organize import

* Adjust spacing

* Don't require all rules in TS

* Rename theme files

* Add template for theme

* Import directly from util to prevent circular

* Register custom themes on app load

* Ignore stylesheet files

* Ignore svg as well

* Add changeset

* Update test snapshots

---------

Co-authored-by: Ben Haynes <ben@rngr.org>
Co-authored-by: Pascal Jufer <pascal-jufer@bluewin.ch>
2023-11-14 13:58:01 -05:00

106 lines
3.5 KiB
TypeScript

import type { AppExtensionConfigs } from '@directus/extensions';
import type { RefRecord } from '@directus/types';
import { App, shallowRef, watch } from 'vue';
import { getInternalDisplays, registerDisplays } from './displays';
import { getInternalInterfaces, registerInterfaces } from './interfaces';
import { i18n } from './lang';
import { getInternalLayouts, registerLayouts } from './layouts';
import { getInternalModules, registerModules } from './modules';
import { getInternalOperations, registerOperations } from './operations';
import { getInternalPanels, registerPanels } from './panels';
import { registerThemes } from './themes/register';
import { getRootPath } from './utils/get-root-path';
import { translate } from './utils/translate-object-values';
let customExtensions: AppExtensionConfigs | null = null;
const extensions: RefRecord<AppExtensionConfigs> = {
interfaces: shallowRef([]),
displays: shallowRef([]),
layouts: shallowRef([]),
modules: shallowRef([]),
panels: shallowRef([]),
operations: shallowRef([]),
themes: shallowRef([]),
};
const onHydrateCallbacks: (() => Promise<void>)[] = [];
const onDehydrateCallbacks: (() => Promise<void>)[] = [];
export async function loadExtensions(): Promise<void> {
try {
customExtensions = import.meta.env.DEV
? await import(/* @vite-ignore */ '@directus-extensions')
: await import(/* @vite-ignore */ `${getRootPath()}extensions/sources/index.js`);
} catch (err: any) {
// eslint-disable-next-line no-console
console.warn(`Couldn't load extensions`);
// eslint-disable-next-line no-console
console.warn(err);
}
}
export function registerExtensions(app: App): void {
const interfaces = getInternalInterfaces();
const displays = getInternalDisplays();
const layouts = getInternalLayouts();
const modules = getInternalModules();
const panels = getInternalPanels();
const operations = getInternalOperations();
const themes = []; // Themes is the first extension type that doesn't rely on internally scoped extensions
if (customExtensions !== null) {
interfaces.push(...customExtensions.interfaces);
displays.push(...customExtensions.displays);
layouts.push(...customExtensions.layouts);
modules.push(...customExtensions.modules);
panels.push(...customExtensions.panels);
operations.push(...customExtensions.operations);
themes.push(...customExtensions.themes);
}
registerInterfaces(interfaces, app);
registerDisplays(displays, app);
registerLayouts(layouts, app);
registerPanels(panels, app);
registerOperations(operations, app);
registerThemes(themes);
watch(
i18n.global.locale,
() => {
extensions.interfaces.value = translate(interfaces);
extensions.displays.value = translate(displays);
extensions.layouts.value = translate(layouts);
extensions.panels.value = translate(panels);
extensions.operations.value = translate(operations);
},
{ immediate: true }
);
const { registeredModules, onHydrateModules, onDehydrateModules } = registerModules(modules);
watch(
[i18n.global.locale, registeredModules],
() => {
extensions.modules.value = translate(registeredModules.value);
},
{ immediate: true }
);
onHydrateCallbacks.push(onHydrateModules);
onDehydrateCallbacks.push(onDehydrateModules);
}
export async function onHydrateExtensions() {
await Promise.all(onHydrateCallbacks.map((onHydrate) => onHydrate()));
}
export async function onDehydrateExtensions() {
await Promise.all(onDehydrateCallbacks.map((onDehydrate) => onDehydrate()));
}
export function useExtensions(): RefRecord<AppExtensionConfigs> {
return extensions;
}