@growth-labs/cms 0.5.26 → 0.5.27

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.
Files changed (59) hide show
  1. package/dist/ui/client/mount.d.ts +1 -0
  2. package/dist/ui/client/mount.d.ts.map +1 -1
  3. package/dist/ui/client/mount.js +1 -0
  4. package/dist/ui/client/mount.js.map +1 -1
  5. package/dist/ui/components/CmsApp.js +2 -11
  6. package/dist/ui/components/CmsApp.js.map +1 -1
  7. package/dist/ui/components/Sidebar.d.ts.map +1 -1
  8. package/dist/ui/components/Sidebar.js +2 -2
  9. package/dist/ui/components/Sidebar.js.map +1 -1
  10. package/dist/ui/components/Topbar.d.ts.map +1 -1
  11. package/dist/ui/components/Topbar.js +1 -10
  12. package/dist/ui/components/Topbar.js.map +1 -1
  13. package/dist/ui/editor/ContentForm.d.ts.map +1 -1
  14. package/dist/ui/editor/ContentForm.js +7 -8
  15. package/dist/ui/editor/ContentForm.js.map +1 -1
  16. package/dist/ui/editor/Rte.js +3 -3
  17. package/dist/ui/editor/Rte.js.map +1 -1
  18. package/dist/ui/inspector/FoundryTab.js +1 -1
  19. package/dist/ui/inspector/FoundryTab.js.map +1 -1
  20. package/dist/ui/pages/admin.astro +1 -1
  21. package/dist/ui/screens/AuthorsScreen.js +1 -1
  22. package/dist/ui/screens/ContentInsightsScreen.js +1 -1
  23. package/dist/ui/screens/ContentInsightsScreen.js.map +1 -1
  24. package/dist/ui/screens/EditorScreen.d.ts +3 -0
  25. package/dist/ui/screens/EditorScreen.d.ts.map +1 -1
  26. package/dist/ui/screens/EditorScreen.js +15 -9
  27. package/dist/ui/screens/EditorScreen.js.map +1 -1
  28. package/dist/ui/screens/LibraryScreen.js +2 -2
  29. package/dist/ui/screens/LibraryScreen.js.map +1 -1
  30. package/dist/ui/screens/SettingsScreen.js +1 -1
  31. package/dist/ui/screens/SubscriptionsScreen.js +2 -2
  32. package/dist/ui/styles/broadsheet.css +131 -156
  33. package/dist/ui/styles/growth-labs-tokens.css +149 -0
  34. package/dist/ui/theme.d.ts +7 -4
  35. package/dist/ui/theme.d.ts.map +1 -1
  36. package/dist/ui/theme.js +24 -65
  37. package/dist/ui/theme.js.map +1 -1
  38. package/dist/ui/use-tweaks.d.ts.map +1 -1
  39. package/dist/ui/use-tweaks.js +2 -1
  40. package/dist/ui/use-tweaks.js.map +1 -1
  41. package/package.json +1 -1
  42. package/src/ui/client/mount.tsx +1 -0
  43. package/src/ui/components/CmsApp.tsx +3 -20
  44. package/src/ui/components/Sidebar.tsx +5 -11
  45. package/src/ui/components/Topbar.tsx +2 -13
  46. package/src/ui/editor/ContentForm.tsx +7 -8
  47. package/src/ui/editor/Rte.tsx +3 -3
  48. package/src/ui/inspector/FoundryTab.tsx +1 -1
  49. package/src/ui/pages/admin.astro +1 -1
  50. package/src/ui/screens/AuthorsScreen.tsx +1 -1
  51. package/src/ui/screens/ContentInsightsScreen.tsx +1 -1
  52. package/src/ui/screens/EditorScreen.tsx +17 -9
  53. package/src/ui/screens/LibraryScreen.tsx +5 -2
  54. package/src/ui/screens/SettingsScreen.tsx +1 -1
  55. package/src/ui/screens/SubscriptionsScreen.tsx +2 -2
  56. package/src/ui/styles/broadsheet.css +131 -156
  57. package/src/ui/styles/growth-labs-tokens.css +149 -0
  58. package/src/ui/theme.ts +29 -68
  59. package/src/ui/use-tweaks.ts +2 -1
