import { IS_BROWSER } from 'fresh/runtime'
import { styles } from './SmartStylesheetCommon.tsx'
/**
* Generate a css scope for the given component/island based on its name.
*
* @param component - Component or island to scope.
* @returns scope - css scope class.
*
* @example
* ```ts
* // ./(components|islands)/Button.tsx
* import type { JSX } from 'preact'
* import { getStyleScope, useSmartStylesheet } from './SmartStylesheet.tsx'
*
* const scope = getStyleScope(Button)
*
* export function Button(props: JSX.ButtonHTMLAttributes) {
* useSmartStylesheet(import.meta, { scope })
*
* return
* }
* ```
*/
export function getStyleScope }>(
component: T,
): string {
// generate scope/class hash
return `_scope_${
btoa(component.name).slice(-10).replaceAll('=', '_').toLowerCase()
}`
}
/**
* Hook to load component/island stylesheet only when
* it is imported by the served route.
* For any `./(component|islands)/Element.tsx` it will
* load the corresponding `./(component|islands)/Element.css`
*
* @param meta - Component ImportMeta used to resolve
* stylesheet path, name and layer.
* @param options - CSS scope to use (default: none)
* and css layer ('components' or 'islands') depending of the ImportMeta.
*
* @example Basic usage
* ```ts
* // ./(components|islands)/Button.tsx
* import type { JSX } from 'preact'
* import { useSmartStylesheet } from './SmartStylesheet.tsx'
*
* export function Button(props: JSX.ButtonHTMLAttributes) {
* useSmartStylesheet(import.meta)
*
* return
* }
* ```
*
* @example Use css scope
* ```ts
* // ./(components|islands)/Button.tsx
* import type { JSX } from 'preact'
* import { getStyleScope, useSmartStylesheet } from './SmartStylesheet.tsx'
*
* const scope = getStyleScope(Button)
*
* export function Button(props: JSX.ButtonHTMLAttributes) {
* useSmartStylesheet(import.meta, { scope })
*
* return
* }
* ```
*
* @example Use custom layer
* ```ts
* // ./(components|islands)/Button.tsx
* import type { JSX } from 'preact'
* import { getStyleScope, useSmartStylesheet } from './SmartStylesheet.tsx'
*
* const scope = getStyleScope(Button)
*
* export function Button(props: JSX.ButtonHTMLAttributes) {
* useSmartStylesheet(import.meta, { scope, layer: 'custom' })
*
* return
* }
* ```
*/
export function useSmartStylesheet(
meta: ImportMeta,
options?: { scope?: string; layer?: string },
) {
if (IS_BROWSER) return
// resolve filename
const css = meta.filename
?.replace('.tsx', '.css')
.replace(Deno.cwd(), '')
.replaceAll('\\', '/')
if (!css) return
if (styles.has(css)) return
// set css layer
const layerValue = options?.layer ?? css.includes('/components/')
? 'components'
: css.includes('/islands/')
? 'islands'
: undefined
styles.set(css, { url: css, scope: options?.scope, layer: layerValue })
}