@slabui/theme-core 0.0.5 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/files.d.mts +2 -0
- package/dist/files.d.mts.map +1 -1
- package/dist/files.mjs +1 -5
- package/dist/index.d.mts +28 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +18 -2
- package/dist/index.mjs.map +1 -1
- package/dist/theme-files-a8APQNco.mjs +12 -0
- package/dist/theme-files-a8APQNco.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/css-COrLu65l.mjs +0 -9
- package/dist/css-COrLu65l.mjs.map +0 -1
- package/dist/files.mjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @slabui/theme-core
|
|
2
2
|
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#85](https://github.com/slabui/ui/pull/85) [`3b1257c`](https://github.com/slabui/ui/commit/3b1257cf215e6546875379bd1f0f4103fbc45148) Thanks [@andrefelipeschulle](https://github.com/andrefelipeschulle)! - O CSS global passa a ter só o tema, com o resto em dois arquivos ao lado dele:
|
|
8
|
+
|
|
9
|
+
- `slabui init` cria o `utilities.css` (`@utility` e `@custom-variant`, com a `no-scrollbar`) e, num CSS global novo, o `base.css` (o `@layer base`, com a barra de rolagem e o `body`). O CSS global importa os dois. Num CSS que já existe, o `@layer base` dele continua valendo e o `base.css` não é criado.
|
|
10
|
+
- O tema do `init` começa enxuto: o `@theme inline` e só as cores que o `base.css` usa (`background`, `foreground`, `border`, `input`, `ring`, `scrollbar-thumb`), mais `radius` e `spacing`. Cada `slabui add` e `slabui update` acrescenta as variáveis do tema padrão que o componente usa e faltam no CSS, sem trocar um valor que já está lá.
|
|
11
|
+
- Os itens podem trazer `@utility`, `@custom-variant` (para o `utilities.css`, com merge pelo nome) e declarações de base (para o `base.css`, com merge por seletor e propriedade). O `add` cria o arquivo e o `@import` quando faltam; o `update` segue as mesmas regras das variáveis.
|
|
12
|
+
- O tema padrão ganha a `--scrollbar-thumb`.
|
|
13
|
+
|
|
3
14
|
## 0.0.5
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
package/dist/files.d.mts
CHANGED
|
@@ -4,7 +4,9 @@ export declare function removeTokens(css: string, unset: UnsetTokens, { theme }?
|
|
|
4
4
|
}): string;
|
|
5
5
|
export declare function themeFileHeader(name: string): string;
|
|
6
6
|
export declare function renameThemeSelectors(css: string, from: string, to: string): string;
|
|
7
|
+
export declare function localImports(css: string): string[];
|
|
7
8
|
export declare function addThemeImport(css: string, path: string): string;
|
|
9
|
+
export declare function addImport(css: string, path: string): string;
|
|
8
10
|
export declare function removeThemeImport(css: string, path: string): string;
|
|
9
11
|
export declare function renameThemeImport(css: string, from: string, to: string): string;
|
|
10
12
|
//# sourceMappingURL=files.d.mts.map
|
package/dist/files.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.d.mts","names":[],"sources":["../src/theme-files.ts"],"mappings":"A,YAKY,cAAc,QAAQ;wBAMlB,aACd,aACA,OAAO,eACL;EAAW;;wBAoBC,gBAAgB;wBAQhB,qBACd,aACA,cACA;wBA2Cc,eAAe,aAAa;
|
|
1
|
+
{"version":3,"file":"files.d.mts","names":[],"sources":["../src/theme-files.ts"],"mappings":"A,YAKY,cAAc,QAAQ;wBAMlB,aACd,aACA,OAAO,eACL;EAAW;;wBAoBC,gBAAgB;wBAQhB,qBACd,aACA,cACA;wBA2Cc,aAAa;wBAUb,eAAe,aAAa;wBAM5B,UAAU,aAAa;wBAkBvB,kBAAkB,aAAa;wBAU/B,kBAAkB,aAAa,cAAc"}
|
package/dist/files.mjs
CHANGED
|
@@ -1,5 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
<html ${e}="${t}"> ou SLABUI_THEME=${t}. */
|
|
3
|
-
`}function s(n,i,a){if(!t(i)||!t(a))throw Error(`Invalid theme name: "${i}" → "${a}"`);let o=RegExp(`\\[${e}\\s*=\\s*(["']?)${i}\\1\\s*\\]`,`g`),s=r.parse(n);return s.walkRules(t=>{t.selector=t.selector.replace(o,`[${e}="${a}"]`)}),s.walkComments(e=>{e.text=e.text.replaceAll(`"${i}"`,`"${a}"`).replaceAll(`SLABUI_THEME=${i}`,`SLABUI_THEME=${a}`)}),s.toString()}function c(e){return e.params.trim().replace(/^url\((.*)\)/,`$1`).split(/\s/)[0]?.replace(/^["']|["']$/g,``)}const l=(e,t)=>e!==void 0&&e.replace(/^\.\//,``)===t.replace(/^\.\//,``);function u(e){return e.nodes.filter(e=>e.type===`atrule`&&e.name===`import`)}function d(e,t){let n=r.parse(e),i=u(n);if(i.some(e=>l(c(e),t)))return e;let a=r.atRule({name:`import`,params:`"${t}"`}),o=i.at(-1);return o?(a.raws={before:`
|
|
4
|
-
`},o.after(a)):(a.raws={before:``},n.prepend(a)),n.toString()}function f(e,t){let n=r.parse(e);for(let e of u(n))l(c(e),t)&&e.remove();return n.toString()}function p(e,t,n){let i=r.parse(e);for(let e of u(i))l(c(e),t)&&(e.params=`"${n}"`);return i.toString()}export{d as addThemeImport,f as removeThemeImport,a as removeTokens,p as renameThemeImport,s as renameThemeSelectors,o as themeFileHeader};
|
|
5
|
-
//# sourceMappingURL=files.mjs.map
|
|
1
|
+
import"./attribute.mjs";export{t as addImport,n as addThemeImport,r as localImports,i as removeThemeImport,a as removeTokens,o as renameThemeImport,s as renameThemeSelectors,c as themeFileHeader}from"./theme-files-a8APQNco.mjs";
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { THEME_ATTRIBUTE, THEME_ENV, isThemeName, themeAttribute, themeSelector } from "./attribute.mjs";
|
|
2
|
+
import { addImport, localImports } from "./files.mjs";
|
|
2
3
|
import "postcss";
|
|
3
4
|
type ThemeGroup = "theme" | "light" | "dark";
|
|
4
5
|
type ThemeVars = Record<string, string>;
|
|
@@ -50,6 +51,7 @@ export declare const defaultTheme: {
|
|
|
50
51
|
spacing: string;
|
|
51
52
|
radius: string;
|
|
52
53
|
background: string;
|
|
54
|
+
"scrollbar-thumb": string;
|
|
53
55
|
foreground: string;
|
|
54
56
|
card: string;
|
|
55
57
|
"card-foreground": string;
|
|
@@ -96,6 +98,7 @@ export declare const defaultTheme: {
|
|
|
96
98
|
};
|
|
97
99
|
dark: {
|
|
98
100
|
background: string;
|
|
101
|
+
"scrollbar-thumb": string;
|
|
99
102
|
foreground: string;
|
|
100
103
|
card: string;
|
|
101
104
|
"card-foreground": string;
|
|
@@ -139,6 +142,30 @@ export declare const defaultTheme: {
|
|
|
139
142
|
"table-hover": string;
|
|
140
143
|
};
|
|
141
144
|
};
|
|
145
|
+
type CssRules = {
|
|
146
|
+
utilities?: Record<string, string>;
|
|
147
|
+
variants?: Record<string, string>;
|
|
148
|
+
base?: Record<string, Record<string, string>>;
|
|
149
|
+
};
|
|
150
|
+
type CssRuleKind = "utility" | "variant" | "base";
|
|
151
|
+
type CssRuleChange = {
|
|
152
|
+
kind: CssRuleKind;
|
|
153
|
+
name: string;
|
|
154
|
+
action: "added" | "updated" | "kept" | "removed" | "unchanged";
|
|
155
|
+
};
|
|
156
|
+
type CssRulesResult = {
|
|
157
|
+
css: string;
|
|
158
|
+
changes: CssRuleChange[];
|
|
159
|
+
warnings: string[];
|
|
160
|
+
};
|
|
161
|
+
type ApplyCssRulesOptions = {
|
|
162
|
+
base?: CssRules;
|
|
163
|
+
overwrite?: boolean;
|
|
164
|
+
shouldRemove?: (kind: CssRuleKind, name: string) => Promise<boolean>;
|
|
165
|
+
};
|
|
166
|
+
export declare function readCssRules(css: string): Required<Pick<CssRules, "utilities" | "variants">>;
|
|
167
|
+
export declare function applyCssRules(css: string, remote: Pick<CssRules, "utilities" | "variants">, options?: ApplyCssRulesOptions): Promise<CssRulesResult>;
|
|
168
|
+
export declare function applyBaseRules(css: string, remote?: CssRules["base"], options?: ApplyCssRulesOptions): Promise<CssRulesResult>;
|
|
142
169
|
type ValueKind = "color" | "length" | "number" | "keyword" | "expression";
|
|
143
170
|
type ThemeIssue = {
|
|
144
171
|
group: ThemeGroup;
|
|
@@ -167,5 +194,5 @@ type TokenCatalog = {
|
|
|
167
194
|
};
|
|
168
195
|
export declare function tokenCatalog(theme: ThemeTokens, itemVars?: ThemeTokens[]): TokenCatalog;
|
|
169
196
|
export declare function findTokens(contents: string[], catalog: TokenCatalog): string[];
|
|
170
|
-
export { type ApplyCssVarsOptions, type CssVarChange, type CssVarsResult, THEME_ATTRIBUTE, THEME_ENV, type ThemeFileOptions, type ThemeGroup, type ThemeIssue, type ThemeTokens, type ThemeVars, type TokenCatalog, type ValidateThemeOptions, type ValueKind, isThemeName, themeAttribute, themeSelector };
|
|
197
|
+
export { type ApplyCssRulesOptions, type ApplyCssVarsOptions, type CssRuleChange, type CssRuleKind, type CssRules, type CssRulesResult, type CssVarChange, type CssVarsResult, THEME_ATTRIBUTE, THEME_ENV, type ThemeFileOptions, type ThemeGroup, type ThemeIssue, type ThemeTokens, type ThemeVars, type TokenCatalog, type ValidateThemeOptions, type ValueKind, addImport, isThemeName, localImports, themeAttribute, themeSelector };
|
|
171
198
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/css.ts","../src/default-theme.ts","../src/validate.ts","../src/theme.ts","../src/tokens.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/css.ts","../src/default-theme.ts","../src/rules.ts","../src/validate.ts","../src/theme.ts","../src/tokens.ts"],"mappings":";;;KACY;KAGA,YAAY;KAIZ,cAAc,QAAQ,OAAO,YAAY;KCGzC;EACV,OAAO;EACP;EACA;;KAGU;EACV;EACA,SAAS;EACT;;KAGU;EAEV,OAAO;EACP;EAEA,gBAAgB,OAAO,YAAY,iBAAiB;EAGpD;;wBAOoB,aACpB,aACA,QAAQ,eACN,MAAM,WAAmB,cAAc,UAAS,sBACjD,QAAQ;wBAiGK,kBAAkB,MAAM,cAAc;qBCvIzC;;IAET;IACA;IACA;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IAEA;IACA;IAEA;IACA;IACA;IACA;IACA;IACA;IAEA;IAEA;IACA;IAGA;;;IAGA;IACA;IACA;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IAEA;IACA;IACA;IAEA;IACA;IACA;;;IAGA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IAEA;IAEA;IACA;IACA;;;KCrHQ;EACV,YAAY;EACZ,WAAW;EACX,OAAO,eAAe;;KAGZ;KAEA;EACV,MAAM;EAEN;EACA;;KAGU;EACV;EACA,SAAS;EACT;;KAGU;EAEV,OAAO;EACP;EAEA,gBAAgB,MAAM,aAAa,iBAAiB;;wBAatC,aACd,cACC,SAAS,KAAK;wBAmBK,cACpB,aACA,QAAQ,KAAK,qCACb,UAAS,uBACR,QAAQ;wBAgDW,eACpB,aACA,SAAQ,kBACR,UAAS,uBACR,QAAQ;KClIC;KAEA;EACV,OAAO;EACP;EACA;EACA;;qBAGW,6BAA6B;WACnB,QAAQ;EAA7B,YAAqB,QAAQ;;wBAwCf,YAAY;wBA6BZ,aAAa,gBAAgB;KA6BjC;EAEV,YAAY;;wBAKE,cACd,QAAQ,eACN,cAA4B,uBAC7B;KCvGS;EAGV;;wBAOc,UACd,eACE,UAAS,mBACV;wBAsCmB,WACpB,aACA,QAAQ,eAEN,cACG,YACF,KAAK,oCAAoC,uBAC3C,QAAQ;KC1DC;EAEV,MAAM;EAGN,QAAQ;;wBAIM,aACd,OAAO,aACP,WAAU,gBACT;wBAyBa,WACd,oBACA,SAAS"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
-
import{THEME_ATTRIBUTE as e,THEME_ENV as t,isThemeName as n,themeAttribute as r,themeSelector as i}from"./attribute.mjs";import{
|
|
2
|
-
`
|
|
1
|
+
import{THEME_ATTRIBUTE as e,THEME_ENV as t,isThemeName as n,themeAttribute as r,themeSelector as i}from"./attribute.mjs";import{d as a,l as o,r as s,t as c,u as l}from"./theme-files-a8APQNco.mjs";import u from"postcss";const d={theme:{"font-sans":`var(--font-sans)`,"font-heading":`var(--font-heading)`,"font-mono":`var(--font-mono)`,"radius-sm":`calc(var(--radius) * 0.6)`,"radius-md":`calc(var(--radius) * 0.8)`,"radius-lg":`var(--radius)`,"radius-xl":`calc(var(--radius) * 1.4)`,"radius-2xl":`calc(var(--radius) * 1.8)`,"radius-3xl":`calc(var(--radius) * 2.2)`,"radius-4xl":`calc(var(--radius) * 2.6)`,"breakpoint-3xl":`1600px`,"breakpoint-4xl":`2000px`,"text-xxs":`0.625rem`,"text-2xxs":`0.688rem`,"text-2xs":`0.813rem`,"text-2xs--line-height":`calc(1.125 / 0.813)`,"text-2sm":`0.938rem`,"text-2sm--line-height":`calc(1.625 / 0.938)`,spacing:`var(--spacing)`,"focus-size":`calc(var(--focus-size))`,"focus-offset":`var(--focus-offset)`,"color-destructive":`var(--danger)`},light:{spacing:`0.25rem`,radius:`0.65rem`,background:`oklch(1 0 0)`,"scrollbar-thumb":`oklch(0.922 0 0)`,foreground:`oklch(0.145 0 0)`,card:`oklch(1 0 0)`,"card-foreground":`oklch(0.145 0 0)`,popover:`oklch(1 0 0)`,"popover-foreground":`oklch(0.145 0 0)`,muted:`oklch(0.97 0 0)`,"muted-foreground":`oklch(0.556 0 0)`,accent:`oklch(0.97 0 0)`,"accent-foreground":`oklch(0.205 0 0)`,border:`oklch(0.922 0 0)`,input:`oklch(0.922 0 0)`,ring:`oklch(0.708 0 0)`,"chart-1":`oklch(0.646 0.222 41.116)`,"chart-2":`oklch(0.6 0.118 184.704)`,"chart-3":`oklch(0.398 0.07 227.392)`,"chart-4":`oklch(0.828 0.189 84.429)`,"chart-5":`oklch(0.769 0.188 70.08)`,sidebar:`oklch(0.985 0 0)`,"sidebar-foreground":`oklch(0.145 0 0)`,"sidebar-primary":`oklch(0.205 0 0)`,"sidebar-primary-foreground":`oklch(0.985 0 0)`,"sidebar-accent":`oklch(0.97 0 0)`,"sidebar-accent-foreground":`oklch(0.205 0 0)`,"sidebar-border":`oklch(0.922 0 0)`,"sidebar-ring":`oklch(0.708 0 0)`,primary:`oklch(70% 0.1435 227.76)`,"primary-foreground":`oklch(0.985 0 0)`,secondary:`oklch(0.97 0 0)`,"secondary-foreground":`oklch(0.205 0 0)`,danger:`oklch(0.577 0.245 27.325)`,"danger-foreground":`oklch(0.985 0 0)`,success:`oklch(0.728 0.125 139.6)`,"success-foreground":`oklch(0.985 0 0)`,warning:`oklch(0.784 0.181 44.7)`,"warning-foreground":`oklch(0.985 0 0)`,inverted:`oklch(0.205 0 0)`,"inverted-foreground":`oklch(0.97 0 0)`,focus:`oklch(0.7 0.181 44.7)`,"focus-size":`2.5px`,"focus-offset":`2px`,table:`oklch(0.94 0 0 / 65%)`,"table-content":`oklch(1 0 0)`,"table-hover":`oklch(0.98 0 0 / 10%)`},dark:{background:`oklch(0.145 0 0)`,"scrollbar-thumb":`oklch(0.269 0 0)`,foreground:`oklch(0.985 0 0)`,card:`oklch(0.205 0 0)`,"card-foreground":`oklch(0.985 0 0)`,popover:`oklch(0.205 0 0)`,"popover-foreground":`oklch(0.985 0 0)`,secondary:`oklch(0.269 0 0)`,"secondary-foreground":`oklch(0.985 0 0)`,muted:`oklch(0.269 0 0)`,"muted-foreground":`oklch(0.708 0 0)`,accent:`oklch(0.269 0 0)`,"accent-foreground":`oklch(0.985 0 0)`,border:`oklch(1 0 0 / 10%)`,input:`oklch(1 0 0 / 15%)`,ring:`oklch(0.556 0 0)`,"chart-1":`oklch(0.488 0.243 264.376)`,"chart-2":`oklch(0.696 0.17 162.48)`,"chart-3":`oklch(0.769 0.188 70.08)`,"chart-4":`oklch(0.627 0.265 303.9)`,"chart-5":`oklch(0.645 0.246 16.439)`,sidebar:`oklch(0.205 0 0)`,"sidebar-foreground":`oklch(0.985 0 0)`,"sidebar-primary":`oklch(0.488 0.243 264.376)`,"sidebar-primary-foreground":`oklch(0.985 0 0)`,"sidebar-accent":`oklch(0.269 0 0)`,"sidebar-accent-foreground":`oklch(0.985 0 0)`,"sidebar-border":`oklch(1 0 0 / 10%)`,"sidebar-ring":`oklch(0.556 0 0)`,primary:`oklch(66% 0.1435 227.76)`,"primary-foreground":`oklch(0.985 0 0)`,danger:`oklch(0.704 0.191 22.216)`,"danger-foreground":`oklch(0.985 0 0)`,success:`oklch(0.728 0.125 139.6)`,"success-foreground":`oklch(0.985 0 0)`,warning:`oklch(0.784 0.181 44.7)`,"warning-foreground":`oklch(0.985 0 0)`,inverted:`oklch(0.922 0 0)`,"inverted-foreground":`oklch(0.205 0 0)`,focus:`oklch(0.7 0.181 44.7)`,table:`oklch(0.265 0 0)`,"table-content":`oklch(0.205 0 0)`,"table-hover":`oklch(0.22 0 0)`}},f={utility:`utility`,variant:`custom-variant`};function p(e){return e.params.trim().split(/[\s({]/)[0]??``}function m(e){let t=u.parse(e),n={},r={};return t.each(e=>{if(e.type!==`atrule`)return;let t=p(e);e.name===f.utility?n[t]=x(e):e.name===f.variant&&t!==`dark`&&(r[t]=x(e))}),{utilities:n,variants:r}}async function h(e,t,n={}){let r=u.parse(e),i=[],a=[];for(let e of[`variant`,`utility`]){let o=e===`utility`?`utilities`:`variants`,s=t[o]??{},c=n.base?.[o]??{},l=/* @__PURE__ */ new Set([...Object.keys(s),...Object.keys(c)]);for(let t of l){let l=s[t],u=c[t],d=v(r,e,t),f=`${o===`utilities`?`@utility`:`@custom-variant`} ${t}`,p=await _({local:d&&x(d),remote:l,base:u,options:n,kind:e,name:t,label:f,warnings:a,add:t=>y(r,e,t),replace:e=>{let t=b(e);t.raws.before=d?.raws.before??``,d?.replaceWith(t)},remove:()=>d?.remove()});p&&i.push({kind:e,name:t,action:p})}}return{css:r.toString(),changes:i,warnings:a}}async function g(e,t={},n={}){let r=u.parse(e),i=[],a=[],o=n.base?.base??{},s=/* @__PURE__ */ new Set([...Object.keys(t),...Object.keys(o)]);for(let e of s){let s=t[e]??{},c=o[e]??{},l=/* @__PURE__ */ new Set([...Object.keys(s),...Object.keys(c)]);for(let t of l){let o=S(r),l=o&&C(o,e),d=l?.nodes.find(e=>e.type===`decl`&&e.prop===t),f=`${e} { ${t} }`,p=await _({local:d?.value,remote:s[t],base:c[t],options:n,kind:`base`,name:f,label:`${t} in ${e}`,warnings:a,add:n=>{l??=w(r,e),l.append(u.decl({prop:t,value:n,raws:{before:`
|
|
2
|
+
`}}))},replace:e=>{d&&(d.value=e)},remove:()=>{d?.remove(),l?.nodes.length===0&&l.remove()}});p&&i.push({kind:`base`,name:f,action:p})}}return{css:r.toString(),changes:i,warnings:a}}async function _({local:e,remote:t,base:n,options:r,kind:i,name:a,label:o,warnings:s,add:c,replace:l,remove:u}){return t===void 0?e===void 0?void 0:r.shouldRemove&&await r.shouldRemove(i,a)?(u(),`removed`):(s.push(`${o} was removed in the new version; kept in the CSS.`),`kept`):e===void 0?n===void 0?(c(t),`added`):`kept`:E(e,t)?`unchanged`:r.overwrite||n!==void 0&&E(e,n)?(l(t),`updated`):(s.push(`${o} was changed in the CSS; kept instead of the new one.`),`kept`)}function v(e,t,n){return e.nodes.find(e=>e.type===`atrule`&&e.name===f[t]&&p(e)===n)}function y(e,t,n){let r=b(n),i=e.nodes.findLast(e=>e.type===`atrule`&&e.name===f.variant);if(t===`variant`){let t=e.nodes.find(e=>e.type===`atrule`&&e.name===f.utility);if(i){r.raws.before=`
|
|
3
|
+
`,i.after(r);return}if(t){r.raws.before=t.raws.before??``,t.raws.before=`
|
|
4
|
+
|
|
5
|
+
`,t.before(r);return}}r.raws.before=e.nodes.length>0?`
|
|
6
|
+
|
|
7
|
+
`:``,e.append(r),e.raws.after=`
|
|
8
|
+
`}function b(e){let t=u.parse(e.trim()).first;if(t?.type!==`atrule`)throw Error(`Not a CSS at-rule: ${e}`);return t}function x(e){let t=e.clone();return t.raws.before=``,t.nodes===void 0?`${t.toString()};`:t.toString()}function S(e){return e.nodes.find(e=>e.type===`atrule`&&e.name===`layer`&&e.params.trim()===`base`)}function C(e,t){return e.nodes?.find(e=>e.type===`rule`&&T(e.selector)===T(t))}function w(e,t){let n=S(e);n===void 0&&(n=u.atRule({name:`layer`,params:`base`}),n.raws={before:e.nodes.length>0?`
|
|
9
|
+
|
|
10
|
+
`:``,between:` `,after:`
|
|
11
|
+
`},e.append(n),e.raws.after=`
|
|
12
|
+
`);let r=u.rule({selector:t});return r.raws={before:(n.nodes?.length??0)>0?`
|
|
13
|
+
|
|
14
|
+
`:`
|
|
15
|
+
`,between:` `,after:`
|
|
16
|
+
`,semicolon:!0},n.append(r),n.raws.after=`
|
|
17
|
+
`,r}const T=e=>e.replace(/["'\s]/g,``);function E(e,t){let n=e=>e.replace(/\s+/g,` `).replace(/\s*([{};:,])\s*/g,`$1`).replace(/;}/g,`}`).replace(/;$/,``).trim();return n(e)===n(t)}var D=class extends Error{issues;constructor(e){super(`Invalid theme:\n${e.map(({group:e,name:t,message:n})=>` --${t} (${e}): ${n}`).join(`
|
|
18
|
+
`)}`),this.issues=e,this.name=`ThemeValidationError`}};const O=/^[\w-]+$/,k=/^[\w\s.,%#()+\-*/]+$/,A=/* @__PURE__ */ new Set([`rgb`,`rgba`,`hsl`,`hsla`,`hwb`,`lab`,`lch`,`oklab`,`oklch`,`color`,`color-mix`]),j=/* @__PURE__ */ new Set([`calc`,`min`,`max`,`clamp`,`var`]),M=/^#(?:[\da-f]{3,4}|[\da-f]{6}|[\da-f]{8})$/i,N=/^[+-]?(?:\d+\.?\d*|\.\d+)$/,P=/^[+-]?(?:\d+\.?\d*|\.\d+)(?:px|rem|em|%|ch|ex|lh|rlh|vw|vh|vmin|vmax|svh|lvh|dvh|cqw|cqh|pt|pc|in|cm|mm|q|deg|rad|turn|ms|s)$/i,F=/^[a-z][a-z-]*$/i,I=/^([a-z-]+)\(/i;function L(e){if(e.trim()===``||e.length>200||!k.test(e))return!1;let t=0;for(let n of e)if(t+=n===`(`?1:n===`)`?-1:0,t<0)return!1;if(t!==0)return!1;for(let[,t]of e.matchAll(/([a-z-]*)\(/gi)){let e=t.toLowerCase();if(e!==``&&!A.has(e)&&!j.has(e))return!1}return!0}function R(e){let t=e.trim();if(M.test(t))return`color`;if(N.test(t))return`number`;if(P.test(t))return`length`;if(F.test(t))return`keyword`;let n=t.match(I)?.[1]?.toLowerCase();return n&&A.has(n)?`color`:`expression`}function z(e,t){return t===e||t===`expression`||t===`keyword`||e===`length`&&t===`number`}function B(e,{reference:t=d}={}){let n=[];for(let r of[`theme`,`light`,`dark`])for(let[i,a]of Object.entries(e[r]??{})){let e=e=>n.push({group:r,name:i,value:a,message:e});if(!O.test(i)){e(`invalid variable name`);continue}if(typeof a!=`string`||!L(a)){e(`unsafe or malformed value`);continue}let o=t[r]?.[i]??t.light?.[i]??t.dark?.[i];if(o===void 0)continue;let s=R(o),c=R(a);s!==`expression`&&!z(s,c)&&e(`expected a ${s}, got a ${c}`)}return n}const V=[`theme`,`light`,`dark`];function H(e,{theme:t}={}){let n=u.parse(e),r={};for(let e of V){let i={};l(n,e,t)?.each(e=>{e.type===`decl`&&e.prop.startsWith(`--`)&&(i[e.prop.slice(2)]=e.value)}),Object.keys(i).length>0&&(r[e]=i)}if(r.theme){let{theme:e={}}=a({light:r.light,dark:r.dark});for(let[t,n]of Object.entries(e))r.theme[t]===n&&delete r.theme[t];Object.keys(r.theme).length===0&&delete r.theme}return r}async function U(e,t,{reference:n,...r}={}){let i=B(t,{reference:n});if(i.length>0)throw new D(i);return o(e,t,{...r,overwrite:!0})}const W=/(?<![\w-])(?:bg|text|border(?:-[xytrblse])?|ring(?:-offset)?|inset-ring|outline|fill|stroke|from|via|to|decoration|divide|accent|caret|placeholder|shadow|inset-shadow)-([a-z][a-z0-9-]*)(?=[/\s"'`\]);,}!]|$)/g,G=/(?<![\w-])rounded(?:-[trblse]{1,2})?(?:-(?:xs|sm|md|lg|xl|2xl|3xl|4xl))?(?![\w[-])/,K=/(?<![\w-])-?(?:p[xytrblse]?|m[xytrblse]?|gap(?:-[xy])?|space-[xy]|size|[wh]|min-[wh]|max-[wh]|inset(?:-[xy])?|top|right|bottom|left|start|end|translate-[xy]|scroll-[mp][xytrblse]?|indent|basis)-\d+(?:\.\d+)?(?![\w.-])/,q=/--spacing\(/,J=/var\(--([\w-]+)/g;function Y(e,t=[]){let n=/* @__PURE__ */ new Set;for(let r of[e,...t])for(let e of[r.light,r.dark])for(let t of Object.keys(e??{}))n.add(t);let r=/* @__PURE__ */ new Map;for(let e of n)r.set(e,e);for(let i of[e,...t])for(let[e,t]of Object.entries(i.theme??{})){let i=t.match(/^var\(--([\w-]+)\)$/)?.[1];e.startsWith(`color-`)&&i&&n.has(i)&&r.set(e.slice(6),i)}return{vars:n,colors:r}}function X(e,t){let n=/* @__PURE__ */ new Set;for(let r of e){for(let[,e]of r.matchAll(W)){let r=t.colors.get(e);r&&n.add(r)}for(let[,e]of r.matchAll(J))t.vars.has(e)&&n.add(e);t.vars.has(`radius`)&&G.test(r)&&n.add(`radius`),t.vars.has(`spacing`)&&(K.test(r)||q.test(r))&&n.add(`spacing`)}return[...n].sort()}export{e as THEME_ATTRIBUTE,t as THEME_ENV,D as ThemeValidationError,c as addImport,g as applyBaseRules,h as applyCssRules,o as applyCssVars,d as defaultTheme,X as findTokens,R as getValueKind,L as isSafeValue,n as isThemeName,s as localImports,m as readCssRules,H as readTheme,r as themeAttribute,i as themeSelector,Y as tokenCatalog,B as validateTheme,a as withColorMappings,U as writeTheme};
|
|
3
19
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["findBlock","withColorMappings","applyCssVars","postcss","defaultTheme","ThemeValidationError","issues","name","group","message","NAME","SAFE_CHARS","COLOR_FUNCTIONS","MATH_FUNCTIONS","HEX","NUMBER","LENGTH","KEYWORD","FUNCTION","isSafeValue","value","depth","char","fn","getValueKind","trimmed","accepts","actual","expected","validateTheme","tokens","issue","reference","expectedKind","actualKind","GROUPS","readTheme","root","css","vars","theme","node","derived","writeTheme","options","COLOR_UTILITY","RADIUS_UTILITY","SPACING_UTILITY","SPACING_FUNCTION","CSS_VAR","tokenCatalog","itemVars","colors","target","findTokens","found","content","contents","token","catalog","THEME_ATTRIBUTE","THEME_ENV","isThemeName","themeAttribute","themeSelector"],"sources":["../src/default-theme.ts","../src/validate.ts","../src/theme.ts","../src/tokens.ts"],"sourcesContent":["import type { ThemeTokens } from \"./types\"\n\n// Tema padrão da SlabUI. Os `--color-<nome>: var(--<nome>)` do `@theme inline`\n// não ficam aqui: saem das cores de `light` e `dark` na gravação.\nexport const defaultTheme = {\n theme: {\n \"font-sans\": \"var(--font-sans)\",\n \"font-heading\": \"var(--font-heading)\",\n \"font-mono\": \"var(--font-mono)\",\n\n \"radius-sm\": \"calc(var(--radius) * 0.6)\",\n \"radius-md\": \"calc(var(--radius) * 0.8)\",\n \"radius-lg\": \"var(--radius)\",\n \"radius-xl\": \"calc(var(--radius) * 1.4)\",\n \"radius-2xl\": \"calc(var(--radius) * 1.8)\",\n \"radius-3xl\": \"calc(var(--radius) * 2.2)\",\n \"radius-4xl\": \"calc(var(--radius) * 2.6)\",\n\n \"breakpoint-3xl\": \"1600px\",\n \"breakpoint-4xl\": \"2000px\",\n\n \"text-xxs\": \"0.625rem\",\n \"text-2xxs\": \"0.688rem\",\n \"text-2xs\": \"0.813rem\",\n \"text-2xs--line-height\": \"calc(1.125 / 0.813)\",\n \"text-2sm\": \"0.938rem\",\n \"text-2sm--line-height\": \"calc(1.625 / 0.938)\",\n\n spacing: \"var(--spacing)\",\n\n \"focus-size\": \"calc(var(--focus-size))\",\n \"focus-offset\": \"var(--focus-offset)\",\n\n // `destructive` (estados inválidos dos componentes) é a cor `danger`.\n \"color-destructive\": \"var(--danger)\",\n },\n light: {\n spacing: \"0.25rem\",\n radius: \"0.65rem\",\n background: \"oklch(1 0 0)\",\n foreground: \"oklch(0.145 0 0)\",\n card: \"oklch(1 0 0)\",\n \"card-foreground\": \"oklch(0.145 0 0)\",\n popover: \"oklch(1 0 0)\",\n \"popover-foreground\": \"oklch(0.145 0 0)\",\n muted: \"oklch(0.97 0 0)\",\n \"muted-foreground\": \"oklch(0.556 0 0)\",\n accent: \"oklch(0.97 0 0)\",\n \"accent-foreground\": \"oklch(0.205 0 0)\",\n border: \"oklch(0.922 0 0)\",\n input: \"oklch(0.922 0 0)\",\n ring: \"oklch(0.708 0 0)\",\n \"chart-1\": \"oklch(0.646 0.222 41.116)\",\n \"chart-2\": \"oklch(0.6 0.118 184.704)\",\n \"chart-3\": \"oklch(0.398 0.07 227.392)\",\n \"chart-4\": \"oklch(0.828 0.189 84.429)\",\n \"chart-5\": \"oklch(0.769 0.188 70.08)\",\n sidebar: \"oklch(0.985 0 0)\",\n \"sidebar-foreground\": \"oklch(0.145 0 0)\",\n \"sidebar-primary\": \"oklch(0.205 0 0)\",\n \"sidebar-primary-foreground\": \"oklch(0.985 0 0)\",\n \"sidebar-accent\": \"oklch(0.97 0 0)\",\n \"sidebar-accent-foreground\": \"oklch(0.205 0 0)\",\n \"sidebar-border\": \"oklch(0.922 0 0)\",\n \"sidebar-ring\": \"oklch(0.708 0 0)\",\n\n primary: \"oklch(70% 0.1435 227.76)\",\n \"primary-foreground\": \"oklch(0.985 0 0)\",\n secondary: \"oklch(0.97 0 0)\",\n \"secondary-foreground\": \"oklch(0.205 0 0)\",\n danger: \"oklch(0.577 0.245 27.325)\",\n \"danger-foreground\": \"oklch(0.985 0 0)\",\n success: \"oklch(0.728 0.125 139.6)\",\n \"success-foreground\": \"oklch(0.985 0 0)\",\n warning: \"oklch(0.784 0.181 44.7)\",\n \"warning-foreground\": \"oklch(0.985 0 0)\",\n inverted: \"oklch(0.205 0 0)\",\n \"inverted-foreground\": \"oklch(0.97 0 0)\",\n\n focus: \"oklch(0.7 0.181 44.7)\",\n \"focus-size\": \"2.5px\",\n \"focus-offset\": \"2px\",\n\n table: \"oklch(0.94 0 0 / 65%)\",\n \"table-content\": \"oklch(1 0 0)\",\n \"table-hover\": \"oklch(0.98 0 0 / 10%)\",\n },\n dark: {\n background: \"oklch(0.145 0 0)\",\n foreground: \"oklch(0.985 0 0)\",\n card: \"oklch(0.205 0 0)\",\n \"card-foreground\": \"oklch(0.985 0 0)\",\n popover: \"oklch(0.205 0 0)\",\n \"popover-foreground\": \"oklch(0.985 0 0)\",\n secondary: \"oklch(0.269 0 0)\",\n \"secondary-foreground\": \"oklch(0.985 0 0)\",\n muted: \"oklch(0.269 0 0)\",\n \"muted-foreground\": \"oklch(0.708 0 0)\",\n accent: \"oklch(0.269 0 0)\",\n \"accent-foreground\": \"oklch(0.985 0 0)\",\n border: \"oklch(1 0 0 / 10%)\",\n input: \"oklch(1 0 0 / 15%)\",\n ring: \"oklch(0.556 0 0)\",\n \"chart-1\": \"oklch(0.488 0.243 264.376)\",\n \"chart-2\": \"oklch(0.696 0.17 162.48)\",\n \"chart-3\": \"oklch(0.769 0.188 70.08)\",\n \"chart-4\": \"oklch(0.627 0.265 303.9)\",\n \"chart-5\": \"oklch(0.645 0.246 16.439)\",\n sidebar: \"oklch(0.205 0 0)\",\n \"sidebar-foreground\": \"oklch(0.985 0 0)\",\n \"sidebar-primary\": \"oklch(0.488 0.243 264.376)\",\n \"sidebar-primary-foreground\": \"oklch(0.985 0 0)\",\n \"sidebar-accent\": \"oklch(0.269 0 0)\",\n \"sidebar-accent-foreground\": \"oklch(0.985 0 0)\",\n \"sidebar-border\": \"oklch(1 0 0 / 10%)\",\n \"sidebar-ring\": \"oklch(0.556 0 0)\",\n\n primary: \"oklch(66% 0.1435 227.76)\",\n \"primary-foreground\": \"oklch(0.985 0 0)\",\n danger: \"oklch(0.704 0.191 22.216)\",\n \"danger-foreground\": \"oklch(0.985 0 0)\",\n success: \"oklch(0.728 0.125 139.6)\",\n \"success-foreground\": \"oklch(0.985 0 0)\",\n warning: \"oklch(0.784 0.181 44.7)\",\n \"warning-foreground\": \"oklch(0.985 0 0)\",\n inverted: \"oklch(0.922 0 0)\",\n \"inverted-foreground\": \"oklch(0.205 0 0)\",\n\n focus: \"oklch(0.7 0.181 44.7)\",\n\n table: \"oklch(0.265 0 0)\",\n \"table-content\": \"oklch(0.205 0 0)\",\n \"table-hover\": \"oklch(0.22 0 0)\",\n },\n} satisfies ThemeTokens\n","import type { ThemeGroup, ThemeTokens } from \"./types\"\n\nimport { defaultTheme } from \"./default-theme\"\n\nexport type ValueKind = \"color\" | \"length\" | \"number\" | \"keyword\" | \"expression\"\n\nexport type ThemeIssue = {\n group: ThemeGroup\n name: string\n value: string\n message: string\n}\n\nexport class ThemeValidationError extends Error {\n constructor(readonly issues: ThemeIssue[]) {\n super(\n `Invalid theme:\\n${issues\n .map(({ group, name, message }) => ` --${name} (${group}): ${message}`)\n .join(\"\\n\")}`,\n )\n this.name = \"ThemeValidationError\"\n }\n}\n\nconst MAX_LENGTH = 200\n\nconst NAME = /^[\\w-]+$/\n// Só o que um valor de tema usa: sem `;`, `{}`, aspas, `\\`, `@`, `!` ou `:`,\n// que permitiriam fechar o bloco ou injetar outra regra.\nconst SAFE_CHARS = /^[\\w\\s.,%#()+\\-*/]+$/\n\nconst COLOR_FUNCTIONS = new Set([\n \"rgb\",\n \"rgba\",\n \"hsl\",\n \"hsla\",\n \"hwb\",\n \"lab\",\n \"lch\",\n \"oklab\",\n \"oklch\",\n \"color\",\n \"color-mix\",\n])\nconst MATH_FUNCTIONS = new Set([\"calc\", \"min\", \"max\", \"clamp\", \"var\"])\n\nconst HEX = /^#(?:[\\da-f]{3,4}|[\\da-f]{6}|[\\da-f]{8})$/i\nconst NUMBER = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)$/\nconst LENGTH =\n /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:px|rem|em|%|ch|ex|lh|rlh|vw|vh|vmin|vmax|svh|lvh|dvh|cqw|cqh|pt|pc|in|cm|mm|q|deg|rad|turn|ms|s)$/i\nconst KEYWORD = /^[a-z][a-z-]*$/i\nconst FUNCTION = /^([a-z-]+)\\(/i\n\n// O valor só usa caracteres e funções conhecidos, com parênteses balanceados.\nexport function isSafeValue(value: string): boolean {\n if (value.trim() === \"\" || value.length > MAX_LENGTH) {\n return false\n }\n if (!SAFE_CHARS.test(value)) {\n return false\n }\n let depth = 0\n for (const char of value) {\n depth += char === \"(\" ? 1 : char === \")\" ? -1 : 0\n if (depth < 0) {\n return false\n }\n }\n if (depth !== 0) {\n return false\n }\n for (const [, name] of value.matchAll(/([a-z-]*)\\(/gi)) {\n // Sem nome, é só um agrupamento: `calc((a + b) * 2)`.\n const fn = name.toLowerCase()\n if (fn !== \"\" && !COLOR_FUNCTIONS.has(fn) && !MATH_FUNCTIONS.has(fn)) {\n return false\n }\n }\n return true\n}\n\n// Tipo do valor, para conferir com o do tema padrão. `calc()` e `var()` são\n// \"expression\": aceitos no lugar de qualquer tipo.\nexport function getValueKind(value: string): ValueKind {\n const trimmed = value.trim()\n if (HEX.test(trimmed)) {\n return \"color\"\n }\n if (NUMBER.test(trimmed)) {\n return \"number\"\n }\n if (LENGTH.test(trimmed)) {\n return \"length\"\n }\n if (KEYWORD.test(trimmed)) {\n return \"keyword\"\n }\n const fn = trimmed.match(FUNCTION)?.[1]?.toLowerCase()\n if (fn && COLOR_FUNCTIONS.has(fn)) {\n return \"color\"\n }\n return \"expression\"\n}\n\nfunction accepts(expected: ValueKind, actual: ValueKind) {\n if (actual === expected || actual === \"expression\" || actual === \"keyword\") {\n return true\n }\n // `0` sem unidade vale como tamanho.\n return expected === \"length\" && actual === \"number\"\n}\n\nexport type ValidateThemeOptions = {\n // Tema que define o tipo de cada token (padrão: `defaultTheme`).\n reference?: ThemeTokens\n}\n\n// Confere nomes e valores antes de gravar ou injetar o tema. Tokens fora da\n// referência só passam pela checagem de segurança.\nexport function validateTheme(\n tokens: ThemeTokens,\n { reference = defaultTheme }: ValidateThemeOptions = {},\n): ThemeIssue[] {\n const issues: ThemeIssue[] = []\n\n for (const group of [\"theme\", \"light\", \"dark\"] as const) {\n for (const [name, value] of Object.entries(tokens[group] ?? {})) {\n const issue = (message: string) =>\n issues.push({ group, name, value, message })\n\n if (!NAME.test(name)) {\n issue(\"invalid variable name\")\n continue\n }\n if (typeof value !== \"string\" || !isSafeValue(value)) {\n issue(\"unsafe or malformed value\")\n continue\n }\n const expected =\n reference[group]?.[name] ??\n reference.light?.[name] ??\n reference.dark?.[name]\n if (expected === undefined) {\n continue\n }\n const expectedKind = getValueKind(expected)\n const actualKind = getValueKind(value)\n if (expectedKind !== \"expression\" && !accepts(expectedKind, actualKind)) {\n issue(`expected a ${expectedKind}, got a ${actualKind}`)\n }\n }\n }\n\n return issues\n}\n","import postcss from \"postcss\"\n\nimport type { ThemeGroup, ThemeTokens, ThemeVars } from \"./types\"\n\nimport {\n type ApplyCssVarsOptions,\n applyCssVars,\n type CssVarsResult,\n findBlock,\n withColorMappings,\n} from \"./css\"\nimport {\n ThemeValidationError,\n type ValidateThemeOptions,\n validateTheme,\n} from \"./validate\"\n\nconst GROUPS: ThemeGroup[] = [\"theme\", \"light\", \"dark\"]\n\nexport type ThemeFileOptions = {\n // Nome do tema, para ler e gravar o arquivo dele (`styles/themes/<nome>.css`)\n // com os blocos `:root[data-slabui-theme=\"<nome>\"]` e `.dark`.\n theme?: string\n}\n\n// Lê o tema do CSS global (`@theme inline`, `:root` e `.dark`), ou de um\n// arquivo de tema com `theme`. Os `--color-<nome>: var(--<nome>)` gerados das\n// cores ficam de fora, como no `defaultTheme`; um mapeamento com outro valor é\n// mantido.\nexport function readTheme(\n css: string,\n { theme }: ThemeFileOptions = {},\n): ThemeTokens {\n const root = postcss.parse(css)\n const tokens: ThemeTokens = {}\n\n for (const group of GROUPS) {\n const vars: ThemeVars = {}\n findBlock(root, group, theme)?.each((node) => {\n if (node.type === \"decl\" && node.prop.startsWith(\"--\")) {\n vars[node.prop.slice(2)] = node.value\n }\n })\n if (Object.keys(vars).length > 0) {\n tokens[group] = vars\n }\n }\n\n if (tokens.theme) {\n const { theme: derived = {} } = withColorMappings({\n light: tokens.light,\n dark: tokens.dark,\n })\n for (const [name, value] of Object.entries(derived)) {\n if (tokens.theme[name] === value) {\n delete tokens.theme[name]\n }\n }\n if (Object.keys(tokens.theme).length === 0) {\n delete tokens.theme\n }\n }\n\n return tokens\n}\n\n// Grava os tokens no CSS global, com merge por variável: só as variáveis\n// passadas mudam, e o resto do arquivo fica como está. Diferente do `add` do\n// registry, o valor do tema substitui o do arquivo. Tokens inválidos\n// interrompem a gravação com `ThemeValidationError`.\nexport async function writeTheme(\n css: string,\n tokens: ThemeTokens,\n {\n reference,\n ...options\n }: Omit<ApplyCssVarsOptions, \"overwrite\"> & ValidateThemeOptions = {},\n): Promise<CssVarsResult> {\n const issues = validateTheme(tokens, { reference })\n if (issues.length > 0) {\n throw new ThemeValidationError(issues)\n }\n return applyCssVars(css, tokens, { ...options, overwrite: true })\n}\n","import type { ThemeTokens } from \"./types\"\n\n// Utilitários de cor do Tailwind: `bg-primary`, `text-muted-foreground`,\n// `dark:border-input/50`, `ring-offset-background`…\nconst COLOR_UTILITY =\n /(?<![\\w-])(?:bg|text|border(?:-[xytrblse])?|ring(?:-offset)?|inset-ring|outline|fill|stroke|from|via|to|decoration|divide|accent|caret|placeholder|shadow|inset-shadow)-([a-z][a-z0-9-]*)(?=[/\\s\"'`\\]);,}!]|$)/g\n\n// `rounded`, `rounded-md`, `rounded-tl-xl`… (sem `none`, `full` e valores\n// arbitrários).\nconst RADIUS_UTILITY =\n /(?<![\\w-])rounded(?:-[trblse]{1,2})?(?:-(?:xs|sm|md|lg|xl|2xl|3xl|4xl))?(?![\\w[-])/\n\n// Escala de espaçamento: `p-4`, `-mt-2`, `gap-x-1.5`, `size-9`, `h-0.5`…\nconst SPACING_UTILITY =\n /(?<![\\w-])-?(?:p[xytrblse]?|m[xytrblse]?|gap(?:-[xy])?|space-[xy]|size|[wh]|min-[wh]|max-[wh]|inset(?:-[xy])?|top|right|bottom|left|start|end|translate-[xy]|scroll-[mp][xytrblse]?|indent|basis)-\\d+(?:\\.\\d+)?(?![\\w.-])/\n\nconst SPACING_FUNCTION = /--spacing\\(/\nconst CSS_VAR = /var\\(--([\\w-]+)/g\n\nexport type TokenCatalog = {\n // Variáveis do tema (`:root`/`.dark`) e as dos próprios itens.\n vars: Set<string>\n // Nome usado nas classes → variável (`destructive` → `danger`, pelo\n // `--color-destructive: var(--danger)` do `@theme inline`).\n colors: Map<string, string>\n}\n\n// Catálogo a partir do tema do CSS global do autor e das `cssVars` dos itens.\nexport function tokenCatalog(\n theme: ThemeTokens,\n itemVars: ThemeTokens[] = [],\n): TokenCatalog {\n const vars = new Set<string>()\n for (const tokens of [theme, ...itemVars]) {\n for (const group of [tokens.light, tokens.dark]) {\n for (const name of Object.keys(group ?? {})) {\n vars.add(name)\n }\n }\n }\n const colors = new Map<string, string>()\n for (const name of vars) {\n colors.set(name, name)\n }\n for (const tokens of [theme, ...itemVars]) {\n for (const [name, value] of Object.entries(tokens.theme ?? {})) {\n const target = value.match(/^var\\(--([\\w-]+)\\)$/)?.[1]\n if (name.startsWith(\"color-\") && target && vars.has(target)) {\n colors.set(name.slice(\"color-\".length), target)\n }\n }\n }\n return { vars, colors }\n}\n\n// Variáveis do tema que os arquivos de um item usam, em ordem alfabética.\nexport function findTokens(\n contents: string[],\n catalog: TokenCatalog,\n): string[] {\n const found = new Set<string>()\n for (const content of contents) {\n for (const [, name] of content.matchAll(COLOR_UTILITY)) {\n const token = catalog.colors.get(name as string)\n if (token) {\n found.add(token)\n }\n }\n for (const [, name] of content.matchAll(CSS_VAR)) {\n if (catalog.vars.has(name as string)) {\n found.add(name as string)\n }\n }\n if (catalog.vars.has(\"radius\") && RADIUS_UTILITY.test(content)) {\n found.add(\"radius\")\n }\n if (\n catalog.vars.has(\"spacing\") &&\n (SPACING_UTILITY.test(content) || SPACING_FUNCTION.test(content))\n ) {\n found.add(\"spacing\")\n }\n }\n return [...found].sort()\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["withColorMappings","applyCssVars","localImports","addImport","findBlock","postcss","defaultTheme","AT_RULE","ruleName","rule","readCssRules","root","css","utilities","variants","node","name","ruleSource","applyCssRules","changes","warnings","kind","field","remoteRules","remote","baseRules","options","names","remoteSource","baseSource","local","findRule","label","result","merge","appendRule","source","next","parseRule","applyBaseRules","previous","selectors","selector","remoteDecls","baseDecls","props","prop","layer","findBaseLayer","findRuleBySelector","declaration","appendBaseRule","value","remove","base","add","same","replace","lastVariant","firstUtility","clone","normalizeSelector","normalize","a","b","ThemeValidationError","issues","group","message","NAME","SAFE_CHARS","COLOR_FUNCTIONS","MATH_FUNCTIONS","HEX","NUMBER","LENGTH","KEYWORD","FUNCTION","isSafeValue","depth","char","fn","getValueKind","trimmed","accepts","actual","expected","validateTheme","tokens","issue","reference","expectedKind","actualKind","GROUPS","readTheme","vars","theme","derived","writeTheme","COLOR_UTILITY","RADIUS_UTILITY","SPACING_UTILITY","SPACING_FUNCTION","CSS_VAR","tokenCatalog","itemVars","colors","target","findTokens","found","content","contents","token","catalog","THEME_ATTRIBUTE","THEME_ENV","isThemeName","themeAttribute","themeSelector"],"sources":["../src/default-theme.ts","../src/rules.ts","../src/validate.ts","../src/theme.ts","../src/tokens.ts"],"sourcesContent":["import type { ThemeTokens } from \"./types\"\n\n// Tema padrão da SlabUI. Os `--color-<nome>: var(--<nome>)` do `@theme inline`\n// não ficam aqui: saem das cores de `light` e `dark` na gravação.\nexport const defaultTheme = {\n theme: {\n \"font-sans\": \"var(--font-sans)\",\n \"font-heading\": \"var(--font-heading)\",\n \"font-mono\": \"var(--font-mono)\",\n\n \"radius-sm\": \"calc(var(--radius) * 0.6)\",\n \"radius-md\": \"calc(var(--radius) * 0.8)\",\n \"radius-lg\": \"var(--radius)\",\n \"radius-xl\": \"calc(var(--radius) * 1.4)\",\n \"radius-2xl\": \"calc(var(--radius) * 1.8)\",\n \"radius-3xl\": \"calc(var(--radius) * 2.2)\",\n \"radius-4xl\": \"calc(var(--radius) * 2.6)\",\n\n \"breakpoint-3xl\": \"1600px\",\n \"breakpoint-4xl\": \"2000px\",\n\n \"text-xxs\": \"0.625rem\",\n \"text-2xxs\": \"0.688rem\",\n \"text-2xs\": \"0.813rem\",\n \"text-2xs--line-height\": \"calc(1.125 / 0.813)\",\n \"text-2sm\": \"0.938rem\",\n \"text-2sm--line-height\": \"calc(1.625 / 0.938)\",\n\n spacing: \"var(--spacing)\",\n\n \"focus-size\": \"calc(var(--focus-size))\",\n \"focus-offset\": \"var(--focus-offset)\",\n\n // `destructive` (estados inválidos dos componentes) é a cor `danger`.\n \"color-destructive\": \"var(--danger)\",\n },\n light: {\n spacing: \"0.25rem\",\n radius: \"0.65rem\",\n background: \"oklch(1 0 0)\",\n // Cor da barra de rolagem (base.css).\n \"scrollbar-thumb\": \"oklch(0.922 0 0)\",\n foreground: \"oklch(0.145 0 0)\",\n card: \"oklch(1 0 0)\",\n \"card-foreground\": \"oklch(0.145 0 0)\",\n popover: \"oklch(1 0 0)\",\n \"popover-foreground\": \"oklch(0.145 0 0)\",\n muted: \"oklch(0.97 0 0)\",\n \"muted-foreground\": \"oklch(0.556 0 0)\",\n accent: \"oklch(0.97 0 0)\",\n \"accent-foreground\": \"oklch(0.205 0 0)\",\n border: \"oklch(0.922 0 0)\",\n input: \"oklch(0.922 0 0)\",\n ring: \"oklch(0.708 0 0)\",\n \"chart-1\": \"oklch(0.646 0.222 41.116)\",\n \"chart-2\": \"oklch(0.6 0.118 184.704)\",\n \"chart-3\": \"oklch(0.398 0.07 227.392)\",\n \"chart-4\": \"oklch(0.828 0.189 84.429)\",\n \"chart-5\": \"oklch(0.769 0.188 70.08)\",\n sidebar: \"oklch(0.985 0 0)\",\n \"sidebar-foreground\": \"oklch(0.145 0 0)\",\n \"sidebar-primary\": \"oklch(0.205 0 0)\",\n \"sidebar-primary-foreground\": \"oklch(0.985 0 0)\",\n \"sidebar-accent\": \"oklch(0.97 0 0)\",\n \"sidebar-accent-foreground\": \"oklch(0.205 0 0)\",\n \"sidebar-border\": \"oklch(0.922 0 0)\",\n \"sidebar-ring\": \"oklch(0.708 0 0)\",\n\n primary: \"oklch(70% 0.1435 227.76)\",\n \"primary-foreground\": \"oklch(0.985 0 0)\",\n secondary: \"oklch(0.97 0 0)\",\n \"secondary-foreground\": \"oklch(0.205 0 0)\",\n danger: \"oklch(0.577 0.245 27.325)\",\n \"danger-foreground\": \"oklch(0.985 0 0)\",\n success: \"oklch(0.728 0.125 139.6)\",\n \"success-foreground\": \"oklch(0.985 0 0)\",\n warning: \"oklch(0.784 0.181 44.7)\",\n \"warning-foreground\": \"oklch(0.985 0 0)\",\n inverted: \"oklch(0.205 0 0)\",\n \"inverted-foreground\": \"oklch(0.97 0 0)\",\n\n focus: \"oklch(0.7 0.181 44.7)\",\n \"focus-size\": \"2.5px\",\n \"focus-offset\": \"2px\",\n\n table: \"oklch(0.94 0 0 / 65%)\",\n \"table-content\": \"oklch(1 0 0)\",\n \"table-hover\": \"oklch(0.98 0 0 / 10%)\",\n },\n dark: {\n background: \"oklch(0.145 0 0)\",\n \"scrollbar-thumb\": \"oklch(0.269 0 0)\",\n foreground: \"oklch(0.985 0 0)\",\n card: \"oklch(0.205 0 0)\",\n \"card-foreground\": \"oklch(0.985 0 0)\",\n popover: \"oklch(0.205 0 0)\",\n \"popover-foreground\": \"oklch(0.985 0 0)\",\n secondary: \"oklch(0.269 0 0)\",\n \"secondary-foreground\": \"oklch(0.985 0 0)\",\n muted: \"oklch(0.269 0 0)\",\n \"muted-foreground\": \"oklch(0.708 0 0)\",\n accent: \"oklch(0.269 0 0)\",\n \"accent-foreground\": \"oklch(0.985 0 0)\",\n border: \"oklch(1 0 0 / 10%)\",\n input: \"oklch(1 0 0 / 15%)\",\n ring: \"oklch(0.556 0 0)\",\n \"chart-1\": \"oklch(0.488 0.243 264.376)\",\n \"chart-2\": \"oklch(0.696 0.17 162.48)\",\n \"chart-3\": \"oklch(0.769 0.188 70.08)\",\n \"chart-4\": \"oklch(0.627 0.265 303.9)\",\n \"chart-5\": \"oklch(0.645 0.246 16.439)\",\n sidebar: \"oklch(0.205 0 0)\",\n \"sidebar-foreground\": \"oklch(0.985 0 0)\",\n \"sidebar-primary\": \"oklch(0.488 0.243 264.376)\",\n \"sidebar-primary-foreground\": \"oklch(0.985 0 0)\",\n \"sidebar-accent\": \"oklch(0.269 0 0)\",\n \"sidebar-accent-foreground\": \"oklch(0.985 0 0)\",\n \"sidebar-border\": \"oklch(1 0 0 / 10%)\",\n \"sidebar-ring\": \"oklch(0.556 0 0)\",\n\n primary: \"oklch(66% 0.1435 227.76)\",\n \"primary-foreground\": \"oklch(0.985 0 0)\",\n danger: \"oklch(0.704 0.191 22.216)\",\n \"danger-foreground\": \"oklch(0.985 0 0)\",\n success: \"oklch(0.728 0.125 139.6)\",\n \"success-foreground\": \"oklch(0.985 0 0)\",\n warning: \"oklch(0.784 0.181 44.7)\",\n \"warning-foreground\": \"oklch(0.985 0 0)\",\n inverted: \"oklch(0.922 0 0)\",\n \"inverted-foreground\": \"oklch(0.205 0 0)\",\n\n focus: \"oklch(0.7 0.181 44.7)\",\n\n table: \"oklch(0.265 0 0)\",\n \"table-content\": \"oklch(0.205 0 0)\",\n \"table-hover\": \"oklch(0.22 0 0)\",\n },\n} satisfies ThemeTokens\n","import postcss, {\n type AtRule,\n type Container,\n type Root,\n type Rule,\n} from \"postcss\"\n\n// Regras de CSS que os itens trazem além das variáveis do tema:\n//\n// - `utilities` e `variants`: `@utility <nome>` e `@custom-variant <nome>`,\n// com o texto completo da regra, no `utilities.css`. O merge é pelo nome.\n// - `base`: declarações em seletores de elemento (`body`, `html`, `*`…),\n// dentro do `@layer base` do `base.css`. O merge é por seletor e\n// propriedade.\n//\n// As regras de merge são as mesmas das variáveis: o que falta é adicionado, o\n// que o usuário mudou fica, e no update o que não foi mexido acompanha a\n// versão nova.\nexport type CssRules = {\n utilities?: Record<string, string>\n variants?: Record<string, string>\n base?: Record<string, Record<string, string>>\n}\n\nexport type CssRuleKind = \"utility\" | \"variant\" | \"base\"\n\nexport type CssRuleChange = {\n kind: CssRuleKind\n // Nome da utility ou da variante; na base, `<seletor> { <propriedade> }`.\n name: string\n action: \"added\" | \"updated\" | \"kept\" | \"removed\" | \"unchanged\"\n}\n\nexport type CssRulesResult = {\n css: string\n changes: CssRuleChange[]\n warnings: string[]\n}\n\nexport type ApplyCssRulesOptions = {\n // Regras da versão instalada (no update); ausente no add.\n base?: CssRules\n overwrite?: boolean\n // Regra removida na versão nova: remover? Ausente = manter.\n shouldRemove?: (kind: CssRuleKind, name: string) => Promise<boolean>\n}\n\nconst AT_RULE = { utility: \"utility\", variant: \"custom-variant\" } as const\n\n// Nome de uma `@utility`/`@custom-variant` pelo começo dos parâmetros\n// (`no-scrollbar`, `fixed (&:is(.layout-fixed *))`).\nexport function ruleName(rule: AtRule): string {\n return rule.params.trim().split(/[\\s({]/)[0] ?? \"\"\n}\n\n// As `@utility` e `@custom-variant` de um CSS, pelo nome, com o texto de cada\n// uma. A variante `dark` fica de fora: é do tema, e o CSS global cuida dela.\nexport function readCssRules(\n css: string,\n): Required<Pick<CssRules, \"utilities\" | \"variants\">> {\n const root = postcss.parse(css)\n const utilities: Record<string, string> = {}\n const variants: Record<string, string> = {}\n root.each((node) => {\n if (node.type !== \"atrule\") {\n return\n }\n const name = ruleName(node)\n if (node.name === AT_RULE.utility) {\n utilities[name] = ruleSource(node)\n } else if (node.name === AT_RULE.variant && name !== \"dark\") {\n variants[name] = ruleSource(node)\n }\n })\n return { utilities, variants }\n}\n\n// Aplica as `@utility` e `@custom-variant` de um item, com merge pelo nome.\nexport async function applyCssRules(\n css: string,\n remote: Pick<CssRules, \"utilities\" | \"variants\">,\n options: ApplyCssRulesOptions = {},\n): Promise<CssRulesResult> {\n const root = postcss.parse(css)\n const changes: CssRuleChange[] = []\n const warnings: string[] = []\n\n for (const kind of [\"variant\", \"utility\"] as const) {\n const field = kind === \"utility\" ? \"utilities\" : \"variants\"\n const remoteRules = remote[field] ?? {}\n const baseRules = options.base?.[field] ?? {}\n const names = new Set([\n ...Object.keys(remoteRules),\n ...Object.keys(baseRules),\n ])\n\n for (const name of names) {\n const remoteSource = remoteRules[name]\n const baseSource = baseRules[name]\n const local = findRule(root, kind, name)\n const label = `${field === \"utilities\" ? \"@utility\" : \"@custom-variant\"} ${name}`\n\n const result = await merge({\n local: local && ruleSource(local),\n remote: remoteSource,\n base: baseSource,\n options,\n kind,\n name,\n label,\n warnings,\n add: (source) => appendRule(root, kind, source),\n replace: (source) => {\n const next = parseRule(source)\n next.raws.before = local?.raws.before ?? \"\"\n local?.replaceWith(next)\n },\n remove: () => local?.remove(),\n })\n if (result) {\n changes.push({ kind, name, action: result })\n }\n }\n }\n\n return { css: root.toString(), changes, warnings }\n}\n\n// Aplica as declarações de base de um item no `@layer base`, com merge por\n// seletor e propriedade.\nexport async function applyBaseRules(\n css: string,\n remote: CssRules[\"base\"] = {},\n options: ApplyCssRulesOptions = {},\n): Promise<CssRulesResult> {\n const root = postcss.parse(css)\n const changes: CssRuleChange[] = []\n const warnings: string[] = []\n const previous = options.base?.base ?? {}\n\n const selectors = new Set([...Object.keys(remote), ...Object.keys(previous)])\n for (const selector of selectors) {\n const remoteDecls = remote[selector] ?? {}\n const baseDecls = previous[selector] ?? {}\n const props = new Set([\n ...Object.keys(remoteDecls),\n ...Object.keys(baseDecls),\n ])\n\n for (const prop of props) {\n const layer = findBaseLayer(root)\n let rule = layer && findRuleBySelector(layer, selector)\n const declaration = rule?.nodes.find(\n (node) => node.type === \"decl\" && node.prop === prop,\n ) as postcss.Declaration | undefined\n const name = `${selector} { ${prop} }`\n\n const result = await merge({\n local: declaration?.value,\n remote: remoteDecls[prop],\n base: baseDecls[prop],\n options,\n kind: \"base\",\n name,\n label: `${prop} in ${selector}`,\n warnings,\n add: (value) => {\n rule ??= appendBaseRule(root, selector)\n rule.append(postcss.decl({ prop, value, raws: { before: \"\\n \" } }))\n },\n replace: (value) => {\n if (declaration) {\n declaration.value = value\n }\n },\n remove: () => {\n declaration?.remove()\n if (rule?.nodes.length === 0) {\n rule.remove()\n }\n },\n })\n if (result) {\n changes.push({ kind: \"base\", name, action: result })\n }\n }\n }\n\n return { css: root.toString(), changes, warnings }\n}\n\n// Mesmas regras do merge das variáveis (`applyCssVars`).\nasync function merge({\n local,\n remote,\n base,\n options,\n kind,\n name,\n label,\n warnings,\n add,\n replace,\n remove,\n}: {\n local: string | undefined\n remote: string | undefined\n base: string | undefined\n options: ApplyCssRulesOptions\n kind: CssRuleKind\n name: string\n label: string\n warnings: string[]\n add: (value: string) => void\n replace: (value: string) => void\n remove: () => void\n}): Promise<CssRuleChange[\"action\"] | undefined> {\n if (remote === undefined) {\n // Removida na versão nova.\n if (local === undefined) {\n return undefined\n }\n if (options.shouldRemove && (await options.shouldRemove(kind, name))) {\n remove()\n return \"removed\"\n }\n warnings.push(`${label} was removed in the new version; kept in the CSS.`)\n return \"kept\"\n }\n\n if (local === undefined) {\n if (base !== undefined) {\n // Apagada pelo usuário: não recria.\n return \"kept\"\n }\n add(remote)\n return \"added\"\n }\n\n if (same(local, remote)) {\n return \"unchanged\"\n }\n if (options.overwrite || (base !== undefined && same(local, base))) {\n replace(remote)\n return \"updated\"\n }\n warnings.push(`${label} was changed in the CSS; kept instead of the new one.`)\n return \"kept\"\n}\n\nfunction findRule(\n root: Root,\n kind: \"utility\" | \"variant\",\n name: string,\n): AtRule | undefined {\n return root.nodes.find(\n (node): node is AtRule =>\n node.type === \"atrule\" &&\n node.name === AT_RULE[kind] &&\n ruleName(node) === name,\n )\n}\n\n// Variantes antes das utilities: uma utility pode usar uma variante.\nfunction appendRule(root: Root, kind: \"utility\" | \"variant\", source: string) {\n const rule = parseRule(source)\n const lastVariant = root.nodes.findLast(\n (node) => node.type === \"atrule\" && node.name === AT_RULE.variant,\n )\n if (kind === \"variant\") {\n const firstUtility = root.nodes.find(\n (node) => node.type === \"atrule\" && node.name === AT_RULE.utility,\n )\n if (lastVariant) {\n rule.raws.before = \"\\n\"\n lastVariant.after(rule)\n return\n }\n if (firstUtility) {\n rule.raws.before = firstUtility.raws.before ?? \"\"\n firstUtility.raws.before = \"\\n\\n\"\n firstUtility.before(rule)\n return\n }\n }\n rule.raws.before = root.nodes.length > 0 ? \"\\n\\n\" : \"\"\n root.append(rule)\n root.raws.after = \"\\n\"\n}\n\nfunction parseRule(source: string): AtRule {\n const node = postcss.parse(source.trim()).first\n if (node?.type !== \"atrule\") {\n throw new Error(`Not a CSS at-rule: ${source}`)\n }\n return node\n}\n\n// Texto da regra sem os espaços de antes (é o que vai para o item publicado).\nfunction ruleSource(rule: AtRule): string {\n const clone = rule.clone()\n clone.raws.before = \"\"\n // Sem bloco (`@custom-variant x (…);`), o `;` é do pai: vai junto.\n return clone.nodes === undefined ? `${clone.toString()};` : clone.toString()\n}\n\nfunction findBaseLayer(root: Root): Container | undefined {\n return root.nodes.find(\n (node) =>\n node.type === \"atrule\" &&\n node.name === \"layer\" &&\n node.params.trim() === \"base\",\n ) as Container | undefined\n}\n\nfunction findRuleBySelector(\n layer: Container,\n selector: string,\n): Rule | undefined {\n return layer.nodes?.find(\n (node): node is Rule =>\n node.type === \"rule\" &&\n normalizeSelector(node.selector) === normalizeSelector(selector),\n )\n}\n\nfunction appendBaseRule(root: Root, selector: string): Rule {\n let layer = findBaseLayer(root)\n if (layer === undefined) {\n layer = postcss.atRule({ name: \"layer\", params: \"base\" })\n layer.raws = {\n before: root.nodes.length > 0 ? \"\\n\\n\" : \"\",\n between: \" \",\n after: \"\\n\",\n }\n root.append(layer)\n root.raws.after = \"\\n\"\n }\n const rule = postcss.rule({ selector })\n rule.raws = {\n before: (layer.nodes?.length ?? 0) > 0 ? \"\\n\\n \" : \"\\n \",\n between: \" \",\n after: \"\\n \",\n semicolon: true,\n }\n layer.append(rule)\n layer.raws.after = \"\\n\"\n return rule\n}\n\n// Compara seletores sem os espaços (`a > b` = `a>b`) e sem as aspas.\nconst normalizeSelector = (selector: string) => selector.replace(/[\"'\\s]/g, \"\")\n\nfunction same(a: string, b: string) {\n const normalize = (value: string) =>\n value\n .replace(/\\s+/g, \" \")\n .replace(/\\s*([{};:,])\\s*/g, \"$1\")\n .replace(/;}/g, \"}\")\n .replace(/;$/, \"\")\n .trim()\n return normalize(a) === normalize(b)\n}\n","import type { ThemeGroup, ThemeTokens } from \"./types\"\n\nimport { defaultTheme } from \"./default-theme\"\n\nexport type ValueKind = \"color\" | \"length\" | \"number\" | \"keyword\" | \"expression\"\n\nexport type ThemeIssue = {\n group: ThemeGroup\n name: string\n value: string\n message: string\n}\n\nexport class ThemeValidationError extends Error {\n constructor(readonly issues: ThemeIssue[]) {\n super(\n `Invalid theme:\\n${issues\n .map(({ group, name, message }) => ` --${name} (${group}): ${message}`)\n .join(\"\\n\")}`,\n )\n this.name = \"ThemeValidationError\"\n }\n}\n\nconst MAX_LENGTH = 200\n\nconst NAME = /^[\\w-]+$/\n// Só o que um valor de tema usa: sem `;`, `{}`, aspas, `\\`, `@`, `!` ou `:`,\n// que permitiriam fechar o bloco ou injetar outra regra.\nconst SAFE_CHARS = /^[\\w\\s.,%#()+\\-*/]+$/\n\nconst COLOR_FUNCTIONS = new Set([\n \"rgb\",\n \"rgba\",\n \"hsl\",\n \"hsla\",\n \"hwb\",\n \"lab\",\n \"lch\",\n \"oklab\",\n \"oklch\",\n \"color\",\n \"color-mix\",\n])\nconst MATH_FUNCTIONS = new Set([\"calc\", \"min\", \"max\", \"clamp\", \"var\"])\n\nconst HEX = /^#(?:[\\da-f]{3,4}|[\\da-f]{6}|[\\da-f]{8})$/i\nconst NUMBER = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)$/\nconst LENGTH =\n /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:px|rem|em|%|ch|ex|lh|rlh|vw|vh|vmin|vmax|svh|lvh|dvh|cqw|cqh|pt|pc|in|cm|mm|q|deg|rad|turn|ms|s)$/i\nconst KEYWORD = /^[a-z][a-z-]*$/i\nconst FUNCTION = /^([a-z-]+)\\(/i\n\n// O valor só usa caracteres e funções conhecidos, com parênteses balanceados.\nexport function isSafeValue(value: string): boolean {\n if (value.trim() === \"\" || value.length > MAX_LENGTH) {\n return false\n }\n if (!SAFE_CHARS.test(value)) {\n return false\n }\n let depth = 0\n for (const char of value) {\n depth += char === \"(\" ? 1 : char === \")\" ? -1 : 0\n if (depth < 0) {\n return false\n }\n }\n if (depth !== 0) {\n return false\n }\n for (const [, name] of value.matchAll(/([a-z-]*)\\(/gi)) {\n // Sem nome, é só um agrupamento: `calc((a + b) * 2)`.\n const fn = name.toLowerCase()\n if (fn !== \"\" && !COLOR_FUNCTIONS.has(fn) && !MATH_FUNCTIONS.has(fn)) {\n return false\n }\n }\n return true\n}\n\n// Tipo do valor, para conferir com o do tema padrão. `calc()` e `var()` são\n// \"expression\": aceitos no lugar de qualquer tipo.\nexport function getValueKind(value: string): ValueKind {\n const trimmed = value.trim()\n if (HEX.test(trimmed)) {\n return \"color\"\n }\n if (NUMBER.test(trimmed)) {\n return \"number\"\n }\n if (LENGTH.test(trimmed)) {\n return \"length\"\n }\n if (KEYWORD.test(trimmed)) {\n return \"keyword\"\n }\n const fn = trimmed.match(FUNCTION)?.[1]?.toLowerCase()\n if (fn && COLOR_FUNCTIONS.has(fn)) {\n return \"color\"\n }\n return \"expression\"\n}\n\nfunction accepts(expected: ValueKind, actual: ValueKind) {\n if (actual === expected || actual === \"expression\" || actual === \"keyword\") {\n return true\n }\n // `0` sem unidade vale como tamanho.\n return expected === \"length\" && actual === \"number\"\n}\n\nexport type ValidateThemeOptions = {\n // Tema que define o tipo de cada token (padrão: `defaultTheme`).\n reference?: ThemeTokens\n}\n\n// Confere nomes e valores antes de gravar ou injetar o tema. Tokens fora da\n// referência só passam pela checagem de segurança.\nexport function validateTheme(\n tokens: ThemeTokens,\n { reference = defaultTheme }: ValidateThemeOptions = {},\n): ThemeIssue[] {\n const issues: ThemeIssue[] = []\n\n for (const group of [\"theme\", \"light\", \"dark\"] as const) {\n for (const [name, value] of Object.entries(tokens[group] ?? {})) {\n const issue = (message: string) =>\n issues.push({ group, name, value, message })\n\n if (!NAME.test(name)) {\n issue(\"invalid variable name\")\n continue\n }\n if (typeof value !== \"string\" || !isSafeValue(value)) {\n issue(\"unsafe or malformed value\")\n continue\n }\n const expected =\n reference[group]?.[name] ??\n reference.light?.[name] ??\n reference.dark?.[name]\n if (expected === undefined) {\n continue\n }\n const expectedKind = getValueKind(expected)\n const actualKind = getValueKind(value)\n if (expectedKind !== \"expression\" && !accepts(expectedKind, actualKind)) {\n issue(`expected a ${expectedKind}, got a ${actualKind}`)\n }\n }\n }\n\n return issues\n}\n","import postcss from \"postcss\"\n\nimport type { ThemeGroup, ThemeTokens, ThemeVars } from \"./types\"\n\nimport {\n type ApplyCssVarsOptions,\n applyCssVars,\n type CssVarsResult,\n findBlock,\n withColorMappings,\n} from \"./css\"\nimport {\n ThemeValidationError,\n type ValidateThemeOptions,\n validateTheme,\n} from \"./validate\"\n\nconst GROUPS: ThemeGroup[] = [\"theme\", \"light\", \"dark\"]\n\nexport type ThemeFileOptions = {\n // Nome do tema, para ler e gravar o arquivo dele (`styles/themes/<nome>.css`)\n // com os blocos `:root[data-slabui-theme=\"<nome>\"]` e `.dark`.\n theme?: string\n}\n\n// Lê o tema do CSS global (`@theme inline`, `:root` e `.dark`), ou de um\n// arquivo de tema com `theme`. Os `--color-<nome>: var(--<nome>)` gerados das\n// cores ficam de fora, como no `defaultTheme`; um mapeamento com outro valor é\n// mantido.\nexport function readTheme(\n css: string,\n { theme }: ThemeFileOptions = {},\n): ThemeTokens {\n const root = postcss.parse(css)\n const tokens: ThemeTokens = {}\n\n for (const group of GROUPS) {\n const vars: ThemeVars = {}\n findBlock(root, group, theme)?.each((node) => {\n if (node.type === \"decl\" && node.prop.startsWith(\"--\")) {\n vars[node.prop.slice(2)] = node.value\n }\n })\n if (Object.keys(vars).length > 0) {\n tokens[group] = vars\n }\n }\n\n if (tokens.theme) {\n const { theme: derived = {} } = withColorMappings({\n light: tokens.light,\n dark: tokens.dark,\n })\n for (const [name, value] of Object.entries(derived)) {\n if (tokens.theme[name] === value) {\n delete tokens.theme[name]\n }\n }\n if (Object.keys(tokens.theme).length === 0) {\n delete tokens.theme\n }\n }\n\n return tokens\n}\n\n// Grava os tokens no CSS global, com merge por variável: só as variáveis\n// passadas mudam, e o resto do arquivo fica como está. Diferente do `add` do\n// registry, o valor do tema substitui o do arquivo. Tokens inválidos\n// interrompem a gravação com `ThemeValidationError`.\nexport async function writeTheme(\n css: string,\n tokens: ThemeTokens,\n {\n reference,\n ...options\n }: Omit<ApplyCssVarsOptions, \"overwrite\"> & ValidateThemeOptions = {},\n): Promise<CssVarsResult> {\n const issues = validateTheme(tokens, { reference })\n if (issues.length > 0) {\n throw new ThemeValidationError(issues)\n }\n return applyCssVars(css, tokens, { ...options, overwrite: true })\n}\n","import type { ThemeTokens } from \"./types\"\n\n// Utilitários de cor do Tailwind: `bg-primary`, `text-muted-foreground`,\n// `dark:border-input/50`, `ring-offset-background`…\nconst COLOR_UTILITY =\n /(?<![\\w-])(?:bg|text|border(?:-[xytrblse])?|ring(?:-offset)?|inset-ring|outline|fill|stroke|from|via|to|decoration|divide|accent|caret|placeholder|shadow|inset-shadow)-([a-z][a-z0-9-]*)(?=[/\\s\"'`\\]);,}!]|$)/g\n\n// `rounded`, `rounded-md`, `rounded-tl-xl`… (sem `none`, `full` e valores\n// arbitrários).\nconst RADIUS_UTILITY =\n /(?<![\\w-])rounded(?:-[trblse]{1,2})?(?:-(?:xs|sm|md|lg|xl|2xl|3xl|4xl))?(?![\\w[-])/\n\n// Escala de espaçamento: `p-4`, `-mt-2`, `gap-x-1.5`, `size-9`, `h-0.5`…\nconst SPACING_UTILITY =\n /(?<![\\w-])-?(?:p[xytrblse]?|m[xytrblse]?|gap(?:-[xy])?|space-[xy]|size|[wh]|min-[wh]|max-[wh]|inset(?:-[xy])?|top|right|bottom|left|start|end|translate-[xy]|scroll-[mp][xytrblse]?|indent|basis)-\\d+(?:\\.\\d+)?(?![\\w.-])/\n\nconst SPACING_FUNCTION = /--spacing\\(/\nconst CSS_VAR = /var\\(--([\\w-]+)/g\n\nexport type TokenCatalog = {\n // Variáveis do tema (`:root`/`.dark`) e as dos próprios itens.\n vars: Set<string>\n // Nome usado nas classes → variável (`destructive` → `danger`, pelo\n // `--color-destructive: var(--danger)` do `@theme inline`).\n colors: Map<string, string>\n}\n\n// Catálogo a partir do tema do CSS global do autor e das `cssVars` dos itens.\nexport function tokenCatalog(\n theme: ThemeTokens,\n itemVars: ThemeTokens[] = [],\n): TokenCatalog {\n const vars = new Set<string>()\n for (const tokens of [theme, ...itemVars]) {\n for (const group of [tokens.light, tokens.dark]) {\n for (const name of Object.keys(group ?? {})) {\n vars.add(name)\n }\n }\n }\n const colors = new Map<string, string>()\n for (const name of vars) {\n colors.set(name, name)\n }\n for (const tokens of [theme, ...itemVars]) {\n for (const [name, value] of Object.entries(tokens.theme ?? {})) {\n const target = value.match(/^var\\(--([\\w-]+)\\)$/)?.[1]\n if (name.startsWith(\"color-\") && target && vars.has(target)) {\n colors.set(name.slice(\"color-\".length), target)\n }\n }\n }\n return { vars, colors }\n}\n\n// Variáveis do tema que os arquivos de um item usam, em ordem alfabética.\nexport function findTokens(\n contents: string[],\n catalog: TokenCatalog,\n): string[] {\n const found = new Set<string>()\n for (const content of contents) {\n for (const [, name] of content.matchAll(COLOR_UTILITY)) {\n const token = catalog.colors.get(name as string)\n if (token) {\n found.add(token)\n }\n }\n for (const [, name] of content.matchAll(CSS_VAR)) {\n if (catalog.vars.has(name as string)) {\n found.add(name as string)\n }\n }\n if (catalog.vars.has(\"radius\") && RADIUS_UTILITY.test(content)) {\n found.add(\"radius\")\n }\n if (\n catalog.vars.has(\"spacing\") &&\n (SPACING_UTILITY.test(content) || SPACING_FUNCTION.test(content))\n ) {\n found.add(\"spacing\")\n }\n }\n return [...found].sort()\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import{THEME_ATTRIBUTE as e,isThemeName as t,themeSelector as n}from"./attribute.mjs";import r from"postcss";const i=/^\s*(oklch|oklab|lch|lab|hsla?|rgba?|hwb|color)\(|^\s*#[0-9a-f]{3,8}\s*$/i;async function a(e,t,{base:n,overwrite:i=!1,shouldRemove:a,theme:s}={}){let c=r.parse(e),p=[],m=[],h=e=>s?e:o(e),g=h(t),_=n?h(n):void 0;for(let e of[`theme`,`light`,`dark`]){let t=g[e]??{},n=_?.[e]??{},o=/* @__PURE__ */ new Set([...Object.keys(t),...Object.keys(n)]);if(o.size===0)continue;let d=l(c,e,s);for(let l of o){let o=t[l],h=n[l],g=d?.nodes?.find(e=>e.type===`decl`&&e.prop===`--${l}`),_=g?.value,v=t=>p.push({group:e,name:l,action:t});if(o===void 0){if(_===void 0)continue;a&&await a(e,l)?(g?.remove(),v(`removed`)):(m.push(`--${l} (${e}) was removed in the new version; kept in the CSS.`),v(`kept`))}else if(_===void 0){if(h!==void 0){v(`kept`);continue}d??=u(c,e,s),d.raws.semicolon=!0,d.raws.after=`
|
|
2
|
+
`,d.append(r.decl({prop:`--${l}`,value:o,raws:{before:`
|
|
3
|
+
`}})),v(`added`)}else f(_,o)?v(`unchanged`):i||h!==void 0&&f(_,h)?(g.value=o,v(`updated`)):(m.push(`--${l} (${e}) has a custom value in the CSS (${_}); kept instead of ${o}.`),v(`kept`))}}return!s&&Object.keys(g.dark??{}).length>0&&d(c),{css:c.toString(),changes:p,warnings:m}}function o(e){let t={...e.theme};for(let n of[e.light,e.dark])for(let[e,r]of Object.entries(n??{}))i.test(r)&&t[`color-${e}`]===void 0&&(t[`color-${e}`]=`var(--${e})`);return{...e,...Object.keys(t).length>0&&{theme:t}}}function s(e,t){return t?n(t,e===`dark`):e===`light`?`:root`:`.dark`}const c=e=>e.replace(/["'\s]/g,``);function l(e,t,n){return e.nodes.find(e=>t===`theme`?e.type===`atrule`&&e.name===`theme`&&e.params.trim()===`inline`:e.type===`rule`&&c(e.selector)===c(s(t,n)))}function u(e,t,n){let i=t===`theme`?r.atRule({name:`theme`,params:`inline`}):r.rule({selector:s(t,n)});return i.raws={before:e.nodes.length>0?`
|
|
4
|
+
|
|
5
|
+
`:``,between:` `,after:`
|
|
6
|
+
`,semicolon:!0},e.append(i),i}function d(e){if(e.nodes.some(e=>e.type===`atrule`&&e.name===`custom-variant`&&e.params.trim().startsWith(`dark`)))return;let t=r.atRule({name:`custom-variant`,params:`dark (&:is(.dark *))`}),n=e.nodes.filter(e=>e.type===`atrule`&&e.name===`import`).at(-1);n?(t.raws={before:`
|
|
7
|
+
|
|
8
|
+
`},n.after(t)):(t.raws={before:``},e.prepend(t))}function f(e,t){return e.replace(/\s+/g,` `).trim()===t.replace(/\s+/g,` `).trim()}const p=/^[\w-]+$/;function m(e,t,{theme:n}={}){let i=r.parse(e);for(let e of[`light`,`dark`]){let r=new Set((t[e]??[]).filter(e=>p.test(e)));r.size!==0&&l(i,e,n)?.each(e=>{e.type===`decl`&&r.has(e.prop.slice(2))&&e.remove()})}return i.toString()}function h(t){return`/* Tema "${t}": só o que muda em relação ao CSS global. Aplicado com
|
|
9
|
+
<html ${e}="${t}"> ou SLABUI_THEME=${t}. */
|
|
10
|
+
`}function g(n,i,a){if(!t(i)||!t(a))throw Error(`Invalid theme name: "${i}" → "${a}"`);let o=RegExp(`\\[${e}\\s*=\\s*(["']?)${i}\\1\\s*\\]`,`g`),s=r.parse(n);return s.walkRules(t=>{t.selector=t.selector.replace(o,`[${e}="${a}"]`)}),s.walkComments(e=>{e.text=e.text.replaceAll(`"${i}"`,`"${a}"`).replaceAll(`SLABUI_THEME=${i}`,`SLABUI_THEME=${a}`)}),s.toString()}function _(e){return e.params.trim().replace(/^url\((.*)\)/,`$1`).split(/\s/)[0]?.replace(/^["']|["']$/g,``)}const v=(e,t)=>e!==void 0&&e.replace(/^\.\//,``)===t.replace(/^\.\//,``);function y(e){return e.nodes.filter(e=>e.type===`atrule`&&e.name===`import`)}function b(e){return y(r.parse(e)).map(_).filter(e=>e?.startsWith(`./`)===!0||e?.startsWith(`../`)===!0)}function x(e,t){return S(e,t)}function S(e,t){let n=r.parse(e),i=y(n);if(i.some(e=>v(_(e),t)))return e;let a=r.atRule({name:`import`,params:`"${t}"`}),o=i.at(-1);return o?(a.raws={before:`
|
|
11
|
+
`},o.after(a)):(a.raws={before:``},n.prepend(a)),n.toString()}function C(e,t){let n=r.parse(e);for(let e of y(n))v(_(e),t)&&e.remove();return n.toString()}function w(e,t,n){let i=r.parse(e);for(let e of y(i))v(_(e),t)&&(e.params=`"${n}"`);return i.toString()}export{m as a,h as c,o as d,C as i,a as l,x as n,w as o,b as r,g as s,S as t,l as u};
|
|
12
|
+
//# sourceMappingURL=theme-files-a8APQNco.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-files-a8APQNco.mjs","names":["postcss","COLOR","applyCssVars","root","css","changes","warnings","mappings","theme","vars","withColorMappings","wanted","remote","previous","base","group","remoteVars","baseVars","names","block","findBlock","name","remoteValue","baseValue","declaration","node","local","record","shouldRemove","createBlock","same","overwrite","ensureDarkVariant","value","blockSelector","themeSelector","normalize","selector","variant","last","a","b","VAR_NAME","removeTokens","unset","themeFileHeader","THEME_ATTRIBUTE","renameThemeSelectors","isThemeName","from","to","pattern","rule","comment","importPath","sameImport","imports","localImports","target","addThemeImport","addImport","path","existing","removeThemeImport","renameThemeImport"],"sources":["../src/css.ts","../src/theme-files.ts"],"sourcesContent":["import postcss, {\n type AtRule,\n type Container,\n type Root,\n type Rule,\n} from \"postcss\"\n\nimport type { ThemeGroup, ThemeTokens } from \"./types\"\n\nimport { themeSelector } from \"./attribute\"\n\nexport type CssVarChange = {\n group: ThemeGroup\n name: string\n action: \"added\" | \"updated\" | \"kept\" | \"removed\" | \"unchanged\"\n}\n\nexport type CssVarsResult = {\n css: string\n changes: CssVarChange[]\n warnings: string[]\n}\n\nexport type ApplyCssVarsOptions = {\n // Variáveis da versão instalada (no update); ausente no add.\n base?: ThemeTokens\n overwrite?: boolean\n // Variável removida na versão nova: remover? Ausente = manter.\n shouldRemove?: (group: ThemeGroup, name: string) => Promise<boolean>\n // Arquivo de um tema (`styles/themes/<nome>.css`): os blocos são\n // `:root[data-slabui-theme=\"<nome>\"]` (e `.dark`) no lugar de `:root`/`.dark`.\n theme?: string\n}\n\nconst COLOR =\n /^\\s*(oklch|oklab|lch|lab|hsla?|rgba?|hwb|color)\\(|^\\s*#[0-9a-f]{3,8}\\s*$/i\n\n// Aplica as variáveis de um item no CSS global, com merge por variável.\nexport async function applyCssVars(\n css: string,\n remote: ThemeTokens,\n { base, overwrite = false, shouldRemove, theme }: ApplyCssVarsOptions = {},\n): Promise<CssVarsResult> {\n const root = postcss.parse(css)\n const changes: CssVarChange[] = []\n const warnings: string[] = []\n // Num arquivo de tema, os `--color-*` já estão no `@theme inline` do CSS\n // global; uma cor nova do tema declara o dela no próprio arquivo.\n const mappings = (vars: ThemeTokens) =>\n theme ? vars : withColorMappings(vars)\n const wanted = mappings(remote)\n const previous = base ? mappings(base) : undefined\n\n for (const group of [\"theme\", \"light\", \"dark\"] as const) {\n const remoteVars = wanted[group] ?? {}\n const baseVars = previous?.[group] ?? {}\n const names = new Set([\n ...Object.keys(remoteVars),\n ...Object.keys(baseVars),\n ])\n if (names.size === 0) {\n continue\n }\n let block = findBlock(root, group, theme)\n\n for (const name of names) {\n const remoteValue = remoteVars[name]\n const baseValue = baseVars[name]\n const declaration = block?.nodes?.find(\n (node) => node.type === \"decl\" && node.prop === `--${name}`,\n ) as postcss.Declaration | undefined\n const local = declaration?.value\n const record = (action: CssVarChange[\"action\"]) =>\n changes.push({ group, name, action })\n\n if (remoteValue === undefined) {\n // Removida na versão nova.\n if (local === undefined) {\n continue\n }\n if (shouldRemove && (await shouldRemove(group, name))) {\n declaration?.remove()\n record(\"removed\")\n } else {\n warnings.push(\n `--${name} (${group}) was removed in the new version; kept in the CSS.`,\n )\n record(\"kept\")\n }\n continue\n }\n\n if (local === undefined) {\n if (baseValue !== undefined) {\n // Apagada do CSS pelo usuário: não recria.\n record(\"kept\")\n continue\n }\n block ??= createBlock(root, group, theme)\n block.raws.semicolon = true\n block.raws.after = \"\\n\"\n block.append(\n postcss.decl({\n prop: `--${name}`,\n value: remoteValue,\n raws: { before: \"\\n \" },\n }),\n )\n record(\"added\")\n continue\n }\n\n if (same(local, remoteValue)) {\n record(\"unchanged\")\n } else if (\n overwrite ||\n (baseValue !== undefined && same(local, baseValue))\n ) {\n ;(declaration as postcss.Declaration).value = remoteValue\n record(\"updated\")\n } else {\n warnings.push(\n `--${name} (${group}) has a custom value in the CSS (${local}); kept instead of ${remoteValue}.`,\n )\n record(\"kept\")\n }\n }\n }\n\n // O arquivo de um tema é importado pelo CSS global, que já tem a variante.\n if (!theme && Object.keys(wanted.dark ?? {}).length > 0) {\n ensureDarkVariant(root)\n }\n\n return { css: root.toString(), changes, warnings }\n}\n\n// Cada cor de light/dark ganha `--color-<nome>: var(--<nome>)` no `theme`,\n// para o Tailwind 4 gerar as utilidades (`bg-<nome>`) e aceitar o `@apply`.\nexport function withColorMappings(vars: ThemeTokens): ThemeTokens {\n const theme = { ...vars.theme }\n for (const group of [vars.light, vars.dark]) {\n for (const [name, value] of Object.entries(group ?? {})) {\n if (COLOR.test(value) && theme[`color-${name}`] === undefined) {\n theme[`color-${name}`] = `var(--${name})`\n }\n }\n }\n return {\n ...vars,\n ...(Object.keys(theme).length > 0 && { theme }),\n }\n}\n\n// Seletor do bloco de cada grupo: `:root`/`.dark` no CSS global, ou os do\n// tema no arquivo de um tema.\nfunction blockSelector(group: \"light\" | \"dark\", theme?: string) {\n if (theme) {\n return themeSelector(theme, group === \"dark\")\n }\n return group === \"light\" ? \":root\" : \".dark\"\n}\n\n// Compara seletores sem espaços nem aspas (`[a=\"x\"]` = `[a='x']` = `[a=x]`).\nconst normalize = (selector: string) => selector.replace(/[\"'\\s]/g, \"\")\n\nexport function findBlock(\n root: Root,\n group: ThemeGroup,\n theme?: string,\n): Container | undefined {\n return root.nodes.find((node) =>\n group === \"theme\"\n ? node.type === \"atrule\" &&\n node.name === \"theme\" &&\n node.params.trim() === \"inline\"\n : node.type === \"rule\" &&\n normalize(node.selector) === normalize(blockSelector(group, theme)),\n ) as Container | undefined\n}\n\nfunction createBlock(\n root: Root,\n group: ThemeGroup,\n theme?: string,\n): AtRule | Rule {\n const block =\n group === \"theme\"\n ? postcss.atRule({ name: \"theme\", params: \"inline\" })\n : postcss.rule({ selector: blockSelector(group, theme) })\n block.raws = {\n before: root.nodes.length > 0 ? \"\\n\\n\" : \"\",\n between: \" \",\n after: \"\\n\",\n semicolon: true,\n }\n root.append(block)\n return block\n}\n\n// `@custom-variant dark` depois dos `@import`, se o CSS não declara a variante.\nfunction ensureDarkVariant(root: Root) {\n const declared = root.nodes.some(\n (node) =>\n node.type === \"atrule\" &&\n node.name === \"custom-variant\" &&\n node.params.trim().startsWith(\"dark\"),\n )\n if (declared) {\n return\n }\n const variant = postcss.atRule({\n name: \"custom-variant\",\n params: \"dark (&:is(.dark *))\",\n })\n const imports = root.nodes.filter(\n (node) => node.type === \"atrule\" && node.name === \"import\",\n )\n const last = imports.at(-1)\n if (last) {\n variant.raws = { before: \"\\n\\n\" }\n last.after(variant)\n } else {\n variant.raws = { before: \"\" }\n root.prepend(variant)\n }\n}\n\nfunction same(a: string, b: string) {\n return a.replace(/\\s+/g, \" \").trim() === b.replace(/\\s+/g, \" \").trim()\n}\n","import postcss, { type AtRule, type Root } from \"postcss\"\n\nimport { isThemeName, THEME_ATTRIBUTE } from \"./attribute\"\nimport { findBlock } from \"./css\"\n\nexport type UnsetTokens = Partial<Record<\"light\" | \"dark\", string[]>>\n\nconst VAR_NAME = /^[\\w-]+$/\n\n// Tira variáveis dos blocos (`:root`/`.dark` ou os de um tema): num tema, a\n// variável volta a vir do CSS global.\nexport function removeTokens(\n css: string,\n unset: UnsetTokens,\n { theme }: { theme?: string } = {},\n): string {\n const root = postcss.parse(css)\n for (const group of [\"light\", \"dark\"] as const) {\n const names = new Set(\n (unset[group] ?? []).filter((name) => VAR_NAME.test(name)),\n )\n if (names.size === 0) {\n continue\n }\n findBlock(root, group, theme)?.each((node) => {\n if (node.type === \"decl\" && names.has(node.prop.slice(2))) {\n node.remove()\n }\n })\n }\n return root.toString()\n}\n\n// Conteúdo inicial do arquivo de um tema novo.\nexport function themeFileHeader(name: string): string {\n return `/* Tema \"${name}\": só o que muda em relação ao CSS global. Aplicado com\n <html ${THEME_ATTRIBUTE}=\"${name}\"> ou SLABUI_THEME=${name}. */\n`\n}\n\n// Troca o nome do tema nos seletores do arquivo\n// (`[data-slabui-theme=\"a\"]` → `[data-slabui-theme=\"b\"]`).\nexport function renameThemeSelectors(\n css: string,\n from: string,\n to: string,\n): string {\n if (!isThemeName(from) || !isThemeName(to)) {\n throw new Error(`Invalid theme name: \"${from}\" → \"${to}\"`)\n }\n const pattern = new RegExp(\n `\\\\[${THEME_ATTRIBUTE}\\\\s*=\\\\s*([\"']?)${from}\\\\1\\\\s*\\\\]`,\n \"g\",\n )\n const root = postcss.parse(css)\n root.walkRules((rule) => {\n rule.selector = rule.selector.replace(\n pattern,\n `[${THEME_ATTRIBUTE}=\"${to}\"]`,\n )\n })\n root.walkComments((comment) => {\n comment.text = comment.text\n .replaceAll(`\"${from}\"`, `\"${to}\"`)\n .replaceAll(`SLABUI_THEME=${from}`, `SLABUI_THEME=${to}`)\n })\n return root.toString()\n}\n\n// Caminho de um `@import \"x\"` ou `@import url(\"x\")`.\nfunction importPath(rule: AtRule) {\n return rule.params\n .trim()\n .replace(/^url\\((.*)\\)/, \"$1\")\n .split(/\\s/)[0]\n ?.replace(/^[\"']|[\"']$/g, \"\")\n}\n\nconst sameImport = (a: string | undefined, b: string) =>\n a !== undefined && a.replace(/^\\.\\//, \"\") === b.replace(/^\\.\\//, \"\")\n\nfunction imports(root: Root) {\n return root.nodes.filter(\n (node): node is AtRule => node.type === \"atrule\" && node.name === \"import\",\n )\n}\n\n// Caminhos dos `@import` locais (`./x.css`, `../x.css`) de um CSS.\nexport function localImports(css: string): string[] {\n return imports(postcss.parse(css))\n .map(importPath)\n .filter(\n (target): target is string =>\n target?.startsWith(\"./\") === true || target?.startsWith(\"../\") === true,\n )\n}\n\n// `@import` do tema no CSS global, depois dos outros imports.\nexport function addThemeImport(css: string, path: string): string {\n return addImport(css, path)\n}\n\n// `@import \"<path>\"` no CSS, depois dos outros imports, se ainda não houver\n// (`./base.css` e `base.css` são o mesmo).\nexport function addImport(css: string, path: string): string {\n const root = postcss.parse(css)\n const existing = imports(root)\n if (existing.some((rule) => sameImport(importPath(rule), path))) {\n return css\n }\n const rule = postcss.atRule({ name: \"import\", params: `\"${path}\"` })\n const last = existing.at(-1)\n if (last) {\n rule.raws = { before: \"\\n\" }\n last.after(rule)\n } else {\n rule.raws = { before: \"\" }\n root.prepend(rule)\n }\n return root.toString()\n}\n\nexport function removeThemeImport(css: string, path: string): string {\n const root = postcss.parse(css)\n for (const rule of imports(root)) {\n if (sameImport(importPath(rule), path)) {\n rule.remove()\n }\n }\n return root.toString()\n}\n\nexport function renameThemeImport(css: string, from: string, to: string) {\n const root = postcss.parse(css)\n for (const rule of imports(root)) {\n if (sameImport(importPath(rule), from)) {\n rule.params = `\"${to}\"`\n }\n }\n return root.toString()\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slabui/theme-core",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "SlabUI theme as CSS variables: read, write, validate and multi-theme helpers",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": "André Felipe Schulle <andrefelipeschulle@icloud.com>",
|
package/dist/css-COrLu65l.mjs
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import{themeSelector as e}from"./attribute.mjs";import t from"postcss";const n=/^\s*(oklch|oklab|lch|lab|hsla?|rgba?|hwb|color)\(|^\s*#[0-9a-f]{3,8}\s*$/i;async function r(e,n,{base:r,overwrite:a=!1,shouldRemove:o,theme:d}={}){let f=t.parse(e),p=[],m=[],h=e=>d?e:i(e),g=h(n),_=r?h(r):void 0;for(let e of[`theme`,`light`,`dark`]){let n=g[e]??{},r=_?.[e]??{},i=/* @__PURE__ */ new Set([...Object.keys(n),...Object.keys(r)]);if(i.size===0)continue;let l=s(f,e,d);for(let s of i){let i=n[s],h=r[s],g=l?.nodes?.find(e=>e.type===`decl`&&e.prop===`--${s}`),_=g?.value,v=t=>p.push({group:e,name:s,action:t});if(i===void 0){if(_===void 0)continue;o&&await o(e,s)?(g?.remove(),v(`removed`)):(m.push(`--${s} (${e}) was removed in the new version; kept in the CSS.`),v(`kept`))}else if(_===void 0){if(h!==void 0){v(`kept`);continue}l??=c(f,e,d),l.raws.semicolon=!0,l.raws.after=`
|
|
2
|
-
`,l.append(t.decl({prop:`--${s}`,value:i,raws:{before:`
|
|
3
|
-
`}})),v(`added`)}else u(_,i)?v(`unchanged`):a||h!==void 0&&u(_,h)?(g.value=i,v(`updated`)):(m.push(`--${s} (${e}) has a custom value in the CSS (${_}); kept instead of ${i}.`),v(`kept`))}}return!d&&Object.keys(g.dark??{}).length>0&&l(f),{css:f.toString(),changes:p,warnings:m}}function i(e){let t={...e.theme};for(let r of[e.light,e.dark])for(let[e,i]of Object.entries(r??{}))n.test(i)&&t[`color-${e}`]===void 0&&(t[`color-${e}`]=`var(--${e})`);return{...e,...Object.keys(t).length>0&&{theme:t}}}function a(t,n){return n?e(n,t===`dark`):t===`light`?`:root`:`.dark`}const o=e=>e.replace(/["'\s]/g,``);function s(e,t,n){return e.nodes.find(e=>t===`theme`?e.type===`atrule`&&e.name===`theme`&&e.params.trim()===`inline`:e.type===`rule`&&o(e.selector)===o(a(t,n)))}function c(e,n,r){let i=n===`theme`?t.atRule({name:`theme`,params:`inline`}):t.rule({selector:a(n,r)});return i.raws={before:e.nodes.length>0?`
|
|
4
|
-
|
|
5
|
-
`:``,between:` `,after:`
|
|
6
|
-
`,semicolon:!0},e.append(i),i}function l(e){if(e.nodes.some(e=>e.type===`atrule`&&e.name===`custom-variant`&&e.params.trim().startsWith(`dark`)))return;let n=t.atRule({name:`custom-variant`,params:`dark (&:is(.dark *))`}),r=e.nodes.filter(e=>e.type===`atrule`&&e.name===`import`).at(-1);r?(n.raws={before:`
|
|
7
|
-
|
|
8
|
-
`},r.after(n)):(n.raws={before:``},e.prepend(n))}function u(e,t){return e.replace(/\s+/g,` `).trim()===t.replace(/\s+/g,` `).trim()}export{s as n,i as r,r as t};
|
|
9
|
-
//# sourceMappingURL=css-COrLu65l.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"css-COrLu65l.mjs","names":["postcss","COLOR","applyCssVars","root","css","changes","warnings","mappings","theme","vars","withColorMappings","wanted","remote","previous","base","group","remoteVars","baseVars","names","block","findBlock","name","remoteValue","baseValue","declaration","node","local","record","shouldRemove","createBlock","same","overwrite","ensureDarkVariant","value","blockSelector","themeSelector","normalize","selector","variant","last","a","b"],"sources":["../src/css.ts"],"sourcesContent":["import postcss, {\n type AtRule,\n type Container,\n type Root,\n type Rule,\n} from \"postcss\"\n\nimport type { ThemeGroup, ThemeTokens } from \"./types\"\n\nimport { themeSelector } from \"./attribute\"\n\nexport type CssVarChange = {\n group: ThemeGroup\n name: string\n action: \"added\" | \"updated\" | \"kept\" | \"removed\" | \"unchanged\"\n}\n\nexport type CssVarsResult = {\n css: string\n changes: CssVarChange[]\n warnings: string[]\n}\n\nexport type ApplyCssVarsOptions = {\n // Variáveis da versão instalada (no update); ausente no add.\n base?: ThemeTokens\n overwrite?: boolean\n // Variável removida na versão nova: remover? Ausente = manter.\n shouldRemove?: (group: ThemeGroup, name: string) => Promise<boolean>\n // Arquivo de um tema (`styles/themes/<nome>.css`): os blocos são\n // `:root[data-slabui-theme=\"<nome>\"]` (e `.dark`) no lugar de `:root`/`.dark`.\n theme?: string\n}\n\nconst COLOR =\n /^\\s*(oklch|oklab|lch|lab|hsla?|rgba?|hwb|color)\\(|^\\s*#[0-9a-f]{3,8}\\s*$/i\n\n// Aplica as variáveis de um item no CSS global, com merge por variável.\nexport async function applyCssVars(\n css: string,\n remote: ThemeTokens,\n { base, overwrite = false, shouldRemove, theme }: ApplyCssVarsOptions = {},\n): Promise<CssVarsResult> {\n const root = postcss.parse(css)\n const changes: CssVarChange[] = []\n const warnings: string[] = []\n // Num arquivo de tema, os `--color-*` já estão no `@theme inline` do CSS\n // global; uma cor nova do tema declara o dela no próprio arquivo.\n const mappings = (vars: ThemeTokens) =>\n theme ? vars : withColorMappings(vars)\n const wanted = mappings(remote)\n const previous = base ? mappings(base) : undefined\n\n for (const group of [\"theme\", \"light\", \"dark\"] as const) {\n const remoteVars = wanted[group] ?? {}\n const baseVars = previous?.[group] ?? {}\n const names = new Set([\n ...Object.keys(remoteVars),\n ...Object.keys(baseVars),\n ])\n if (names.size === 0) {\n continue\n }\n let block = findBlock(root, group, theme)\n\n for (const name of names) {\n const remoteValue = remoteVars[name]\n const baseValue = baseVars[name]\n const declaration = block?.nodes?.find(\n (node) => node.type === \"decl\" && node.prop === `--${name}`,\n ) as postcss.Declaration | undefined\n const local = declaration?.value\n const record = (action: CssVarChange[\"action\"]) =>\n changes.push({ group, name, action })\n\n if (remoteValue === undefined) {\n // Removida na versão nova.\n if (local === undefined) {\n continue\n }\n if (shouldRemove && (await shouldRemove(group, name))) {\n declaration?.remove()\n record(\"removed\")\n } else {\n warnings.push(\n `--${name} (${group}) was removed in the new version; kept in the CSS.`,\n )\n record(\"kept\")\n }\n continue\n }\n\n if (local === undefined) {\n if (baseValue !== undefined) {\n // Apagada do CSS pelo usuário: não recria.\n record(\"kept\")\n continue\n }\n block ??= createBlock(root, group, theme)\n block.raws.semicolon = true\n block.raws.after = \"\\n\"\n block.append(\n postcss.decl({\n prop: `--${name}`,\n value: remoteValue,\n raws: { before: \"\\n \" },\n }),\n )\n record(\"added\")\n continue\n }\n\n if (same(local, remoteValue)) {\n record(\"unchanged\")\n } else if (\n overwrite ||\n (baseValue !== undefined && same(local, baseValue))\n ) {\n ;(declaration as postcss.Declaration).value = remoteValue\n record(\"updated\")\n } else {\n warnings.push(\n `--${name} (${group}) has a custom value in the CSS (${local}); kept instead of ${remoteValue}.`,\n )\n record(\"kept\")\n }\n }\n }\n\n // O arquivo de um tema é importado pelo CSS global, que já tem a variante.\n if (!theme && Object.keys(wanted.dark ?? {}).length > 0) {\n ensureDarkVariant(root)\n }\n\n return { css: root.toString(), changes, warnings }\n}\n\n// Cada cor de light/dark ganha `--color-<nome>: var(--<nome>)` no `theme`,\n// para o Tailwind 4 gerar as utilidades (`bg-<nome>`) e aceitar o `@apply`.\nexport function withColorMappings(vars: ThemeTokens): ThemeTokens {\n const theme = { ...vars.theme }\n for (const group of [vars.light, vars.dark]) {\n for (const [name, value] of Object.entries(group ?? {})) {\n if (COLOR.test(value) && theme[`color-${name}`] === undefined) {\n theme[`color-${name}`] = `var(--${name})`\n }\n }\n }\n return {\n ...vars,\n ...(Object.keys(theme).length > 0 && { theme }),\n }\n}\n\n// Seletor do bloco de cada grupo: `:root`/`.dark` no CSS global, ou os do\n// tema no arquivo de um tema.\nfunction blockSelector(group: \"light\" | \"dark\", theme?: string) {\n if (theme) {\n return themeSelector(theme, group === \"dark\")\n }\n return group === \"light\" ? \":root\" : \".dark\"\n}\n\n// Compara seletores sem espaços nem aspas (`[a=\"x\"]` = `[a='x']` = `[a=x]`).\nconst normalize = (selector: string) => selector.replace(/[\"'\\s]/g, \"\")\n\nexport function findBlock(\n root: Root,\n group: ThemeGroup,\n theme?: string,\n): Container | undefined {\n return root.nodes.find((node) =>\n group === \"theme\"\n ? node.type === \"atrule\" &&\n node.name === \"theme\" &&\n node.params.trim() === \"inline\"\n : node.type === \"rule\" &&\n normalize(node.selector) === normalize(blockSelector(group, theme)),\n ) as Container | undefined\n}\n\nfunction createBlock(\n root: Root,\n group: ThemeGroup,\n theme?: string,\n): AtRule | Rule {\n const block =\n group === \"theme\"\n ? postcss.atRule({ name: \"theme\", params: \"inline\" })\n : postcss.rule({ selector: blockSelector(group, theme) })\n block.raws = {\n before: root.nodes.length > 0 ? \"\\n\\n\" : \"\",\n between: \" \",\n after: \"\\n\",\n semicolon: true,\n }\n root.append(block)\n return block\n}\n\n// `@custom-variant dark` depois dos `@import`, se o CSS não declara a variante.\nfunction ensureDarkVariant(root: Root) {\n const declared = root.nodes.some(\n (node) =>\n node.type === \"atrule\" &&\n node.name === \"custom-variant\" &&\n node.params.trim().startsWith(\"dark\"),\n )\n if (declared) {\n return\n }\n const variant = postcss.atRule({\n name: \"custom-variant\",\n params: \"dark (&:is(.dark *))\",\n })\n const imports = root.nodes.filter(\n (node) => node.type === \"atrule\" && node.name === \"import\",\n )\n const last = imports.at(-1)\n if (last) {\n variant.raws = { before: \"\\n\\n\" }\n last.after(variant)\n } else {\n variant.raws = { before: \"\" }\n root.prepend(variant)\n }\n}\n\nfunction same(a: string, b: string) {\n return a.replace(/\\s+/g, \" \").trim() === b.replace(/\\s+/g, \" \").trim()\n}\n"],"mappings":"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"}
|
package/dist/files.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"files.mjs","names":["postcss","VAR_NAME","removeTokens","root","css","group","names","unset","name","findBlock","theme","node","themeFileHeader","THEME_ATTRIBUTE","renameThemeSelectors","isThemeName","from","to","pattern","rule","comment","importPath","sameImport","a","b","imports","addThemeImport","existing","path","last","removeThemeImport","renameThemeImport"],"sources":["../src/theme-files.ts"],"sourcesContent":["import postcss, { type AtRule, type Root } from \"postcss\"\n\nimport { isThemeName, THEME_ATTRIBUTE } from \"./attribute\"\nimport { findBlock } from \"./css\"\n\nexport type UnsetTokens = Partial<Record<\"light\" | \"dark\", string[]>>\n\nconst VAR_NAME = /^[\\w-]+$/\n\n// Tira variáveis dos blocos (`:root`/`.dark` ou os de um tema): num tema, a\n// variável volta a vir do CSS global.\nexport function removeTokens(\n css: string,\n unset: UnsetTokens,\n { theme }: { theme?: string } = {},\n): string {\n const root = postcss.parse(css)\n for (const group of [\"light\", \"dark\"] as const) {\n const names = new Set(\n (unset[group] ?? []).filter((name) => VAR_NAME.test(name)),\n )\n if (names.size === 0) {\n continue\n }\n findBlock(root, group, theme)?.each((node) => {\n if (node.type === \"decl\" && names.has(node.prop.slice(2))) {\n node.remove()\n }\n })\n }\n return root.toString()\n}\n\n// Conteúdo inicial do arquivo de um tema novo.\nexport function themeFileHeader(name: string): string {\n return `/* Tema \"${name}\": só o que muda em relação ao CSS global. Aplicado com\n <html ${THEME_ATTRIBUTE}=\"${name}\"> ou SLABUI_THEME=${name}. */\n`\n}\n\n// Troca o nome do tema nos seletores do arquivo\n// (`[data-slabui-theme=\"a\"]` → `[data-slabui-theme=\"b\"]`).\nexport function renameThemeSelectors(\n css: string,\n from: string,\n to: string,\n): string {\n if (!isThemeName(from) || !isThemeName(to)) {\n throw new Error(`Invalid theme name: \"${from}\" → \"${to}\"`)\n }\n const pattern = new RegExp(\n `\\\\[${THEME_ATTRIBUTE}\\\\s*=\\\\s*([\"']?)${from}\\\\1\\\\s*\\\\]`,\n \"g\",\n )\n const root = postcss.parse(css)\n root.walkRules((rule) => {\n rule.selector = rule.selector.replace(\n pattern,\n `[${THEME_ATTRIBUTE}=\"${to}\"]`,\n )\n })\n root.walkComments((comment) => {\n comment.text = comment.text\n .replaceAll(`\"${from}\"`, `\"${to}\"`)\n .replaceAll(`SLABUI_THEME=${from}`, `SLABUI_THEME=${to}`)\n })\n return root.toString()\n}\n\n// Caminho de um `@import \"x\"` ou `@import url(\"x\")`.\nfunction importPath(rule: AtRule) {\n return rule.params\n .trim()\n .replace(/^url\\((.*)\\)/, \"$1\")\n .split(/\\s/)[0]\n ?.replace(/^[\"']|[\"']$/g, \"\")\n}\n\nconst sameImport = (a: string | undefined, b: string) =>\n a !== undefined && a.replace(/^\\.\\//, \"\") === b.replace(/^\\.\\//, \"\")\n\nfunction imports(root: Root) {\n return root.nodes.filter(\n (node): node is AtRule => node.type === \"atrule\" && node.name === \"import\",\n )\n}\n\n// `@import` do tema no CSS global, depois dos outros imports.\nexport function addThemeImport(css: string, path: string): string {\n const root = postcss.parse(css)\n const existing = imports(root)\n if (existing.some((rule) => sameImport(importPath(rule), path))) {\n return css\n }\n const rule = postcss.atRule({ name: \"import\", params: `\"${path}\"` })\n const last = existing.at(-1)\n if (last) {\n rule.raws = { before: \"\\n\" }\n last.after(rule)\n } else {\n rule.raws = { before: \"\" }\n root.prepend(rule)\n }\n return root.toString()\n}\n\nexport function removeThemeImport(css: string, path: string): string {\n const root = postcss.parse(css)\n for (const rule of imports(root)) {\n if (sameImport(importPath(rule), path)) {\n rule.remove()\n }\n }\n return root.toString()\n}\n\nexport function renameThemeImport(css: string, from: string, to: string) {\n const root = postcss.parse(css)\n for (const rule of imports(root)) {\n if (sameImport(importPath(rule), from)) {\n rule.params = `\"${to}\"`\n }\n }\n return root.toString()\n}\n"],"mappings":"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"}
|