package/dist/ui/theme.js CHANGED
@@ -1,81 +1,40 @@
1
- // src/ui/theme.ts theme tokens ported from the resolved Broadsheet design
2
- // (app.jsx). The accent/serif vars are applied to documentElement at runtime by
3
- // the useTweaks effect; broadsheet.css carries the rest.
1
+ // Compatibility helpers for the fixed Growth Labs visual contract. Theme and
2
+ // density remain user preferences; brand accent and typography do not.
4
3
  export const ACCENTS = {
5
- 'Ink blue': {
6
- a: '#0c4a6e',
7
- s: '#075985',
8
- fg: '#ffffff',
9
- tint: 'rgba(12,74,110,0.09)',
10
- ring: 'rgba(12,74,110,0.38)',
11
- },
12
- 'Press red': {
13
- a: '#b23a2e',
14
- s: '#962f25',
15
- fg: '#ffffff',
16
- tint: 'rgba(178,58,46,0.10)',
17
- ring: 'rgba(178,58,46,0.38)',
18
- },
19
- Forest: {
20
- a: '#1f6b4a',
21
- s: '#19583d',
22
- fg: '#ffffff',
23
- tint: 'rgba(31,107,74,0.10)',
24
- ring: 'rgba(31,107,74,0.38)',
25
- },
26
- Violet: {
27
- a: '#5b4bc4',
28
- s: '#4c3ea8',
29
- fg: '#ffffff',
30
- tint: 'rgba(91,75,196,0.10)',
31
- ring: 'rgba(91,75,196,0.38)',
4
+ 'Growth Labs': {
5
+ a: '#2F6FBD',
6
+ s: '#245CA8',
7
+ fg: '#FFFFFF',
8
+ tint: 'rgba(62,209,198,0.14)',
9
+ ring: '#1E5EA8',
32
10
  },
33
11
  };
34
12
  export const ACCENTS_DARK = {
35
- 'Ink blue': {
36
- a: '#4c9ae8',
37
- s: '#3b86d4',
38
- fg: '#06121d',
39
- tint: 'rgba(76,154,232,0.16)',
40
- ring: 'rgba(76,154,232,0.45)',
41
- },
42
- 'Press red': {
43
- a: '#ef6e62',
44
- s: '#e05348',
45
- fg: '#1d0a08',
46
- tint: 'rgba(239,110,98,0.16)',
47
- ring: 'rgba(239,110,98,0.45)',
48
- },
49
- Forest: {
50
- a: '#4ec98a',
51
- s: '#3bb476',
52
- fg: '#06160f',
53
- tint: 'rgba(78,201,138,0.16)',
54
- ring: 'rgba(78,201,138,0.45)',
55
- },
56
- Violet: {
57
- a: '#9d8df0',
58
- s: '#8978e6',
59
- fg: '#0e0a1d',
60
- tint: 'rgba(157,141,240,0.16)',
61
- ring: 'rgba(157,141,240,0.45)',
13
+ 'Growth Labs': {
14
+ a: '#3F86D8',
15
+ s: '#2F6FBD',
16
+ fg: '#FFFFFF',
17
+ tint: 'rgba(62,209,198,0.18)',
18
+ ring: '#50F5EC',
62
19
  },
63
20
  };
64
21
  export const TWEAK_DEFAULTS = {
65
- theme: 'dark',
66
- accent: 'Ink blue',
22
+ theme: 'light',
23
+ accent: 'Growth Labs',
67
24
  density: 'regular',
68
25
  previewPos: 'off',
69
- serifDisplay: true,
26
+ serifDisplay: false,
70
27
  };
71
- const SERIF = '"Source Serif 4", Georgia, serif';
72
- const SANS = '"DM Sans", system-ui, sans-serif';
73
- export function serifVar(serifDisplay) {
74
- return serifDisplay ? SERIF : SANS;
28
+ const DISPLAY = '"Space Grotesk", "Lato", system-ui, sans-serif';
29
+ export function serifVar(_serifDisplay) {
30
+ return DISPLAY;
31
+ }
32
+ export function inverseTextVar(theme) {
33
+ return theme === 'dark' ? '#2B2F33' : '#FFFFFF';
75
34
  }
76
35
  export function resolveAccentVars(theme, accent) {
77
36
  const table = theme === 'dark' ? ACCENTS_DARK : ACCENTS;
78
- const set = table[accent] ?? table['Ink blue'];
37
+ const set = table[accent] ?? table['Growth Labs'];
79
38
  return {
80
39
  '--accent': set.a,
81
40
  '--accent-strong': set.s,
@@ -1 +1 @@
1
- {"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/ui/theme.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,gFAAgF;AAChF,yDAAyD;AAWzD,MAAM,CAAC,MAAM,OAAO,GAAkC;IACrD,UAAU,EAAE;QACX,CAAC,EAAE,SAAS;QACZ,CAAC,EAAE,SAAS;QACZ,EAAE,EAAE,SAAS;QACb,IAAI,EAAE,sBAAsB;QAC5B,IAAI,EAAE,sBAAsB;KAC5B;IACD,WAAW,EAAE;QACZ,CAAC,EAAE,SAAS;QACZ,CAAC,EAAE,SAAS;QACZ,EAAE,EAAE,SAAS;QACb,IAAI,EAAE,sBAAsB;QAC5B,IAAI,EAAE,sBAAsB;KAC5B;IACD,MAAM,EAAE;QACP,CAAC,EAAE,SAAS;QACZ,CAAC,EAAE,SAAS;QACZ,EAAE,EAAE,SAAS;QACb,IAAI,EAAE,sBAAsB;QAC5B,IAAI,EAAE,sBAAsB;KAC5B;IACD,MAAM,EAAE;QACP,CAAC,EAAE,SAAS;QACZ,CAAC,EAAE,SAAS;QACZ,EAAE,EAAE,SAAS;QACb,IAAI,EAAE,sBAAsB;QAC5B,IAAI,EAAE,sBAAsB;KAC5B;CACD,CAAA;AACD,MAAM,CAAC,MAAM,YAAY,GAAkC;IAC1D,UAAU,EAAE;QACX,CAAC,EAAE,SAAS;QACZ,CAAC,EAAE,SAAS;QACZ,EAAE,EAAE,SAAS;QACb,IAAI,EAAE,uBAAuB;QAC7B,IAAI,EAAE,uBAAuB;KAC7B;IACD,WAAW,EAAE;QACZ,CAAC,EAAE,SAAS;QACZ,CAAC,EAAE,SAAS;QACZ,EAAE,EAAE,SAAS;QACb,IAAI,EAAE,uBAAuB;QAC7B,IAAI,EAAE,uBAAuB;KAC7B;IACD,MAAM,EAAE;QACP,CAAC,EAAE,SAAS;QACZ,CAAC,EAAE,SAAS;QACZ,EAAE,EAAE,SAAS;QACb,IAAI,EAAE,uBAAuB;QAC7B,IAAI,EAAE,uBAAuB;KAC7B;IACD,MAAM,EAAE;QACP,CAAC,EAAE,SAAS;QACZ,CAAC,EAAE,SAAS;QACZ,EAAE,EAAE,SAAS;QACb,IAAI,EAAE,wBAAwB;QAC9B,IAAI,EAAE,wBAAwB;KAC9B;CACD,CAAA;AAMD,MAAM,CAAC,MAAM,cAAc,GAAG;IAC7B,KAAK,EAAE,MAAmB;IAC1B,MAAM,EAAE,UAAwB;IAChC,OAAO,EAAE,SAAoB;IAC7B,UAAU,EAAE,KAAmB;IAC/B,YAAY,EAAE,IAAI;CAClB,CAAA;AAED,MAAM,KAAK,GAAG,kCAAkC,CAAA;AAChD,MAAM,IAAI,GAAG,kCAAkC,CAAA;AAE/C,MAAM,UAAU,QAAQ,CAAC,YAAqB;IAC7C,OAAO,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;AACnC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAgB,EAAE,MAAkB;IACrE,MAAM,KAAK,GAAG,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAA;IACvD,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,CAAA;IAC9C,OAAO;QACN,UAAU,EAAE,GAAG,CAAC,CAAC;QACjB,iBAAiB,EAAE,GAAG,CAAC,CAAC;QACxB,aAAa,EAAE,GAAG,CAAC,EAAE;QACrB,eAAe,EAAE,GAAG,CAAC,IAAI;QACzB,eAAe,EAAE,GAAG,CAAC,IAAI;KACzB,CAAA;AACF,CAAC"}
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/ui/theme.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,uEAAuE;AAYvE,MAAM,CAAC,MAAM,OAAO,GAAuC;IAC1D,aAAa,EAAE;QACd,CAAC,EAAE,SAAS;QACZ,CAAC,EAAE,SAAS;QACZ,EAAE,EAAE,SAAS;QACb,IAAI,EAAE,uBAAuB;QAC7B,IAAI,EAAE,SAAS;KACf;CACD,CAAA;AACD,MAAM,CAAC,MAAM,YAAY,GAAuC;IAC/D,aAAa,EAAE;QACd,CAAC,EAAE,SAAS;QACZ,CAAC,EAAE,SAAS;QACZ,EAAE,EAAE,SAAS;QACb,IAAI,EAAE,uBAAuB;QAC7B,IAAI,EAAE,SAAS;KACf;CACD,CAAA;AAMD,MAAM,CAAC,MAAM,cAAc,GAAG;IAC7B,KAAK,EAAE,OAAoB;IAC3B,MAAM,EAAE,aAA2B;IACnC,OAAO,EAAE,SAAoB;IAC7B,UAAU,EAAE,KAAmB;IAC/B,YAAY,EAAE,KAAK;CACnB,CAAA;AAED,MAAM,OAAO,GAAG,gDAAgD,CAAA;AAEhE,MAAM,UAAU,QAAQ,CAAC,aAAsB;IAC9C,OAAO,OAAO,CAAA;AACf,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAgB;IAC9C,OAAO,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAA;AAChD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAgB,EAAE,MAAkB;IACrE,MAAM,KAAK,GAAG,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAA;IACvD,MAAM,GAAG,GAAG,KAAK,CAAC,MAAyB,CAAC,IAAI,KAAK,CAAC,aAAa,CAAC,CAAA;IACpE,OAAO;QACN,UAAU,EAAE,GAAG,CAAC,CAAC;QACjB,iBAAiB,EAAE,GAAG,CAAC,CAAC;QACxB,aAAa,EAAE,GAAG,CAAC,EAAE;QACrB,eAAe,EAAE,GAAG,CAAC,IAAI;QACzB,eAAe,EAAE,GAAG,CAAC,IAAI;KACzB,CAAA;AACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-tweaks.d.ts","sourceRoot":"","sources":["../../src/ui/use-tweaks.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsC,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AAEjF,wBAAgB,SAAS,IAAI;IAC5B,CAAC,EAAE,UAAU,CAAA;IACb,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,MAAM,UAAU,CAAC,KAAK,IAAI,CAAA;CAC/F,CAuBA"}
1
+ {"version":3,"file":"use-tweaks.d.ts","sourceRoot":"","sources":["../../src/ui/use-tweaks.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsC,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AAEjF,wBAAgB,SAAS,IAAI;IAC5B,CAAC,EAAE,UAAU,CAAA;IACb,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,MAAM,UAAU,CAAC,KAAK,IAAI,CAAA;CAC/F,CAwBA"}
@@ -1,5 +1,5 @@
1
1
  import { useCallback, useEffect, useState } from 'react';
2
- import { resolveAccentVars, serifVar } from './theme.js';
2
+ import { inverseTextVar, resolveAccentVars, serifVar } from './theme.js';
3
3
  import { applyTweak, loadTweaks, saveTweaks } from './tweaks.js';
4
4
  export function useTweaks() {
5
5
  const [t, setState] = useState(() => typeof localStorage !== 'undefined' ? loadTweaks(localStorage) : {});
@@ -18,6 +18,7 @@ export function useTweaks() {
18
18
  for (const [k, val] of Object.entries(resolveAccentVars(t.theme, t.accent)))
19
19
  root.style.setProperty(k, val);
20
20
  root.style.setProperty('--serif', serifVar(t.serifDisplay));
21
+ root.style.setProperty('--text-on-inverse', inverseTextVar(t.theme));
21
22
  }, [t.theme, t.density, t.accent, t.serifDisplay]);
22
23
  return { t, setTweak };
23
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"use-tweaks.js","sourceRoot":"","sources":["../../src/ui/use-tweaks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAmB,MAAM,aAAa,CAAA;AAEjF,MAAM,UAAU,SAAS;IAIxB,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAa,GAAG,EAAE,CAC/C,OAAO,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAE,EAAiB,CACnF,CAAA;IACD,MAAM,QAAQ,GAAG,WAAW,CAC3B,CAAC,CAAyC,EAAE,CAAgC,EAAE,EAAE;QAC/E,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE;YACjB,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YACnC,IAAI,OAAO,YAAY,KAAK,WAAW;gBAAE,UAAU,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;YACvE,OAAO,IAAI,CAAA;QACZ,CAAC,CAAC,CAAA;IACH,CAAC,EACD,EAAE,CACF,CAAA;IACD,SAAS,CAAC,GAAG,EAAE;QACd,MAAM,IAAI,GAAG,QAAQ,CAAC,eAAe,CAAA;QACrC,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAA;QACxC,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,CAAA;QAC5C,KAAK,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;YAC1E,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;QAC/B,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAA;IAC5D,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAA;IAClD,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAA;AACvB,CAAC"}
1
+ {"version":3,"file":"use-tweaks.js","sourceRoot":"","sources":["../../src/ui/use-tweaks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACxD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACxE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAmB,MAAM,aAAa,CAAA;AAEjF,MAAM,UAAU,SAAS;IAIxB,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAa,GAAG,EAAE,CAC/C,OAAO,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAE,EAAiB,CACnF,CAAA;IACD,MAAM,QAAQ,GAAG,WAAW,CAC3B,CAAC,CAAyC,EAAE,CAAgC,EAAE,EAAE;QAC/E,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE;YACjB,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YACnC,IAAI,OAAO,YAAY,KAAK,WAAW;gBAAE,UAAU,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;YACvE,OAAO,IAAI,CAAA;QACZ,CAAC,CAAC,CAAA;IACH,CAAC,EACD,EAAE,CACF,CAAA;IACD,SAAS,CAAC,GAAG,EAAE;QACd,MAAM,IAAI,GAAG,QAAQ,CAAC,eAAe,CAAA;QACrC,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAA;QACxC,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,CAAA;QAC5C,KAAK,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;YAC1E,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;QAC/B,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAA;QAC3D,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,mBAAmB,EAAE,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;IACrE,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAA;IAClD,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAA;AACvB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@growth-labs/cms",
3
- "version": "0.5.26",
3
+ "version": "0.5.27",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "growth-labs-cms-migrations": "./dist/cli/migrations.js"
@@ -5,6 +5,7 @@ import { CmsApp } from '../components/CmsApp.js'
5
5
  import { createCmsScreens } from '../screens/registry.js'
6
6
  import { initialWorkspaceState } from '../workspace-context.js'
7
7
  import { type MeResponseSummary, resolveBootState } from './boot-state.js'
8
+ import '../styles/growth-labs-tokens.css'
8
9
  import '../styles/broadsheet.css'
9
10
 
10
11
  async function fetchMe(base: string): Promise<MeResponseSummary | null> {
@@ -99,11 +99,7 @@ export function resolveScreenForAccess(
99
99
  }
100
100
 
101
101
  function EmptyRoute({ route }: { route: Route }) {
102
- return (
103
- <div className="page" style={{ padding: 40, color: 'var(--ink-muted)' }}>
104
- The &quot;{route}&quot; screen mounts here.
105
- </div>
106
- )
102
+ return <div className="page shell-state">The &quot;{route}&quot; screen mounts here.</div>
107
103
  }
108
104
 
109
105
  // Render the active screen as a real child of the error boundary. The registry
@@ -135,26 +131,13 @@ class ScreenErrorBoundary extends Component<
135
131
  render() {
136
132
  if (this.state.error) {
137
133
  return (
138
- <div className="page" style={{ padding: 40 }}>
134
+ <div className="page shell-state">
139
135
  <h1 className="page-title">Something went wrong</h1>
140
136
  <div className="page-sub" style={{ marginTop: 8 }}>
141
137
  The “{this.props.route}” screen hit an error and couldn’t render. The rest of the CMS is
142
138
  unaffected — use the sidebar to navigate elsewhere.
143
139
  </div>
144
- <pre
145
- style={{
146
- marginTop: 16,
147
- padding: 12,
148
- fontSize: 12,
149
- color: 'var(--red)',
150
- whiteSpace: 'pre-wrap',
151
- wordBreak: 'break-word',
152
- background: 'var(--surface-sunken, rgba(0,0,0,0.04))',
153
- borderRadius: 6,
154
- }}
155
- >
156
- {this.state.error.message}
157
- </pre>
140
+ <pre className="shell-error-detail">{this.state.error.message}</pre>
158
141
  <button
159
142
  type="button"
160
143
  className="btn sm"
@@ -1,6 +1,6 @@
1
1
  import type { Route } from '../hash-router.js'
2
2
  import type { IconName } from '../icons.js'
3
- import { BrandMark, Icon } from '../icons.js'
3
+ import { Icon } from '../icons.js'
4
4
  import { navItems } from '../nav.js'
5
5
  import { useWorkspace } from '../workspace-context.js'
6
6
  import { SiteSwitcher } from './SiteSwitcher.js'
@@ -21,16 +21,10 @@ export function Sidebar(props: {
21
21
 
22
22
  return (
23
23
  <aside className="sidebar" aria-label="Main navigation" data-collapsed={props.collapsed}>
24
- {/* Brand block mark + serif wordmark with accent period */}
24
+ {/* Growth Labs gradient mark + Masthead wordmark. */}
25
25
  <div className="sb-brand">
26
- <div className="sb-mark">
27
- <BrandMark size={18} color="#fff" />
28
- </div>
29
- {!props.collapsed && (
30
- <div className="sb-wordmark">
31
- Masthead<span className="dot">.</span>
32
- </div>
33
- )}
26
+ <div className="sb-mark" aria-hidden="true" />
27
+ {!props.collapsed && <div className="sb-wordmark">Masthead</div>}
34
28
  </div>
35
29
 
36
30
  {/* Workspace switcher */}
@@ -64,7 +58,7 @@ export function Sidebar(props: {
64
58
  {/* Current-user footer */}
65
59
  <div className="sb-foot">
66
60
  <div className="sb-user">
67
- <div className="avatar" style={{ background: 'var(--accent)' }}>
61
+ <div className="avatar" style={{ background: 'var(--surface-inverse)' }}>
68
62
  {initial}
69
63
  </div>
70
64
  {!props.collapsed && (
@@ -67,22 +67,11 @@ export function Topbar(props: {
67
67
  style={{ position: 'relative' }}
68
68
  >
69
69
  <Icon name="bell" size={17} />
70
- <span
71
- style={{
72
- position: 'absolute',
73
- top: 7,
74
- right: 8,
75
- width: 7,
76
- height: 7,
77
- borderRadius: '50%',
78
- background: 'var(--red)',
79
- border: '1.5px solid var(--bg)',
80
- }}
81
- />
70
+ <span className="notification-dot" />
82
71
  </button>
83
72
 
84
73
  {/* Divider */}
85
- <div style={{ width: 1, height: 22, background: 'var(--border)', margin: '0 4px' }} />
74
+ <div className="topbar-divider" />
86
75
 
87
76
  {/* New content quick-create */}
88
77
  <button type="button" className="btn primary sm" onClick={props.onCommand}>
@@ -807,7 +807,7 @@ export function ContentForm({
807
807
  }
808
808
 
809
809
  return (
810
- <div style={formWrap}>
810
+ <div className="editor-document" style={formWrap}>
811
811
  {/* Autosave indicator + AI assist toggle */}
812
812
  <div style={saveIndicator}>
813
813
  <span
@@ -1567,7 +1567,6 @@ const formWrap: React.CSSProperties = {
1567
1567
  display: 'flex',
1568
1568
  flexDirection: 'column',
1569
1569
  gap: 0,
1570
- padding: '16px 24px',
1571
1570
  flex: 1,
1572
1571
  overflowY: 'auto',
1573
1572
  }
@@ -1589,11 +1588,11 @@ const titleInput: React.CSSProperties = {
1589
1588
  width: '100%',
1590
1589
  border: 0,
1591
1590
  background: 'transparent',
1592
- fontFamily: 'var(--serif)',
1591
+ fontFamily: 'var(--font-display)',
1593
1592
  fontWeight: 600,
1594
- fontSize: 36,
1595
- letterSpacing: '-0.025em',
1596
- lineHeight: 1.08,
1593
+ fontSize: 34,
1594
+ letterSpacing: '-0.02em',
1595
+ lineHeight: 1.15,
1597
1596
  color: 'var(--ink)',
1598
1597
  padding: 0,
1599
1598
  outline: 'none',
@@ -1603,8 +1602,8 @@ const dekInput: React.CSSProperties = {
1603
1602
  width: '100%',
1604
1603
  border: 0,
1605
1604
  background: 'transparent',
1606
- fontFamily: 'var(--serif)',
1607
- fontSize: 19,
1605
+ fontFamily: 'var(--font-body)',
1606
+ fontSize: 17,
1608
1607
  lineHeight: 1.5,
1609
1608
  color: 'var(--ink-soft)',
1610
1609
  padding: 0,
@@ -493,8 +493,8 @@ const contentWrap: React.CSSProperties = {
493
493
  flex: 1,
494
494
  padding: '20px 22px',
495
495
  overflowY: 'auto',
496
- fontFamily: 'var(--serif)',
497
- fontSize: 17,
498
- lineHeight: 1.75,
496
+ fontFamily: 'var(--font-body)',
497
+ fontSize: 15.5,
498
+ lineHeight: 1.65,
499
499
  color: 'var(--ink)',
500
500
  }
@@ -499,7 +499,7 @@ const progressTrack: React.CSSProperties = {
499
499
  const progressFill: React.CSSProperties = {
500
500
  width: '100%',
501
501
  height: '100%',
502
- background: 'var(--gold)',
502
+ background: 'var(--accent-primary)',
503
503
  }
504
504
 
505
505
  const errorText: React.CSSProperties = {
@@ -22,7 +22,7 @@ const initial = { workspaces: config.workspaces, activeWorkspaceId: config.activ
22
22
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
23
23
  <link
24
24
  rel="stylesheet"
25
- href="https://fonts.googleapis.com/css2?family=Source+Serif+4:ital,opsz,wght@0,8..60,400;0,8..60,600;0,8..60,700;1,8..60,400&family=DM+Sans:ital,opsz,wght@0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;1,9..40,400&family=DM+Mono:ital,wght@0,400;0,500;1,400&display=swap"
25
+ href="https://fonts.googleapis.com/css2?family=Lato:wght@300;400;700&family=Space+Grotesk:wght@400;500;600;700&display=swap"
26
26
  />
27
27
  </head>
28
28
  <body>
@@ -520,7 +520,7 @@ function initialsFor(name: string): string {
520
520
  return (name.trim().slice(0, 2) || '—').toUpperCase()
521
521
  }
522
522
 
523
- const AVATAR_COLORS = ['#0c4a6e', '#1f6b4a', '#5b4bc4', '#8c6d14', '#075985', '#475569']
523
+ const AVATAR_COLORS = ['#2F6FBD', '#1FA3A8', '#8075ED', '#F7A34B', '#2CA8E0', '#4D4D4D']
524
524
 
525
525
  function avatarColor(seed: string): string {
526
526
  let h = 0
@@ -171,7 +171,7 @@ export function ContentInsightsScreen() {
171
171
  style={{
172
172
  overflow: 'hidden',
173
173
  marginBottom: 'var(--gap)',
174
- borderLeft: `3px solid ${group.lane == null ? 'var(--hairline)' : 'var(--gold)'}`,
174
+ borderLeft: `3px solid ${group.lane == null ? 'var(--hairline)' : 'var(--accent-primary)'}`,
175
175
  }}
176
176
  >
177
177
  <header
@@ -58,12 +58,20 @@ const CONTENT_TYPE_LABELS: Record<ContentType, string> = {
58
58
 
59
59
  const STATUS_PILL_COLORS: Record<ContentStatus, string> = {
60
60
  draft: 'var(--ink-faint)',
61
- review: '#a78bfa',
62
- scheduled: '#60a5fa',
63
- published: '#34d399',
61
+ review: 'var(--amber)',
62
+ scheduled: 'var(--accent)',
63
+ published: 'var(--green)',
64
64
  archived: 'var(--ink-faint)',
65
65
  }
66
66
 
67
+ export function editorStatusColor(status: ContentStatus): string {
68
+ return STATUS_PILL_COLORS[status]
69
+ }
70
+
71
+ export function editorStatusBackground(status: ContentStatus): string {
72
+ return `color-mix(in srgb, ${editorStatusColor(status)} 14%, transparent)`
73
+ }
74
+
67
75
  // ---------------------------------------------------------------------------
68
76
  // EditorScreen
69
77
  // ---------------------------------------------------------------------------
@@ -503,8 +511,8 @@ function statusPill(status: ContentStatus): React.CSSProperties {
503
511
  fontWeight: 600,
504
512
  letterSpacing: '0.06em',
505
513
  textTransform: 'uppercase',
506
- background: `${STATUS_PILL_COLORS[status]}22`,
507
- color: STATUS_PILL_COLORS[status],
514
+ background: editorStatusBackground(status),
515
+ color: editorStatusColor(status),
508
516
  flexShrink: 0,
509
517
  }
510
518
  }
@@ -526,10 +534,10 @@ const headerBar: React.CSSProperties = {
526
534
  display: 'flex',
527
535
  alignItems: 'center',
528
536
  justifyContent: 'space-between',
529
- height: 48,
530
- padding: '0 16px',
537
+ height: 58,
538
+ padding: '0 20px',
531
539
  borderBottom: '1px solid var(--border)',
532
- background: 'var(--panel)',
540
+ background: 'var(--surface-raised-nav)',
533
541
  flexShrink: 0,
534
542
  gap: 12,
535
543
  }
@@ -661,7 +669,7 @@ const formArea: React.CSSProperties = {
661
669
  }
662
670
 
663
671
  const inspectorSlot: React.CSSProperties = {
664
- flex: '0 0 340px',
672
+ flex: '0 0 296px',
665
673
  borderLeft: '1px solid var(--border)',
666
674
  display: 'flex',
667
675
  flexDirection: 'column',
@@ -753,7 +753,10 @@ function ListRow({
753
753
  >
754
754
  {row.title || '(Untitled)'}
755
755
  {row.featured && (
756
- <span title="Premium" style={{ color: 'var(--gold)', flex: 'none' }}>
756
+ <span
757
+ title="Premium"
758
+ style={{ color: 'var(--accent-primary-strong)', flex: 'none' }}
759
+ >
757
760
  <Icon name="star" size={13} />
758
761
  </span>
759
762
  )}
@@ -1064,7 +1067,7 @@ function BoardCard({
1064
1067
  {row.updatedAt ? formatDate(row.updatedAt) : (row.authorName ?? '—')}
1065
1068
  </span>
1066
1069
  {row.featured && (
1067
- <span style={{ marginLeft: 'auto', color: 'var(--gold)' }}>
1070
+ <span style={{ marginLeft: 'auto', color: 'var(--accent-primary-strong)' }}>
1068
1071
  <Icon name="star" size={12} />
1069
1072
  </span>
1070
1073
  )}
@@ -375,7 +375,7 @@ function GeneralSettings({
375
375
  // Branding settings
376
376
  // ---------------------------------------------------------------------------
377
377
 
378
- const ACCENT_PRESETS = ['#0c4a6e', '#b23a2e', '#1f6b4a', '#5b4bc4', '#374151']
378
+ const ACCENT_PRESETS = ['#2F6FBD', '#1FA3A8', '#2CA8E0', '#8075ED', '#F56A61']
379
379
  const TYPEFACE_OPTIONS = ['serif', 'Source Serif 4', 'Spectral', 'Newsreader', 'Inter']
380
380
 
381
381
  function BrandingSettings({
@@ -1310,7 +1310,7 @@ function KpiCard({
1310
1310
  // PlanMixChart — stacked bar + legend rows (aside panel)
1311
1311
  // ---------------------------------------------------------------------------
1312
1312
 
1313
- const PLAN_DOT_COLORS = ['#1f6b4a', '#0c4a6e', '#5b4bc4', '#8c6d14', '#475569']
1313
+ const PLAN_DOT_COLORS = ['#1FA3A8', '#2F6FBD', '#8075ED', '#F7A34B', '#4D4D4D']
1314
1314
 
1315
1315
  function PlanMixChart({
1316
1316
  planMix,
@@ -1746,7 +1746,7 @@ function initialsFor(email: string): string {
1746
1746
  return local.slice(0, 2).toUpperCase()
1747
1747
  }
1748
1748
 
1749
- const AVATAR_COLORS = ['#0c4a6e', '#1f6b4a', '#5b4bc4', '#8c6d14', '#075985', '#475569']
1749
+ const AVATAR_COLORS = ['#2F6FBD', '#1FA3A8', '#8075ED', '#F7A34B', '#2CA8E0', '#4D4D4D']
1750
1750
 
1751
1751
  function avatarColor(seed: string): string {
1752
1752
  let h = 0