diff --git a/packages/ui/deno.json b/packages/ui/deno.json index 73e0294..e0fa3df 100644 --- a/packages/ui/deno.json +++ b/packages/ui/deno.json @@ -1,6 +1,9 @@ { "name": "@sikessem/ui", "version": "0.0.0", + "imports": { + "npm:plugwind.js": "jsr:@siguici/plugwind" + }, "exports": { ".": "./jsr/index.ts" }, diff --git a/packages/ui/deno.lock b/packages/ui/deno.lock index cd9ead8..4239bc8 100644 --- a/packages/ui/deno.lock +++ b/packages/ui/deno.lock @@ -695,6 +695,9 @@ }, "remote": {}, "workspace": { + "dependencies": [ + "jsr:@siguici/plugwind" + ], "packageJson": { "dependencies": [ "npm:@types/node@^22.2.0", diff --git a/packages/ui/src/colors.ts b/packages/ui/src/colors.ts index b73033d..34700e2 100644 --- a/packages/ui/src/colors.ts +++ b/packages/ui/src/colors.ts @@ -11,11 +11,14 @@ import { Plugin } from "./plugin"; export type ColorName = keyof typeof colors; export type ColorValue = string; export type ColorValues = Record; +export type ColorVariant = ColorValues | ColorValue; export type RequiredColorVariants = { default: ColorValue; light: ColorValues; dark: ColorValues; }; +export type ColorScheme = + T extends ColorValue ? "default" : "light" | "dark"; export type ColorVariants = Partial; export class Colors extends Plugin { @@ -1215,15 +1218,13 @@ export class Colors extends Plugin { } protected addColor(name: string, variants: ColorVariants): this { - Object.entries(variants).forEach((color) => { - const scheme = color[0]; - const value = color[1]; + for (const [scheme, value] of Object.entries(variants)) { if (typeof value === "string") { this.addColorValue(name, value); } else { - this.matchColorValues(`${name}-${scheme}`, variants[scheme]); + this.matchColorValues(`${name}-${scheme}`, value); } - }); + } return this.matchColorScheme(name, variants); } @@ -1278,11 +1279,11 @@ export class Colors extends Plugin { ): RuleSet[] { const { e } = this.api; const style: RuleSet[] = []; - Object.entries(this.components).forEach((component) => { + for (const component of Object.entries(this.components)) { const name = `${component[0]}-${variant}`; const utilities = component[1]; - Object.entries(lightValues).forEach((color) => { + for (const color of Object.entries(lightValues)) { const colorKey = color[0]; const colorName = `${name}-${colorKey}`; const colorValue = color[1]; @@ -1309,7 +1310,7 @@ export class Colors extends Plugin { ), ); } else { - Object.entries(utilities).forEach((utility) => { + for (const utility of Object.entries(utilities)) { const utilityName = utility[0] === "DEFAULT" ? colorName @@ -1338,10 +1339,10 @@ export class Colors extends Plugin { ), ); } - }); + } } - }); - }); + } + } return style; } @@ -1351,12 +1352,10 @@ export class Colors extends Plugin { darkValues: ColorValues | undefined = undefined, ): RuleSet[] { const style: RuleSet[] = []; - Object.entries(this.utilities).forEach((utility) => { + for (const utility of Object.entries(this.utilities)) { const utilityName = `${utility[0]}-${variant}`; const propertyName = utility[1]; - Object.entries(lightValues).forEach((color) => { - const colorKey = color[0]; - const colorValue = color[1]; + for (const [colorKey, colorValue] of Object.entries(lightValues)) { style.push( darken_class( this.darkMode, @@ -1367,8 +1366,8 @@ export class Colors extends Plugin { : stylize_property(propertyName, darkValues[colorKey]), ), ); - }); - }); + } + } return style; } @@ -1376,7 +1375,7 @@ export class Colors extends Plugin { const { e } = this.api; let rules: RuleSet = {}; - Object.entries(this.utilities).forEach((utility) => { + for (const utility of Object.entries(this.utilities)) { const utilityName = `${utility[0]}-${e(name)}`; const propertyName = utility[1]; rules = append_style( @@ -1385,7 +1384,7 @@ export class Colors extends Plugin { }), rules, ); - }); + } return rules; } @@ -1393,12 +1392,10 @@ export class Colors extends Plugin { const { e } = this.api; const rules: StyleCallbacks = {}; - Object.entries(this.utilities).forEach((utility) => { - const utilityName = utility[0]; - const propertyName = utility[1]; + for (const [utilityName, propertyName] of Object.entries(this.utilities)) { rules[`${utilityName}-${e(name)}`] = (value) => stylize_property(propertyName, value); - }); + } return rules; } } diff --git a/packages/ui/src/plugger.ts b/packages/ui/src/plugger.ts index c855c65..0d32b38 100644 --- a/packages/ui/src/plugger.ts +++ b/packages/ui/src/plugger.ts @@ -7,10 +7,13 @@ import type { UIOptions, } from "."; -import plug, { +import _plug, { + type Plug, + type Plugin, type PluginAPI, type PluginCreator, type PluginCreatorWithOptions, + type PluginWithOptions, } from "plugwind.js"; import { Colors } from "./colors"; import { Edges } from "./edges"; @@ -23,20 +26,56 @@ export const DEFAULT_OPTIONS: RequiredUIOptions = { }; export function plugUI(): PluginCreatorWithOptions { - return plug.with((options: UIOptions = DEFAULT_OPTIONS) => (api) => { - useColors(api); - useLinks(api, { - linkClass: options.linkClass || DEFAULT_OPTIONS.linkClass, - }); - useEdges(api, { - entryClass: options.entryClass || DEFAULT_OPTIONS.entryClass, - buttonClass: options.buttonClass || DEFAULT_OPTIONS.buttonClass, - }); - }); + return plug.with( + (options: UIOptions = DEFAULT_OPTIONS) => + (api: PluginAPI) => { + useColors(api); + useLinks(api, { + linkClass: options.linkClass || DEFAULT_OPTIONS.linkClass, + }); + useEdges(api, { + entryClass: options.entryClass || DEFAULT_OPTIONS.entryClass, + buttonClass: options.buttonClass || DEFAULT_OPTIONS.buttonClass, + }); + }, + ); } +const isPlug = (plug: unknown): plug is Plug => { + return ( + typeof plug === "function" && typeof (plug as Plug).with === "function" + ); +}; + +const toPlug = (plug: unknown): Plug => { + if (isPlug(plug)) { + return plug; + } + + const plugWithMethod: Plug = Object.assign( + (plugin: Plugin): PluginCreator => { + if (typeof plug !== "function") { + throw new Error("Invalid plug type"); + } + return plug(plugin); + }, + { + with(plugin: PluginWithOptions): PluginCreatorWithOptions { + if (isPlug(plug)) { + return plug.with(plugin); + } + throw new Error("Invalid plug type"); + }, + }, + ); + + return plugWithMethod; +}; + +const plug: Plug = toPlug(_plug); + export function plugColors(): PluginCreator { - return plug((api) => useColors(api)); + return plug((api: PluginAPI) => useColors(api)); } export function plugLinks(): PluginCreatorWithOptions { @@ -46,7 +85,7 @@ export function plugLinks(): PluginCreatorWithOptions { linkClass: DEFAULT_OPTIONS.linkClass, }, ) => - (api) => + (api: PluginAPI) => useLinks(api, options as RequiredLinkOptions), ); } @@ -59,7 +98,7 @@ export function plugEdges(): PluginCreatorWithOptions { buttonClass: DEFAULT_OPTIONS.buttonClass, }, ) => - (api) => { + (api: PluginAPI) => { const plugin = new Edges(api, options as RequiredEdgeOptions); return plugin.create(); }, diff --git a/packages/ui/src/plugin.ts b/packages/ui/src/plugin.ts index 56e5260..c40b709 100644 --- a/packages/ui/src/plugin.ts +++ b/packages/ui/src/plugin.ts @@ -3,6 +3,7 @@ import type { DarkModeConfig, PluginAPI } from "tailwindcss/types/config"; import type { ComponentList, DarkMode, + DarkModeStrategy, PropertyName, PropertyValue, RuleSet, @@ -45,7 +46,7 @@ export abstract class Plugin implements PluginContract { configDarkMode === "media" ? mediaQuery : classQuery, ]; } else if (configDarkMode[0] !== undefined) { - this.darkMode = [configDarkMode[0], classQuery]; + this.darkMode = [configDarkMode[0] as DarkModeStrategy, classQuery]; } } } @@ -58,9 +59,9 @@ export abstract class Plugin implements PluginContract { protected getPropertiesOf(utilities: UtilityName[]): PropertyName[] { const properties: PropertyName[] = []; - utilities.forEach((utility) => { + for (const utility of utilities) { properties.push(this.getPropertyOf(utility)); - }); + } return properties; } @@ -90,7 +91,7 @@ export abstract class Plugin implements PluginContract { const { e } = this.api; const rules: StyleCallbacks = {}; - Object.entries(this.components).forEach((component) => { + for (const component of Object.entries(this.components)) { const name = `${component[0]}-${e(variant)}`; const utilities = component[1]; @@ -99,7 +100,7 @@ export abstract class Plugin implements PluginContract { } else if (Array.isArray(utilities)) { rules[name] = this.stylizeUtilitiesCallback(utilities); } else { - Object.entries(utilities).forEach((utility) => { + for (const utility of Object.entries(utilities)) { const utilityName = utility[0] === "DEFAULT" ? name : `${name}-${e(utility[0])}`; const properties = utility[1]; @@ -108,9 +109,9 @@ export abstract class Plugin implements PluginContract { } else { rules[utilityName] = this.stylizeUtilitiesCallback(properties); } - }); + } } - }); + } return rules; } @@ -118,7 +119,7 @@ export abstract class Plugin implements PluginContract { const { e } = this.api; let rules: RuleSet = {}; - Object.entries(this.components).forEach((component) => { + for (const component of Object.entries(this.components)) { const name = `${component[0]}-${e(variant)}`; const utilities = component[1]; @@ -133,7 +134,7 @@ export abstract class Plugin implements PluginContract { rules, ); } else { - Object.entries(utilities).forEach((utility) => { + for (const utility of Object.entries(utilities)) { const utilityName = utility[0] === "DEFAULT" ? name : `${name}-${e(utility[0])}`; const properties = utility[1]; @@ -154,9 +155,9 @@ export abstract class Plugin implements PluginContract { rules, ); } - }); + } } - }); + } return rules; }