@ttt-productions/theme-core 0.1.1

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/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # @ttt-productions/theme-core
2
+
3
+ Shared theme provider + CSS token contract.
4
+
5
+ ## Install
6
+ ```bash
7
+ npm install @ttt-productions/theme-core
@@ -0,0 +1,3 @@
1
+ export * from "./theme-provider";
2
+ export * from "./required-tokens";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./theme-provider";
2
+ export * from "./required-tokens";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare const REQUIRED_TOKENS: readonly ["--brand-primary", "--brand-secondary", "--brand-accent", "--status-success", "--status-warning", "--status-error", "--neutral-white", "--neutral-black"];
2
+ export type RequiredToken = (typeof REQUIRED_TOKENS)[number];
3
+ //# sourceMappingURL=required-tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"required-tokens.d.ts","sourceRoot":"","sources":["../src/required-tokens.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,qKAWhB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ export const REQUIRED_TOKENS = [
2
+ "--brand-primary",
3
+ "--brand-secondary",
4
+ "--brand-accent",
5
+ "--status-success",
6
+ "--status-warning",
7
+ "--status-error",
8
+ "--neutral-white",
9
+ "--neutral-black"
10
+ ];
11
+ //# sourceMappingURL=required-tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"required-tokens.js","sourceRoot":"","sources":["../src/required-tokens.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG;IAC3B,iBAAiB;IACjB,mBAAmB;IACnB,gBAAgB;IAEhB,kBAAkB;IAClB,kBAAkB;IAClB,gBAAgB;IAEhB,iBAAiB;IACjB,iBAAiB;CACT,CAAC"}
@@ -0,0 +1,11 @@
1
+ @layer base {
2
+ html, body {
3
+ background-color: hsl(var(--background));
4
+ color: hsl(var(--foreground));
5
+ }
6
+
7
+ * {
8
+ border-color: hsl(var(--border));
9
+ }
10
+ }
11
+
@@ -0,0 +1,27 @@
1
+ @layer base {
2
+ :root {
3
+ /* Loud fallbacks: if you see this color, app did not define required brand contract */
4
+ --brand-primary: 999 100% 50%;
5
+ --brand-secondary: 999 100% 50%;
6
+ --brand-accent: 999 100% 50%;
7
+
8
+ --status-success: 999 100% 50%;
9
+ --status-warning: 999 100% 50%;
10
+ --status-error: 999 100% 50%;
11
+
12
+ --neutral-white: 0 0% 100%;
13
+ --neutral-black: 0 0% 0%;
14
+ }
15
+
16
+ /* High contrast must be pure B/W: override brand tokens too (prevents bleed) */
17
+ .high-contrast {
18
+ --brand-primary: 0 0% 0%;
19
+ --brand-secondary: 0 0% 0%;
20
+ --brand-accent: 0 0% 100%;
21
+
22
+ --status-success: 0 0% 0%;
23
+ --status-warning: 0 0% 0%;
24
+ --status-error: 0 0% 0%;
25
+ }
26
+ }
27
+
@@ -0,0 +1,3 @@
1
+ @import "./contract.css";
2
+ @import "./tokens.css";
3
+ @import "./base.css";
@@ -0,0 +1,82 @@
1
+ @layer base {
2
+ :root {
3
+ /* Semantic tokens (default = light) */
4
+ --background: var(--neutral-white);
5
+ --foreground: var(--neutral-black);
6
+
7
+ --card: var(--neutral-white);
8
+ --card-foreground: var(--neutral-black);
9
+
10
+ --popover: var(--neutral-white);
11
+ --popover-foreground: var(--neutral-black);
12
+
13
+ --muted: 0 0% 95%;
14
+ --muted-foreground: var(--neutral-black);
15
+
16
+ --accent: var(--brand-accent);
17
+ --accent-foreground: var(--neutral-black);
18
+
19
+ --primary: var(--brand-primary);
20
+ --primary-foreground: var(--neutral-white);
21
+
22
+ --secondary: var(--brand-secondary);
23
+ --secondary-foreground: var(--neutral-white);
24
+
25
+ --destructive: var(--status-error);
26
+ --destructive-foreground: var(--neutral-white);
27
+
28
+ --border: var(--brand-primary);
29
+ --ring: var(--brand-primary);
30
+
31
+ --radius: 1rem;
32
+ }
33
+
34
+ .dark {
35
+ /* Keep semantic token mapping; apps can override brand tokens per-mode if they want */
36
+ --background: 240 6% 10%;
37
+ --foreground: 0 0% 100%;
38
+
39
+ --card: 240 6% 12%;
40
+ --card-foreground: 0 0% 100%;
41
+
42
+ --popover: 240 6% 12%;
43
+ --popover-foreground: 0 0% 100%;
44
+
45
+ --muted: 240 4% 20%;
46
+ --muted-foreground: 0 0% 100%;
47
+
48
+ --border: 0 0% 100%;
49
+ --ring: 0 0% 100%;
50
+ }
51
+
52
+ .high-contrast {
53
+ /* You already had this approach in master-app and it’s correct: pure B/W semantic tokens */
54
+ --background: 0 0% 0%;
55
+ --foreground: 0 0% 100%;
56
+
57
+ --card: 0 0% 0%;
58
+ --card-foreground: 0 0% 100%;
59
+
60
+ --popover: 0 0% 0%;
61
+ --popover-foreground: 0 0% 100%;
62
+
63
+ --muted: 0 0% 0%;
64
+ --muted-foreground: 0 0% 100%;
65
+
66
+ --accent: 0 0% 0%;
67
+ --accent-foreground: 0 0% 100%;
68
+
69
+ --primary: 0 0% 100%;
70
+ --primary-foreground: 0 0% 0%;
71
+
72
+ --secondary: 0 0% 100%;
73
+ --secondary-foreground: 0 0% 0%;
74
+
75
+ --destructive: 0 0% 100%;
76
+ --destructive-foreground: 0 0% 0%;
77
+
78
+ --border: 0 0% 100%;
79
+ --ring: 0 0% 100%;
80
+ }
81
+ }
82
+
@@ -0,0 +1,5 @@
1
+ import * as React from "react";
2
+ export declare function ThemeProvider({ children }: {
3
+ children: React.ReactNode;
4
+ }): import("react/jsx-runtime").JSX.Element;
5
+ //# sourceMappingURL=theme-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-provider.d.ts","sourceRoot":"","sources":["../src/theme-provider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAuB/B,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,2CAexE"}
@@ -0,0 +1,28 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { ThemeProvider as NextThemesProvider } from "next-themes";
5
+ import { REQUIRED_TOKENS } from "./required-tokens";
6
+ function warnMissingTokens() {
7
+ if (typeof window === "undefined")
8
+ return;
9
+ const root = document.documentElement;
10
+ const styles = getComputedStyle(root);
11
+ const missing = REQUIRED_TOKENS.filter((t) => styles.getPropertyValue(t).trim() === "");
12
+ const loud = REQUIRED_TOKENS.filter((t) => styles.getPropertyValue(t).includes("999 100% 50%"));
13
+ if (missing.length || loud.length) {
14
+ // eslint-disable-next-line no-console
15
+ console.warn(`[theme-core] Missing/invalid required theme tokens.\n` +
16
+ (missing.length ? `Missing: ${missing.join(", ")}\n` : "") +
17
+ (loud.length ? `Still using loud fallbacks: ${loud.join(", ")}\n` : "") +
18
+ `Define these in the consuming app (brand contract).`);
19
+ }
20
+ }
21
+ export function ThemeProvider({ children }) {
22
+ React.useEffect(() => {
23
+ if (process.env.NODE_ENV !== "production")
24
+ warnMissingTokens();
25
+ }, []);
26
+ return (_jsx(NextThemesProvider, { attribute: "class", defaultTheme: "system", enableSystem: true, themes: ["light", "dark", "high-contrast"], children: children }));
27
+ }
28
+ //# sourceMappingURL=theme-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-provider.js","sourceRoot":"","sources":["../src/theme-provider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,aAAa,IAAI,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,SAAS,iBAAiB;IACxB,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO;IAC1C,MAAM,IAAI,GAAG,QAAQ,CAAC,eAAe,CAAC;IACtC,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAEtC,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACxF,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;IAEhG,IAAI,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAClC,sCAAsC;QACtC,OAAO,CAAC,IAAI,CACV,uDAAuD;YACrD,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,+BAA+B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACvE,qDAAqD,CACxD,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAAE,QAAQ,EAAiC;IACvE,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY;YAAE,iBAAiB,EAAE,CAAC;IACjE,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,CACL,KAAC,kBAAkB,IACjB,SAAS,EAAC,OAAO,EACjB,YAAY,EAAC,QAAQ,EACrB,YAAY,QACZ,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,CAAC,YAEzC,QAAQ,GACU,CACtB,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@ttt-productions/theme-core",
3
+ "version": "0.1.1",
4
+ "description": "Theme provider + CSS token contract for TTT Productions apps",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./styles.css": "./dist/styles/index.css"
17
+ },
18
+ "scripts": {
19
+ "build": "tsc && rm -rf dist/styles && mkdir -p dist/styles && cp -R src/styles/* dist/styles/",
20
+ "clean": "rm -rf dist *.tsbuildinfo",
21
+ "typecheck": "tsc --noEmit",
22
+ "prepublishOnly": "npm run clean && npm run build"
23
+ },
24
+ "peerDependencies": {
25
+ "react": "^19.0.0",
26
+ "react-dom": "^19.0.0"
27
+ },
28
+ "dependencies": {
29
+ "next-themes": "^0.4.6"
30
+ },
31
+ "devDependencies": {
32
+ "@types/react": "^19.0.0",
33
+ "@types/react-dom": "^19.0.0",
34
+ "react": "^19.2.0",
35
+ "react-dom": "^19.2.0",
36
+ "typescript": "^5.8.3"
37
+ },
38
+ "author": "DJ (TTT Productions)",
39
+ "license": "MIT",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://github.com/ttt-productions/ttt-packages.git",
43
+ "directory": "packages/theme-core"
44
+ }
45
+ }