web: Storybook css import fix (#5964)

* web: fix storybook `build` css import issue

This is an incredibly frustrating issue, because Storybook works
in `dev` mode but not in `build` mode, and that's not at all what
you'd expecte from a mature piece of software.  Lit uses the native
CSS adoptedStylesheets field, which takes only a constructedStylesheet.
Lit provides a way of generating those, but the imports from
Patternfly (or any `.css` file) are text, and converting those to
stylesheets required a bit of magic.

What this means going forward is that any Storied components will
have to have their CSS wrapped in a way that ensures it is managed
correctly by Lit (well, to be pedantic, by the
shadowDOM.adoptedStylesheets).  That wrapper is provided and the
components that need it have been wrapped.

This problem deserves further investigation, but for the time
being this actually does solve it with a minimum amount of surgical
pain.

* web: fix storybook build issue

This commit further fixes the typing issues around strings, CSSResults,
and CSSStyleSheets by providing overloaded functions that assist
consumers in knowing that if they send an array to expect an array
in return, and if they send a scalar expect a scalar in return.

* replace any with unknown

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Ken Sternberg 2023-06-16 04:36:04 -07:00 committed by GitHub
parent 50fd93b7cd
commit f179d6572e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 5 deletions

View File

@ -1,5 +1,7 @@
import { SentryIgnoredError } from "@goauthentik/common/errors";
import { CSSResult, css } from "lit";
export function getCookie(name: string): string {
let cookieValue = "";
if (document.cookie && document.cookie !== "") {
@ -115,3 +117,28 @@ export function dateTimeLocal(date: Date): string {
const parts = localISOTime.split(":");
return `${parts[0]}:${parts[1]}`;
}
// Lit is extremely well-typed with regard to CSS, and Storybook's `build` does not currently have a
// coherent way of importing CSS-as-text into CSSStyleSheet. It works well when Storybook is running
// in `dev,` but in `build` it fails. Storied components will have to map their textual CSS imports
// using the function below.
type AdaptableStylesheet = Readonly<string | CSSResult | CSSStyleSheet>;
type AdaptedStylesheets = CSSStyleSheet | CSSStyleSheet[];
const isCSSResult = (v: unknown): v is CSSResult =>
v instanceof CSSResult && v.styleSheet !== undefined;
// prettier-ignore
export const _adaptCSS = (sheet: AdaptableStylesheet): CSSStyleSheet =>
(typeof sheet === "string" ? css([sheet] as unknown as TemplateStringsArray, ...[]).styleSheet
: isCSSResult(sheet) ? sheet.styleSheet
: sheet) as CSSStyleSheet;
// Overloaded function definitions inform consumers that if you pass it an array, expect an array in
// return; if you pass it a scaler, expect a scalar in return.
export function adaptCSS(sheet: AdaptableStylesheet): CSSStyleSheet;
export function adaptCSS(sheet: AdaptableStylesheet[]): CSSStyleSheet[];
export function adaptCSS(sheet: AdaptableStylesheet | AdaptableStylesheet[]): AdaptedStylesheets {
return Array.isArray(sheet) ? sheet.map(_adaptCSS) : _adaptCSS(sheet);
}

View File

@ -1,8 +1,9 @@
import { config, tenant } from "@goauthentik/common/api/config";
import { EVENT_LOCALE_CHANGE, EVENT_THEME_CHANGE } from "@goauthentik/common/constants";
import { UIConfig, uiConfig } from "@goauthentik/common/ui/config";
import { adaptCSS } from "@goauthentik/common/utils";
import { CSSResult, LitElement } from "lit";
import { LitElement } from "lit";
import { state } from "lit/decorators.js";
import AKGlobal from "@goauthentik/common/styles/authentik.css";
@ -68,8 +69,7 @@ export class AKElement extends LitElement {
if ("ShadyDOM" in window) {
styleRoot = document;
}
const globalStyleSheet = AKGlobal instanceof CSSResult ? AKGlobal.styleSheet : AKGlobal;
styleRoot.adoptedStyleSheets = [...styleRoot.adoptedStyleSheets, globalStyleSheet];
styleRoot.adoptedStyleSheets = adaptCSS([...styleRoot.adoptedStyleSheets, AKGlobal]);
this._initTheme(styleRoot);
this._initCustomCSS(styleRoot);
return root;

View File

@ -1,4 +1,5 @@
import { docLink } from "@goauthentik/common/global";
import { adaptCSS } from "@goauthentik/common/utils";
import { AKElement } from "@goauthentik/elements/Base";
import { paramURL } from "@goauthentik/elements/router/RouterOutlet";
@ -19,7 +20,7 @@ import PFSpacing from "@patternfly/patternfly/utilities/Spacing/spacing.css";
* administrator, provide a link to the "Create a new application" page.
*/
const styles = [
const styles = adaptCSS([
PFBase,
PFEmptyState,
PFButton,
@ -31,7 +32,7 @@ const styles = [
font-weight: bold;
}
`,
];
]);
@customElement("ak-library-application-empty-list")
export class LibraryPageApplicationEmptyList extends AKElement {