@stamcat/craftsman 0.0.34 → 0.0.36

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stamcat/craftsman",
3
- "version": "0.0.34",
3
+ "version": "0.0.36",
4
4
  "type": "module",
5
5
  "description": "A powerful, lightweight framework for design systems",
6
6
  "repository": {
@@ -202,6 +202,31 @@ Do not compute `calc()` strings per-property in JS/TS (for example building a `p
202
202
 
203
203
  Valid `theme.widths` keys: `"text" | "gutter" | "column" | "tablet" | "desktop" | "extDesktop" | "mobileMax" | "tabletMax" | "desktopMax"`
204
204
 
205
+ ### Cascade Layers and `ThemeProvider`'s `layered`/`hoist` Options
206
+
207
+ `ThemeProvider` (and the underlying `themeBuilder`) exposes two related but independent options for controlling how the runtime theme CSS interacts with cascade layers:
208
+
209
+ - **`layered`** (default `true`) — whether the theme CSS is wrapped in the `craftsman-theme` cascade layer.
210
+ - **`hoist`** (default `true`) — whether the theme `<style>` is hoisted to `<head>` via React's resource precedence mechanism. React always inserts a hoisted style as the first stylesheet in the document, which wins any `@layer` name-registration race against your app's own `@layer` order pin.
211
+
212
+ By default (`hoist: true`), the hoisted style is always the first stylesheet in `<head>` regardless of import order, so its `@layer` declaration always wins the layer-registration race and permanently fixes `craftsman-theme`'s priority relative to any layers a consuming app declares afterward.
213
+
214
+ If the consuming app uses Tailwind or another framework that declares its own cascade layer order (for example Tailwind's `@layer theme, base, components, utilities;`) and needs that app-level order to win instead, set `hoist: false` so the theme `<style>` renders in normal tree/commit order instead — letting an earlier-declared app-level `@layer` statement control where `craftsman-theme` ranks:
215
+
216
+ ```tsx
217
+ <ThemeProvider theme={theme} hoist={false} />
218
+ ```
219
+
220
+ Set `layered: false` (on `ThemeProvider` or `themeBuilder` directly) when the theme CSS should not join `@layer craftsman-theme` at all:
221
+
222
+ ```tsx
223
+ <ThemeProvider theme={theme} layered={false} />
224
+ // or, calling themeBuilder directly:
225
+ themeBuilder(theme, { layered: false });
226
+ ```
227
+
228
+ With `layered: false`, the theme CSS still declares `@layer craftsman-theme` but does not join a Craftsman-owned layer order — the consuming app is responsible for declaring `craftsman-theme` in its own `@layer` order statement wherever it wants that priority to apply.
229
+
205
230
  ### Theme Authoring Usage Parameters
206
231
 
207
232
  - Prefer authoring theme styles as SCSS over JS styling, except in apps that primarily use JS styling and do not use SCSS.
@@ -2,8 +2,9 @@ import { Theme } from '../theme/types';
2
2
  type ThemeProviderProps = {
3
3
  theme?: Theme;
4
4
  children?: React.ReactNode;
5
- precedence?: string;
5
+ precedence?: string | false;
6
6
  href?: string;
7
+ layered?: boolean;
7
8
  };
8
- export declare function ThemeProvider({ theme, children, precedence, href, }: ThemeProviderProps): import("react").JSX.Element;
9
+ export declare function ThemeProvider({ theme, children, precedence, href, layered, }: ThemeProviderProps): import("react").JSX.Element;
9
10
  export {};
@@ -1,11 +1,14 @@
1
1
  import { themeBuilder as e } from "../theme/theme.esm.js";
2
2
  import { Fragment as t, jsx as n, jsxs as r } from "react/jsx-runtime";
3
3
  //#region src/styles/components/ThemeProvider.tsx
4
- function i({ theme: i, children: a, precedence: o = "high", href: s = "stamcat-craftsman-theme-provider" }) {
4
+ function i({ theme: i, children: a, precedence: o = "high", href: s = "stamcat-craftsman-theme-provider", layered: c = !0 }) {
5
+ let l = e(i || {}, { layered: c });
5
6
  return /* @__PURE__ */ r(t, { children: [/* @__PURE__ */ n("style", {
6
- precedence: o,
7
- href: s,
8
- dangerouslySetInnerHTML: { __html: e(i || {}) }
7
+ ...o === !1 ? {} : {
8
+ precedence: o,
9
+ href: s
10
+ },
11
+ dangerouslySetInnerHTML: { __html: l }
9
12
  }), a] });
10
13
  }
11
14
  //#endregion
@@ -1,2 +1,5 @@
1
1
  import { Theme } from './types';
2
- export declare function themeBuilder(theme: Theme): string;
2
+ export type ThemeBuilderOptions = {
3
+ layered?: boolean;
4
+ };
5
+ export declare function themeBuilder(theme: Theme, options?: ThemeBuilderOptions): string;
@@ -27,18 +27,23 @@ function s(t) {
27
27
  function c(e) {
28
28
  if (!(!e || Object.keys(e).length === 0)) return `:root { ${Object.entries(e).map(([e, t]) => `--w-${e}: ${t}px;`).join(" ")} }`;
29
29
  }
30
- function l(e) {
31
- let n = [
30
+ function l(e, n) {
31
+ let o = n?.layered ?? !0, l = [
32
32
  t(":root", { ...e.colors || {} }),
33
33
  c(e.widths),
34
34
  a(e.root),
35
35
  ...s(e.components)
36
36
  ].filter(Boolean).join("\n");
37
- return [
37
+ return o ? [
38
38
  `:root { ${i} ${r} }`,
39
39
  "@layer craftsman-base, craftsman-theme;",
40
40
  "@layer craftsman-theme {",
41
- n,
41
+ l,
42
+ "}"
43
+ ].filter(Boolean).join("\n") : [
44
+ `:root { ${i} ${r} }`,
45
+ "@layer craftsman-theme {",
46
+ l,
42
47
  "}"
43
48
  ].filter(Boolean).join("\n");
44
49
  }