@slabui/theme-core 0.0.0-stage → 0.0.2
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 +16 -0
- package/LICENSE +59 -0
- package/README.md +12 -2
- package/dist/attribute.d.mts +6 -0
- package/dist/attribute.d.mts.map +1 -0
- package/dist/attribute.mjs +2 -0
- package/dist/attribute.mjs.map +1 -0
- package/dist/css-COrLu65l.mjs +9 -0
- package/dist/css-COrLu65l.mjs.map +1 -0
- package/dist/files.d.mts +10 -0
- package/dist/files.d.mts.map +1 -0
- package/dist/files.mjs +5 -0
- package/dist/files.mjs.map +1 -0
- package/dist/index.d.mts +171 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +56 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# @slabui/theme-core
|
|
2
|
+
|
|
3
|
+
## 0.0.2
|
|
4
|
+
|
|
5
|
+
## 0.0.1
|
|
6
|
+
|
|
7
|
+
### Patch Changes
|
|
8
|
+
|
|
9
|
+
- [#44](https://github.com/slabui/ui/pull/44) [`a03fb1e`](https://github.com/slabui/ui/commit/a03fb1e6cfaae16d96167545da30e368cf1335ce) Thanks [@andrefelipeschulle](https://github.com/andrefelipeschulle)! - Primeira versão pública dos pacotes da SlabUI:
|
|
10
|
+
|
|
11
|
+
- `slabui`: o comando que se usa no projeto (`npx slabui init`, `npx slabui add button`). Instala o `@slabui/cli`, que traz o `init`, `add`, `update`, `outdated`, `diff`, `search`, `info`, `login`/`logout` e `mcp`.
|
|
12
|
+
- `@slabui/mcp`: o servidor MCP do registry da SlabUI. Roda na máquina do desenvolvedor (`npx -y @slabui/mcp`, por stdio) e é o mesmo que responde em `https://slabui.com/mcp`.
|
|
13
|
+
- `@slabui/theme-react`: o editor de tema ao vivo e os plugins do Vite e do Next, que gravam as variáveis no CSS do projeto.
|
|
14
|
+
- `@slabui/theme-core`: o tema da SlabUI como variáveis CSS (ler, gravar e validar) e o atributo do tema ativo no `<html>`.
|
|
15
|
+
|
|
16
|
+
A documentação fica em https://slabui.com/docs.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
SlabUI Software License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BrainyLab Desenvolvimento de Software LTDA.
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
This license applies to the slabui, @slabui/cli, @slabui/mcp,
|
|
7
|
+
@slabui/theme-core and @slabui/theme-react packages (the "Software").
|
|
8
|
+
|
|
9
|
+
1. Grant
|
|
10
|
+
|
|
11
|
+
Subject to the terms of this license, BrainyLab grants you a worldwide,
|
|
12
|
+
non-exclusive, non-transferable, royalty-free license to install and run
|
|
13
|
+
the Software, in unmodified form, in any project, including commercial
|
|
14
|
+
projects and projects used to build other tools and products.
|
|
15
|
+
|
|
16
|
+
Output produced by running the Software (such as configuration files and
|
|
17
|
+
the files it writes into your project) is not covered by this license. Files
|
|
18
|
+
installed from a registry are covered by that registry's own license.
|
|
19
|
+
|
|
20
|
+
2. Restrictions
|
|
21
|
+
|
|
22
|
+
You may not:
|
|
23
|
+
|
|
24
|
+
a. modify, adapt, translate or create derivative works of the Software;
|
|
25
|
+
b. copy, redistribute, sublicense, sell, rent or lease the Software, alone
|
|
26
|
+
or as part of another package, except as an unmodified dependency
|
|
27
|
+
installed from the official npm package;
|
|
28
|
+
c. reverse engineer, decompile or disassemble the Software, except to the
|
|
29
|
+
extent applicable law expressly permits it despite this restriction;
|
|
30
|
+
d. remove or alter any copyright or license notice in the Software.
|
|
31
|
+
|
|
32
|
+
3. Ownership
|
|
33
|
+
|
|
34
|
+
The Software is licensed, not sold. BrainyLab keeps all rights, title and
|
|
35
|
+
interest in the Software not expressly granted in this license.
|
|
36
|
+
|
|
37
|
+
4. Termination
|
|
38
|
+
|
|
39
|
+
This license ends automatically if you breach its terms. On termination,
|
|
40
|
+
you must stop using the Software and delete your copies of it.
|
|
41
|
+
|
|
42
|
+
5. No warranty
|
|
43
|
+
|
|
44
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
45
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
46
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
47
|
+
|
|
48
|
+
6. Limitation of liability
|
|
49
|
+
|
|
50
|
+
IN NO EVENT SHALL BRAINYLAB OR ITS CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
|
|
51
|
+
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
52
|
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
53
|
+
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
54
|
+
|
|
55
|
+
7. Governing law
|
|
56
|
+
|
|
57
|
+
This license is governed by the laws of the Federative Republic of Brazil.
|
|
58
|
+
Any dispute arising from it will be settled in the courts of the judicial
|
|
59
|
+
district where BrainyLab has its registered office.
|
package/README.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @slabui/theme-core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The SlabUI theme as CSS variables: read and write a theme in your CSS, validate
|
|
4
|
+
values and set the active theme on `<html>`. Shared by the theme editor, the
|
|
5
|
+
CLI and servers.
|
|
6
|
+
|
|
7
|
+
[](https://slabui.com/docs/themes/api-reference)
|
|
8
|
+
|
|
9
|
+
The API is in the [documentation](https://slabui.com/docs/themes/api-reference).
|
|
10
|
+
|
|
11
|
+
## License
|
|
12
|
+
|
|
13
|
+
Released under the [SlabUI Software License](./LICENSE).
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const THEME_ATTRIBUTE = "data-slabui-theme";
|
|
2
|
+
export declare const THEME_ENV = "SLABUI_THEME";
|
|
3
|
+
export declare function isThemeName(name: string): boolean;
|
|
4
|
+
export declare function themeSelector(name: string, dark?: boolean): string;
|
|
5
|
+
export declare function themeAttribute(theme?: string | undefined): Record<string, string>;
|
|
6
|
+
//# sourceMappingURL=attribute.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribute.d.mts","names":[],"sources":["../src/attribute.ts"],"mappings":"A,qBAIa;qBAIA;wBAKG,YAAY;wBAKZ,cAAc,cAAc;wBAS5B,eACd,6BAGC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=`data-slabui-theme`,t=`SLABUI_THEME`,n=/^[a-z0-9][a-z0-9-]*$/i;function r(e){return n.test(e)}function i(t,n=!1){if(!r(t))throw Error(`Invalid theme name: "${t}"`);return`:root[${e}="${t}"]${n?`.dark`:``}`}function a(n=typeof process>`u`?void 0:process.env[t]){return n&&r(n)?{[e]:n}:{}}export{e as THEME_ATTRIBUTE,t as THEME_ENV,r as isThemeName,a as themeAttribute,i as themeSelector};
|
|
2
|
+
//# sourceMappingURL=attribute.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribute.mjs","names":["THEME_ATTRIBUTE","THEME_ENV","THEME_NAME","isThemeName","name","themeSelector","dark","themeAttribute","theme"],"sources":["../src/attribute.ts"],"sourcesContent":["// Multi-tema estático: cada tema é um CSS em `styles/themes/<nome>.css`,\n// aplicado pelo atributo no `<html>`. Sem dependências, para o layout do app\n// (Next) ou o navegador importarem.\n\nexport const THEME_ATTRIBUTE = \"data-slabui-theme\"\n\n// Variável de ambiente que escolhe o tema quando o código não define o\n// atributo.\nexport const THEME_ENV = \"SLABUI_THEME\"\n\n// Vai num seletor CSS e num caminho de arquivo: só letras, números e `-`.\nconst THEME_NAME = /^[a-z0-9][a-z0-9-]*$/i\n\nexport function isThemeName(name: string): boolean {\n return THEME_NAME.test(name)\n}\n\n// `:root[data-slabui-theme=\"loja-a\"]` e, no modo escuro, com `.dark`.\nexport function themeSelector(name: string, dark = false): string {\n if (!isThemeName(name)) {\n throw new Error(`Invalid theme name: \"${name}\"`)\n }\n return `:root[${THEME_ATTRIBUTE}=\"${name}\"]${dark ? \".dark\" : \"\"}`\n}\n\n// Atributo do `<html>` com o tema da variável de ambiente (ou o informado):\n// `<html {...themeAttribute()}>`. Sem tema, um objeto vazio.\nexport function themeAttribute(\n theme: string | undefined = typeof process === \"undefined\"\n ? undefined\n : process.env[THEME_ENV],\n): Record<string, string> {\n return theme && isThemeName(theme) ? { [THEME_ATTRIBUTE]: theme } : {}\n}\n"],"mappings":"AAIA,MAAaA,EAAkB,oBAIlBC,EAAY,eAGnBC,EAAa,wBAEnB,SAAgBC,EAAY,EAAuB,CACjD,OAAOD,EAAW,KAAKE,CAAI,CAC7B,CAGA,SAAgBC,EAAc,EAAc,EAAO,GAAe,CAChE,GAAI,CAACF,EAAYC,CAAI,EACnB,MAAU,MAAM,wBAAwBA,EAAK,EAAE,EAEjD,MAAO,SAASJ,EAAgB,IAAII,EAAK,IAAIE,EAAO,QAAU,IAChE,CAIA,SAAgBC,EACd,EAA4B,OAAO,QAAY,IAC3C,IAAA,GACA,QAAQ,IAAIN,GACQ,CACxB,OAAOO,GAASL,EAAYK,CAAK,EAAI,EAAGR,GAAkBQ,CAAM,EAAI,CAAC,CACvE,C"}
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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.d.mts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type UnsetTokens = Partial<Record<"light" | "dark", string[]>>;
|
|
2
|
+
export declare function removeTokens(css: string, unset: UnsetTokens, { theme }?: {
|
|
3
|
+
theme?: string;
|
|
4
|
+
}): string;
|
|
5
|
+
export declare function themeFileHeader(name: string): string;
|
|
6
|
+
export declare function renameThemeSelectors(css: string, from: string, to: string): string;
|
|
7
|
+
export declare function addThemeImport(css: string, path: string): string;
|
|
8
|
+
export declare function removeThemeImport(css: string, path: string): string;
|
|
9
|
+
export declare function renameThemeImport(css: string, from: string, to: string): string;
|
|
10
|
+
//# sourceMappingURL=files.d.mts.map
|
|
@@ -0,0 +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;wBAkB5B,kBAAkB,aAAa;wBAU/B,kBAAkB,aAAa,cAAc"}
|
package/dist/files.mjs
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{THEME_ATTRIBUTE as e,isThemeName as t}from"./attribute.mjs";import{n}from"./css-COrLu65l.mjs";import r from"postcss";const i=/^[\w-]+$/;function a(e,t,{theme:a}={}){let o=r.parse(e);for(let e of[`light`,`dark`]){let r=new Set((t[e]??[]).filter(e=>i.test(e)));r.size!==0&&n(o,e,a)?.each(e=>{e.type===`decl`&&r.has(e.prop.slice(2))&&e.remove()})}return o.toString()}function o(t){return`/* Tema "${t}": só o que muda em relação ao CSS global. Aplicado com
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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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"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { THEME_ATTRIBUTE, THEME_ENV, isThemeName, themeAttribute, themeSelector } from "./attribute.mjs";
|
|
2
|
+
import "postcss";
|
|
3
|
+
type ThemeGroup = "theme" | "light" | "dark";
|
|
4
|
+
type ThemeVars = Record<string, string>;
|
|
5
|
+
type ThemeTokens = Partial<Record<ThemeGroup, ThemeVars>>;
|
|
6
|
+
type CssVarChange = {
|
|
7
|
+
group: ThemeGroup;
|
|
8
|
+
name: string;
|
|
9
|
+
action: "added" | "updated" | "kept" | "removed" | "unchanged";
|
|
10
|
+
};
|
|
11
|
+
type CssVarsResult = {
|
|
12
|
+
css: string;
|
|
13
|
+
changes: CssVarChange[];
|
|
14
|
+
warnings: string[];
|
|
15
|
+
};
|
|
16
|
+
type ApplyCssVarsOptions = {
|
|
17
|
+
base?: ThemeTokens;
|
|
18
|
+
overwrite?: boolean;
|
|
19
|
+
shouldRemove?: (group: ThemeGroup, name: string) => Promise<boolean>;
|
|
20
|
+
theme?: string;
|
|
21
|
+
};
|
|
22
|
+
export declare function applyCssVars(css: string, remote: ThemeTokens, { base, overwrite, shouldRemove, theme }?: ApplyCssVarsOptions): Promise<CssVarsResult>;
|
|
23
|
+
export declare function withColorMappings(vars: ThemeTokens): ThemeTokens;
|
|
24
|
+
export declare const defaultTheme: {
|
|
25
|
+
theme: {
|
|
26
|
+
"font-sans": string;
|
|
27
|
+
"font-heading": string;
|
|
28
|
+
"font-mono": string;
|
|
29
|
+
"radius-sm": string;
|
|
30
|
+
"radius-md": string;
|
|
31
|
+
"radius-lg": string;
|
|
32
|
+
"radius-xl": string;
|
|
33
|
+
"radius-2xl": string;
|
|
34
|
+
"radius-3xl": string;
|
|
35
|
+
"radius-4xl": string;
|
|
36
|
+
"breakpoint-3xl": string;
|
|
37
|
+
"breakpoint-4xl": string;
|
|
38
|
+
"text-xxs": string;
|
|
39
|
+
"text-2xxs": string;
|
|
40
|
+
"text-2xs": string;
|
|
41
|
+
"text-2xs--line-height": string;
|
|
42
|
+
"text-2sm": string;
|
|
43
|
+
"text-2sm--line-height": string;
|
|
44
|
+
spacing: string;
|
|
45
|
+
"focus-size": string;
|
|
46
|
+
"focus-offset": string;
|
|
47
|
+
"color-destructive": string;
|
|
48
|
+
};
|
|
49
|
+
light: {
|
|
50
|
+
spacing: string;
|
|
51
|
+
radius: string;
|
|
52
|
+
background: string;
|
|
53
|
+
foreground: string;
|
|
54
|
+
card: string;
|
|
55
|
+
"card-foreground": string;
|
|
56
|
+
popover: string;
|
|
57
|
+
"popover-foreground": string;
|
|
58
|
+
muted: string;
|
|
59
|
+
"muted-foreground": string;
|
|
60
|
+
accent: string;
|
|
61
|
+
"accent-foreground": string;
|
|
62
|
+
border: string;
|
|
63
|
+
input: string;
|
|
64
|
+
ring: string;
|
|
65
|
+
"chart-1": string;
|
|
66
|
+
"chart-2": string;
|
|
67
|
+
"chart-3": string;
|
|
68
|
+
"chart-4": string;
|
|
69
|
+
"chart-5": string;
|
|
70
|
+
sidebar: string;
|
|
71
|
+
"sidebar-foreground": string;
|
|
72
|
+
"sidebar-primary": string;
|
|
73
|
+
"sidebar-primary-foreground": string;
|
|
74
|
+
"sidebar-accent": string;
|
|
75
|
+
"sidebar-accent-foreground": string;
|
|
76
|
+
"sidebar-border": string;
|
|
77
|
+
"sidebar-ring": string;
|
|
78
|
+
primary: string;
|
|
79
|
+
"primary-foreground": string;
|
|
80
|
+
secondary: string;
|
|
81
|
+
"secondary-foreground": string;
|
|
82
|
+
danger: string;
|
|
83
|
+
"danger-foreground": string;
|
|
84
|
+
success: string;
|
|
85
|
+
"success-foreground": string;
|
|
86
|
+
warning: string;
|
|
87
|
+
"warning-foreground": string;
|
|
88
|
+
inverted: string;
|
|
89
|
+
"inverted-foreground": string;
|
|
90
|
+
focus: string;
|
|
91
|
+
"focus-size": string;
|
|
92
|
+
"focus-offset": string;
|
|
93
|
+
table: string;
|
|
94
|
+
"table-content": string;
|
|
95
|
+
"table-hover": string;
|
|
96
|
+
};
|
|
97
|
+
dark: {
|
|
98
|
+
background: string;
|
|
99
|
+
foreground: string;
|
|
100
|
+
card: string;
|
|
101
|
+
"card-foreground": string;
|
|
102
|
+
popover: string;
|
|
103
|
+
"popover-foreground": string;
|
|
104
|
+
secondary: string;
|
|
105
|
+
"secondary-foreground": string;
|
|
106
|
+
muted: string;
|
|
107
|
+
"muted-foreground": string;
|
|
108
|
+
accent: string;
|
|
109
|
+
"accent-foreground": string;
|
|
110
|
+
border: string;
|
|
111
|
+
input: string;
|
|
112
|
+
ring: string;
|
|
113
|
+
"chart-1": string;
|
|
114
|
+
"chart-2": string;
|
|
115
|
+
"chart-3": string;
|
|
116
|
+
"chart-4": string;
|
|
117
|
+
"chart-5": string;
|
|
118
|
+
sidebar: string;
|
|
119
|
+
"sidebar-foreground": string;
|
|
120
|
+
"sidebar-primary": string;
|
|
121
|
+
"sidebar-primary-foreground": string;
|
|
122
|
+
"sidebar-accent": string;
|
|
123
|
+
"sidebar-accent-foreground": string;
|
|
124
|
+
"sidebar-border": string;
|
|
125
|
+
"sidebar-ring": string;
|
|
126
|
+
primary: string;
|
|
127
|
+
"primary-foreground": string;
|
|
128
|
+
danger: string;
|
|
129
|
+
"danger-foreground": string;
|
|
130
|
+
success: string;
|
|
131
|
+
"success-foreground": string;
|
|
132
|
+
warning: string;
|
|
133
|
+
"warning-foreground": string;
|
|
134
|
+
inverted: string;
|
|
135
|
+
"inverted-foreground": string;
|
|
136
|
+
focus: string;
|
|
137
|
+
table: string;
|
|
138
|
+
"table-content": string;
|
|
139
|
+
"table-hover": string;
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
type ValueKind = "color" | "length" | "number" | "keyword" | "expression";
|
|
143
|
+
type ThemeIssue = {
|
|
144
|
+
group: ThemeGroup;
|
|
145
|
+
name: string;
|
|
146
|
+
value: string;
|
|
147
|
+
message: string;
|
|
148
|
+
};
|
|
149
|
+
export declare class ThemeValidationError extends Error {
|
|
150
|
+
readonly issues: ThemeIssue[];
|
|
151
|
+
constructor(issues: ThemeIssue[]);
|
|
152
|
+
}
|
|
153
|
+
export declare function isSafeValue(value: string): boolean;
|
|
154
|
+
export declare function getValueKind(value: string): ValueKind;
|
|
155
|
+
type ValidateThemeOptions = {
|
|
156
|
+
reference?: ThemeTokens;
|
|
157
|
+
};
|
|
158
|
+
export declare function validateTheme(tokens: ThemeTokens, { reference }?: ValidateThemeOptions): ThemeIssue[];
|
|
159
|
+
type ThemeFileOptions = {
|
|
160
|
+
theme?: string;
|
|
161
|
+
};
|
|
162
|
+
export declare function readTheme(css: string, { theme }?: ThemeFileOptions): ThemeTokens;
|
|
163
|
+
export declare function writeTheme(css: string, tokens: ThemeTokens, { reference, ...options }?: Omit<ApplyCssVarsOptions, "overwrite"> & ValidateThemeOptions): Promise<CssVarsResult>;
|
|
164
|
+
type TokenCatalog = {
|
|
165
|
+
vars: Set<string>;
|
|
166
|
+
colors: Map<string, string>;
|
|
167
|
+
};
|
|
168
|
+
export declare function tokenCatalog(theme: ThemeTokens, itemVars?: ThemeTokens[]): TokenCatalog;
|
|
169
|
+
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 };
|
|
171
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +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":";;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;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;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IAEA;IAEA;IACA;IACA;;;KChIQ;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
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{THEME_ATTRIBUTE as e,THEME_ENV as t,isThemeName as n,themeAttribute as r,themeSelector as i}from"./attribute.mjs";import{n as a,r as o,t as s}from"./css-COrLu65l.mjs";import c from"postcss";const l={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)`,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)`,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)`}};var u=class extends Error{issues;constructor(e){super(`Invalid theme:\n${e.map(({group:e,name:t,message:n})=>` --${t} (${e}): ${n}`).join(`
|
|
2
|
+
`)}`),this.issues=e,this.name=`ThemeValidationError`}};const d=/^[\w-]+$/,f=/^[\w\s.,%#()+\-*/]+$/,p=/* @__PURE__ */ new Set([`rgb`,`rgba`,`hsl`,`hsla`,`hwb`,`lab`,`lch`,`oklab`,`oklch`,`color`,`color-mix`]),m=/* @__PURE__ */ new Set([`calc`,`min`,`max`,`clamp`,`var`]),h=/^#(?:[\da-f]{3,4}|[\da-f]{6}|[\da-f]{8})$/i,g=/^[+-]?(?:\d+\.?\d*|\.\d+)$/,_=/^[+-]?(?:\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,v=/^[a-z][a-z-]*$/i,y=/^([a-z-]+)\(/i;function b(e){if(e.trim()===``||e.length>200||!f.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!==``&&!p.has(e)&&!m.has(e))return!1}return!0}function x(e){let t=e.trim();if(h.test(t))return`color`;if(g.test(t))return`number`;if(_.test(t))return`length`;if(v.test(t))return`keyword`;let n=t.match(y)?.[1]?.toLowerCase();return n&&p.has(n)?`color`:`expression`}function S(e,t){return t===e||t===`expression`||t===`keyword`||e===`length`&&t===`number`}function C(e,{reference:t=l}={}){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(!d.test(i)){e(`invalid variable name`);continue}if(typeof a!=`string`||!b(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=x(o),c=x(a);s!==`expression`&&!S(s,c)&&e(`expected a ${s}, got a ${c}`)}return n}const w=[`theme`,`light`,`dark`];function T(e,{theme:t}={}){let n=c.parse(e),r={};for(let e of w){let i={};a(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={}}=o({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 E(e,t,{reference:n,...r}={}){let i=C(t,{reference:n});if(i.length>0)throw new u(i);return s(e,t,{...r,overwrite:!0})}const D=/(?<![\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,O=/(?<![\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.-])/,A=/--spacing\(/,j=/var\(--([\w-]+)/g;function M(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 N(e,t){let n=/* @__PURE__ */ new Set;for(let r of e){for(let[,e]of r.matchAll(D)){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`)&&O.test(r)&&n.add(`radius`),t.vars.has(`spacing`)&&(k.test(r)||A.test(r))&&n.add(`spacing`)}return[...n].sort()}export{e as THEME_ATTRIBUTE,t as THEME_ENV,u as ThemeValidationError,s as applyCssVars,l as defaultTheme,N as findTokens,x as getValueKind,b as isSafeValue,n as isThemeName,T as readTheme,r as themeAttribute,i as themeSelector,M as tokenCatalog,C as validateTheme,o as withColorMappings,E as writeTheme};
|
|
3
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,59 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slabui/theme-core",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "SlabUI theme as CSS variables: read, write, validate and multi-theme helpers",
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
|
+
"author": "André Felipe Schulle <andrefelipeschulle@icloud.com>",
|
|
7
|
+
"homepage": "https://slabui.com/docs/themes/introduction",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/slabui/ui.git",
|
|
11
|
+
"directory": "packages/theme-core"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/slabui/ui/issues"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"module": "dist/index.mjs",
|
|
18
|
+
"keywords": [
|
|
19
|
+
"slabui",
|
|
20
|
+
"theme",
|
|
21
|
+
"theming",
|
|
22
|
+
"css-variables",
|
|
23
|
+
"design-tokens",
|
|
24
|
+
"tailwindcss",
|
|
25
|
+
"oklch",
|
|
26
|
+
"dark-mode"
|
|
27
|
+
],
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"LICENSE",
|
|
31
|
+
"CHANGELOG.md"
|
|
32
|
+
],
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./dist/index.d.mts",
|
|
36
|
+
"import": "./dist/index.mjs"
|
|
37
|
+
},
|
|
38
|
+
"./attribute": {
|
|
39
|
+
"types": "./dist/attribute.d.mts",
|
|
40
|
+
"import": "./dist/attribute.mjs"
|
|
41
|
+
},
|
|
42
|
+
"./files": {
|
|
43
|
+
"types": "./dist/files.d.mts",
|
|
44
|
+
"import": "./dist/files.mjs"
|
|
45
|
+
},
|
|
46
|
+
"./package.json": "./package.json"
|
|
47
|
+
},
|
|
48
|
+
"sideEffects": false,
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"postcss": "8.5.23"
|
|
51
|
+
},
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=22.12.0"
|
|
54
|
+
},
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"access": "public"
|
|
57
|
+
},
|
|
58
|
+
"types": "dist/index.d.mts"
|
|
6
59
|
}
|