diff --git a/CHANGELOG.md b/CHANGELOG.md index 8da97f85c..693be5dfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Piral Changelog +## 1.8.0 (tbd) + +- Added configuration for internal styles (#731) + ## 1.7.3 (December 11, 2024) - Fixed `pilet upgrade` command with `npm` client not changing *package.json* diff --git a/docs/static/schemas/piral-v0.json b/docs/static/schemas/piral-v0.json index eecbe5977..d2e0a0ca6 100644 --- a/docs/static/schemas/piral-v0.json +++ b/docs/static/schemas/piral-v0.json @@ -83,6 +83,15 @@ ], "description": "Defines what isolation / component wrapper is used for components of micro frontends. By default, the 'classic' isolation mode is used." }, + "internalStyles": { + "type": "string", + "enum": [ + "inline", + "sheet", + "none" + ], + "description": "Defines how the styles for the web components are transported. 'inline' puts them on the web components when rendering, 'sheet' includes a stylesheet when bundling, 'none' requires you to include them somewhere. By default, 'inline' is used." + }, "shared": { "type": "array", "items": { diff --git a/src/framework/piral-core/app.codegen b/src/framework/piral-core/app.codegen index ba41b8a3f..189d05da4 100644 --- a/src/framework/piral-core/app.codegen +++ b/src/framework/piral-core/app.codegen @@ -24,9 +24,11 @@ module.exports = function () { debug: debug && (cfg.debugSettings || {}), emulator: !!process.env.DEBUG_PILET, shared: Array.isArray(cfg.shared) ? cfg.shared : [], + internalStyles: cfg.internalStyles || 'inline', isolation: cfg.isolation || 'classic', }; + cg.createBasicAppFunc(imports, exports, opts); cg.createDependencies(imports, exports, opts); cg.createDefaultState(imports, exports, opts); cg.createDebugHandler(imports, exports, opts); diff --git a/src/framework/piral-core/app.codegen.d.ts b/src/framework/piral-core/app.codegen.d.ts index 473d93237..b2e6f6956 100644 --- a/src/framework/piral-core/app.codegen.d.ts +++ b/src/framework/piral-core/app.codegen.d.ts @@ -6,6 +6,8 @@ import type { AppPath, GlobalState, GlobalStateContext, NavigationApi } from './ export const publicPath: string; +export function applyStyle(element: HTMLElement): void; + export function createNavigation(publicPath: string): NavigationApi; export function createDefaultState(): GlobalState; diff --git a/src/framework/piral-core/package.json b/src/framework/piral-core/package.json index 510a1f8b3..62e8c0646 100644 --- a/src/framework/piral-core/package.json +++ b/src/framework/piral-core/package.json @@ -39,7 +39,8 @@ "lib", "src", "app.codegen", - "app.codegen.d.ts" + "app.codegen.d.ts", + "style.css" ], "funding": { "type": "github", diff --git a/src/framework/piral-core/src/modules/element.ts b/src/framework/piral-core/src/modules/element.ts index 754e37065..e44a7dc02 100644 --- a/src/framework/piral-core/src/modules/element.ts +++ b/src/framework/piral-core/src/modules/element.ts @@ -1,4 +1,5 @@ import { ExtensionSlot } from '../components'; +import { applyStyle } from '../../app.codegen'; import { Disposable, GlobalStateContext, BaseExtensionSlotProps } from '../types'; import { tryParseJson, @@ -20,8 +21,6 @@ export interface Updatable { } if (typeof window !== 'undefined' && 'customElements' in window) { - const contents = 'contents'; - /** * This is a nice abstraction allowing anyone to actually use the extension system * brought by Piral. Not all props of the extension system are actually exposed. @@ -113,7 +112,7 @@ if (typeof window !== 'undefined' && 'customElements' in window) { } connectedCallback() { - this.style.display = contents; + applyStyle(this); if (this.isConnected) { this.dispatchEvent( @@ -168,7 +167,7 @@ if (typeof window !== 'undefined' && 'customElements' in window) { */ class PiralPortal extends HTMLElement { connectedCallback() { - this.style.display = contents; + applyStyle(this); } } @@ -187,7 +186,7 @@ if (typeof window !== 'undefined' && 'customElements' in window) { */ class PiralSlot extends HTMLElement { connectedCallback() { - this.style.display = contents; + applyStyle(this); } } @@ -220,7 +219,7 @@ if (typeof window !== 'undefined' && 'customElements' in window) { static contentAssignments = {}; connectedCallback() { - this.style.display = contents; + applyStyle(this); const cid = this.getAttribute('cid'); const content = PiralContent.contentAssignments[cid]; const portal = this.closest('piral-portal'); @@ -264,7 +263,7 @@ if (typeof window !== 'undefined' && 'customElements' in window) { } connectedCallback() { - this.style.display = contents; + applyStyle(this); this.deferEvent('add-component'); } diff --git a/src/framework/piral-core/src/tools/codegen.ts b/src/framework/piral-core/src/tools/codegen.ts index da4ea0b69..255e52af6 100644 --- a/src/framework/piral-core/src/tools/codegen.ts +++ b/src/framework/piral-core/src/tools/codegen.ts @@ -86,6 +86,7 @@ interface CodegenOptions { externals: Array; publicPath: string; isolation: 'classic' | 'modern'; + internalStyles: 'inline' | 'sheet' | 'none'; debug?: { viewState?: boolean; loadPilets?: boolean; @@ -97,6 +98,27 @@ interface CodegenOptions { emulator: boolean; } +export function createBasicAppFunc(imports: Array, exports: Array, opts: CodegenOptions) { + switch (opts.internalStyles) { + case 'sheet': + imports.push(`import 'piral-core/style.css';`); + // no return - we fall through and also include the dummy applyStyle for "none" + case 'none': + exports.push(` + export function applyStyle(element) {} + `); + return; + case 'inline': + default: + exports.push(` + export function applyStyle(element) { + element.style.display = 'contents'; + } + `); + return; + } +} + export function createDependencies(imports: Array, exports: Array, opts: CodegenOptions) { const { root, appName, externals, shared, origin } = opts; const assignments: Array = []; @@ -142,7 +164,6 @@ export function createDependencies(imports: Array, exports: Array