@@ -31,16 +31,35 @@ export const restoreScroll = ( target: HTMLElement = document.documentElement )
3131
3232}
3333
34+
35+ /**
36+ * Represents a URL stylesheet as a simple URL input, URL object or as an object
37+ * with URL and fetch configuration options.
38+ */
39+ export type UrlStylesheet = UrlInput | {
40+ /**
41+ * The URL string or a URL object of the stylesheet to load.
42+ *
43+ */
44+ url : UrlInput
45+ /**
46+ * Indicates whether to fetch the given URL.
47+ *
48+ * @default false
49+ */
50+ fetch ?: boolean
51+ }
52+
53+
3454/**
3555 * Represents a style input.
3656 *
37- *
38- * @property {UrlInput } - A URL string or input pointing to an external stylesheet
39- * @property {HTMLStyleElement } - An HTML style element containing CSS rules
40- * @property {CSSStyleSheet } - A CSS stylesheet object
41- * @property {StyleSheetList } - A collection of CSS stylesheets
57+ * @property {UrlStylesheet } - A URL string or input pointing to a stylesheet file URL.
58+ * @property {HTMLStyleElement } - An HTML style element containing CSS rules.
59+ * @property {CSSStyleSheet } - A CSS stylesheet object.
60+ * @property {StyleSheetList } - A collection of CSS stylesheets.
4261 */
43- export type Style = UrlInput | HTMLStyleElement | CSSStyleSheet | StyleSheetList
62+ export type Style = UrlStylesheet | HTMLStyleElement | CSSStyleSheet | StyleSheetList
4463
4564
4665/**
@@ -50,6 +69,8 @@ export type Style = UrlInput | HTMLStyleElement | CSSStyleSheet | StyleSheetList
5069 */
5170export type Styles = Style | Style [ ]
5271
72+ export type CloneStyleSheetsReturn = ( HTMLStyleElement | HTMLLinkElement ) [ ]
73+
5374
5475/**
5576 * Clones a StyleSheetList or array of CSSStyleSheets into an array of `HTMLStyleElement` objects.
@@ -70,8 +91,8 @@ export type Styles = Style | Style[]
7091 * styles.forEach( style => shadowRoot.appendChild( style ) )
7192 * ```
7293 */
73- export const cloneStyleSheetList = ( styles : StyleSheetList | CSSStyleSheet [ ] ) => (
74- [ ...styles ] . map ( ( { cssRules } ) => {
94+ const cloneStyleSheetList = ( styleSheets : StyleSheetList | CSSStyleSheet [ ] ) => (
95+ [ ...styleSheets ] . map ( ( { cssRules } ) => {
7596 try {
7697
7798 const style = document . createElement ( 'style' )
@@ -91,35 +112,43 @@ export const cloneStyleSheetList = ( styles: StyleSheetList | CSSStyleSheet[] )
91112 } catch ( error ) {
92113
93114 console . error ( 'Error while cloning styles.' , error )
94-
115+
95116 }
96117 } ) . filter ( Boolean ) as HTMLStyleElement [ ]
97118)
98119
99120
100121/**
101- * Clones style sheets from various sources into new ` HTMLStyleElement` instances .
122+ * Clones style sheets from various sources into new HTMLStyleElement nodes .
102123 *
103- * @param styles A single style source or array of style sources. Can be:
104- * - `StyleSheetList`: A list of stylesheets
105- * - `CSSStyleSheet`: A single stylesheet object
106- * - `HTMLStyleElement`: A style DOM element
107- * - `UrlInput `: A URL string or object pointing to a stylesheet
124+ * @param styles A style source or array of style sources. Style source an be:
125+ * - `StyleSheetList`: A list of stylesheets.
126+ * - `CSSStyleSheet` A single stylesheet object.
127+ * - `HTMLStyleElement`: A style DOM element.
128+ * - `UrlStylesheet `: A URL stylesheet as a simple URL input, URL object or as an object with URL and fetch configuration options.
108129 *
109- * @returns A promise that resolves to an array of cloned `HTMLStyleElement` nodes.
110- * Each element is a new style element containing the CSS rules from the source.
130+ * @returns A promise that resolves to an array of cloned HTMLStyleElement and HTMLLinkElement nodes.
131+ * For inline styles and StyleSheetLists, returns HTMLStyleElement nodes.
132+ * For URL-based stylesheets, returns HTMLLinkElement nodes (or HTMLStyleElement if fetch is true).
133+ * Failed operations are silently ignored.
134+ *
135+ * @remarks
136+ * - When a URL stylesheet has `fetch: true`, the stylesheet content is fetched and embedded as inline CSS.
137+ * - When `fetch: false` (default), a link element is created instead.
138+ * - URL parsing is handled through the Url utility with support for both string and `UrlInput` object formats.
111139 */
112- export const cloneStyleSheets = async ( styles : Styles ) : Promise < HTMLStyleElement [ ] > => {
140+ export const cloneStyleSheets = async ( styles : Styles ) : Promise < CloneStyleSheetsReturn > => {
113141
114142 if ( ! Array . isArray ( styles ) ) {
115143 return cloneStyleSheets ( [ styles ] )
116144 }
117145
118- const styleNodes : HTMLStyleElement [ ] = [ ]
146+ const styleNodes : CloneStyleSheetsReturn = [ ]
147+
119148 const styleSheetList : StyleSheetList [ ] = [ ]
120149 const styleSheets : CSSStyleSheet [ ] = [ ]
121150 const styleElements : HTMLStyleElement [ ] = [ ]
122- const styleUrls : UrlInput [ ] = [ ]
151+ const styleUrls : UrlStylesheet [ ] = [ ]
123152
124153 styles . forEach ( style => {
125154 if ( style instanceof StyleSheetList ) {
@@ -161,7 +190,28 @@ export const cloneStyleSheets = async ( styles: Styles ): Promise<HTMLStyleEleme
161190 await Promise . allSettled (
162191 styleUrls . map ( async urlInput => {
163192
164- const { data, error } = await fetch < string > ( Url . format ( urlInput ) )
193+ const isUrlString = typeof urlInput === 'string'
194+
195+ const url = (
196+ ! isUrlString && 'url' in urlInput && Url . format ( urlInput . url )
197+ ) || Url . format ( urlInput as UrlInput )
198+
199+ const fetchUrl = (
200+ ! isUrlString && 'fetch' in urlInput && urlInput . fetch
201+ ) ?? false
202+
203+ if ( ! fetchUrl ) {
204+ const link = document . createElement ( 'link' )
205+ link . rel = 'stylesheet'
206+ link . href = url
207+
208+ styleNodes . push ( link )
209+
210+ return link
211+ }
212+
213+
214+ const { data, error } = await fetch < string > ( url )
165215
166216 if ( error ) throw error
167217
0 commit comments