@tumbaland/frontend-core 1.14.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/authService.d.ts +10 -0
  2. package/dist/authService.js +18 -3
  3. package/dist/components/AppErrorBoundary/AppErrorBoundary.d.ts +26 -0
  4. package/dist/components/AppErrorBoundary/AppErrorBoundary.js +25 -0
  5. package/dist/components/AppErrorBoundary/index.d.ts +2 -0
  6. package/dist/components/AppErrorBoundary/index.js +1 -0
  7. package/dist/components/AppLayout/AppLayout.d.ts +27 -0
  8. package/dist/components/AppLayout/AppLayout.js +45 -0
  9. package/dist/components/AppLayout/index.d.ts +2 -0
  10. package/dist/components/AppLayout/index.js +1 -0
  11. package/dist/components/AuthHeader/AuthHeader.d.ts +57 -0
  12. package/dist/components/AuthHeader/AuthHeader.js +135 -0
  13. package/dist/components/AuthHeader/index.d.ts +2 -0
  14. package/dist/components/AuthHeader/index.js +1 -0
  15. package/dist/components/ErrorPage/ErrorPage.d.ts +17 -0
  16. package/dist/components/ErrorPage/ErrorPage.js +19 -0
  17. package/dist/components/ErrorPage/index.d.ts +2 -0
  18. package/dist/components/ErrorPage/index.js +1 -0
  19. package/dist/components/Loader/Loader.d.ts +12 -0
  20. package/dist/components/Loader/Loader.js +15 -0
  21. package/dist/components/Loader/index.d.ts +2 -0
  22. package/dist/components/Loader/index.js +1 -0
  23. package/dist/components/LoginButton/LoginButton.d.ts +5 -0
  24. package/dist/components/LoginButton/LoginButton.js +15 -0
  25. package/dist/components/LoginButton/index.d.ts +2 -0
  26. package/dist/components/LoginButton/index.js +1 -0
  27. package/dist/components/NotificationsMenu/NotificationsMenu.d.ts +9 -0
  28. package/dist/components/NotificationsMenu/NotificationsMenu.js +29 -0
  29. package/dist/components/ProtectedRoute/ProtectedRoute.d.ts +33 -0
  30. package/dist/components/ProtectedRoute/ProtectedRoute.js +50 -0
  31. package/dist/components/ProtectedRoute/index.d.ts +2 -0
  32. package/dist/components/ProtectedRoute/index.js +1 -0
  33. package/dist/components/UnauthorizedPage/UnauthorizedPage.d.ts +5 -0
  34. package/dist/components/UnauthorizedPage/UnauthorizedPage.js +9 -0
  35. package/dist/components/UnauthorizedPage/index.d.ts +2 -0
  36. package/dist/components/UnauthorizedPage/index.js +1 -0
  37. package/dist/components/UsageMeter/UsageMeter.d.ts +35 -0
  38. package/dist/components/UsageMeter/UsageMeter.js +50 -0
  39. package/dist/components/UsageMeter/index.d.ts +4 -0
  40. package/dist/components/UsageMeter/index.js +2 -0
  41. package/dist/components/UsageMeter/useEntitlements.d.ts +27 -0
  42. package/dist/components/UsageMeter/useEntitlements.js +56 -0
  43. package/dist/components/tenant/TenantProvider.d.ts +11 -0
  44. package/dist/components/tenant/TenantProvider.js +53 -0
  45. package/dist/components/tenant/TenantSelector.d.ts +24 -0
  46. package/dist/components/tenant/TenantSelector.js +77 -0
  47. package/dist/components/tenant/index.d.ts +5 -0
  48. package/dist/components/tenant/index.js +3 -0
  49. package/dist/components/tenant/useTenant.d.ts +15 -0
  50. package/dist/components/tenant/useTenant.js +222 -0
  51. package/dist/components/tenant/useTenantDataRefresh.d.ts +6 -0
  52. package/dist/components/tenant/useTenantDataRefresh.js +28 -0
  53. package/dist/config/createConfigProvider.d.ts +44 -0
  54. package/dist/config/createConfigProvider.js +92 -0
  55. package/dist/federation.d.ts +46 -0
  56. package/dist/federation.js +37 -0
  57. package/dist/index.d.ts +26 -0
  58. package/dist/index.js +34 -1
  59. package/dist/monitoring/batch.js +3 -3
  60. package/dist/monitoring/config.js +1 -4
  61. package/dist/monitoring/console.js +1 -1
  62. package/dist/plansService.js +1 -1
  63. package/dist/routing/embedContext.d.ts +31 -0
  64. package/dist/routing/embedContext.js +63 -0
  65. package/dist/routing/index.d.ts +12 -0
  66. package/dist/routing/index.js +12 -0
  67. package/dist/sessionStorage.d.ts +1 -1
  68. package/dist/sessionStorage.js +1 -1
  69. package/dist/theme/createTumbalandTheme.d.ts +38 -0
  70. package/dist/theme/createTumbalandTheme.js +245 -0
  71. package/dist/theme/index.d.ts +2 -0
  72. package/dist/theme/index.js +2 -0
  73. package/dist/theme/tokens.d.ts +169 -0
  74. package/dist/theme/tokens.js +162 -0
  75. package/package.json +28 -2
  76. package/dist/test/setup.d.ts +0 -9
  77. package/dist/test/setup.js +0 -26
@@ -0,0 +1,162 @@
1
+ /**
2
+ * One place the look is decided, for all eight fronts.
3
+ *
4
+ * This file used to live in shell-front, which meant the signed-in home page
5
+ * was the only screen that knew what colour Tumbaland is. The other seven
6
+ * frontends fell back to MUI's factory defaults — Roboto and `#1976d2` — and
7
+ * then painted over them with literals, which is how three palettes ended up
8
+ * in the product at once: the pink below, an indigo one in a dozen gradient
9
+ * literals, and a sky-blue one in five copies of `AppLayout`.
10
+ *
11
+ * Naming the palette once, in the package every front already depends on,
12
+ * makes it a knob rather than a search-and-replace.
13
+ *
14
+ * Two pinks, on purpose. `pink` is the identity — bright, and only ever used
15
+ * for gradients and large decorative fills, where its 3.5:1 against white does
16
+ * not matter. `pinkInk` is the one anything readable or clickable uses: the
17
+ * same hue walked down to 4.7:1, which clears WCAG AA as text on white and as
18
+ * a button behind white text. Reaching for `pink` on a label is the mistake
19
+ * this pair exists to prevent.
20
+ */
21
+ /** The accent family. Pink leads; violet is what it resolves into. */
22
+ export const brand = {
23
+ /** Decorative only — gradient start, large fills. Fails AA as text. */
24
+ pink: '#ff1fae',
25
+ /** Decorative — the hover end of the gradient. */
26
+ pinkDeep: '#f01aa2',
27
+ /** The readable pink: text, icons, buttons, anything interactive. AA on white. */
28
+ pinkInk: '#d61f92',
29
+ /** Pressed and hover states for `pinkInk`. */
30
+ pinkInkDeep: '#b3177a',
31
+ magenta: '#c026d3',
32
+ /** Decorative — gradient end. */
33
+ violet: '#8b5cf6',
34
+ violetDeep: '#7c4de8',
35
+ /** The readable violet, for the same reason as `pinkInk`. AA on white. */
36
+ violetInk: '#7c3aed',
37
+ purple: '#9333ea'
38
+ };
39
+ /** Text, darkest to lightest. Slate rather than grey, to sit under the pink. */
40
+ export const ink = {
41
+ strong: '#0f172a',
42
+ body: '#475569',
43
+ // #64748b, the slate this was, reads 4.48:1 on the sunken surface and 4.36:1
44
+ // on the pink top of the page wash — just under AA, on exactly the secondary
45
+ // text that ends up there. Two steps darker clears it on every surface.
46
+ muted: '#5f6d80',
47
+ /** Decorative only — 2.6:1 on white. Never put words a reader needs in this. */
48
+ faint: '#94a3b8'
49
+ };
50
+ /**
51
+ * Page and card backgrounds.
52
+ *
53
+ * `page` replaces the three different radial gradients the AppLayouts each had
54
+ * (two sky-blue, one indigo). It is the pink-to-violet wash, so a module opened
55
+ * inside the shell's iframe sits on the same backdrop as the shell around it —
56
+ * which is what made the seam between them visible before.
57
+ */
58
+ export const surface = {
59
+ page: 'radial-gradient(circle at 50% 0%, #fdf2fa 0%, #f3edff 55%, #fbfcff 100%)',
60
+ default: '#fbf9fd',
61
+ paper: '#ffffff',
62
+ /** Table heads, inset panels, anything one step back from `paper`. */
63
+ sunken: '#faf7fc',
64
+ divider: '#ece7f2'
65
+ };
66
+ export const gradient = {
67
+ brand: `linear-gradient(135deg, ${brand.pink} 0%, ${brand.violet} 100%)`,
68
+ brandHover: `linear-gradient(135deg, ${brand.pinkDeep} 0%, ${brand.violetDeep} 100%)`,
69
+ /** For a large tint behind a section, where the full-strength gradient shouts. */
70
+ wash: `linear-gradient(135deg, ${brand.pink}14 0%, ${brand.violet}14 100%)`
71
+ };
72
+ /**
73
+ * Per-module accent, keyed by the shell's route.
74
+ *
75
+ * These were literals in shell-front's `apps.ts`, and four of the six failed
76
+ * AA against white — Money's `#22c55e` sat at 2.3:1 as the active tab's label,
77
+ * which on a phone in daylight is the one colour that has to read. Same hues,
78
+ * walked down until they clear 4.5:1.
79
+ */
80
+ export const moduleAccent = {
81
+ home: brand.purple,
82
+ journal: '#e11d48',
83
+ album: '#2563eb',
84
+ money: '#15803d',
85
+ profile: ink.strong,
86
+ groups: brand.violetInk,
87
+ billing: '#4f46e5'
88
+ };
89
+ /**
90
+ * The script wordmark, gradient-filled.
91
+ *
92
+ * Used by the landing hero and by the signed-in greeting. It was written out
93
+ * twice with the same eight properties; a single definition is the only reason
94
+ * the two can be trusted to match.
95
+ */
96
+ export const wordmark = {
97
+ fontFamily: '"Pacifico", cursive',
98
+ lineHeight: 1.25,
99
+ letterSpacing: 1,
100
+ background: gradient.brand,
101
+ backgroundClip: 'text',
102
+ WebkitBackgroundClip: 'text',
103
+ WebkitTextFillColor: 'transparent',
104
+ filter: 'drop-shadow(0 4px 8px rgba(0,0,0,0.08))',
105
+ pb: 1
106
+ };
107
+ /**
108
+ * The frosted card both pages are built from.
109
+ *
110
+ * Translucent on purpose: the cloud backdrop shows through, which is what ties
111
+ * a card to the page rather than laying it on top.
112
+ */
113
+ export const glass = {
114
+ borderRadius: 3.5,
115
+ background: 'rgba(255,255,255,0.62)',
116
+ backdropFilter: 'blur(10px)',
117
+ border: '1px solid rgba(255,255,255,0.7)',
118
+ boxShadow: '0 10px 30px -22px rgba(31,38,135,0.5)'
119
+ };
120
+ /** A card that responds to being pointed at. `accent` tints the lifted shadow. */
121
+ export const glassInteractive = (accent = brand.purple) => ({
122
+ ...glass,
123
+ transition: 'transform .2s ease, box-shadow .2s ease',
124
+ '&:hover': {
125
+ transform: 'translateY(-3px)',
126
+ boxShadow: `0 20px 38px -24px ${accent}cc`
127
+ }
128
+ });
129
+ /** The primary call to action, wherever one appears. */
130
+ export const brandButton = {
131
+ textTransform: 'none',
132
+ fontWeight: 600,
133
+ borderRadius: 3,
134
+ background: gradient.brand,
135
+ boxShadow: `0 10px 28px -10px rgba(168,45,190,0.75)`,
136
+ '&:hover': {
137
+ background: gradient.brandHover,
138
+ boxShadow: `0 12px 32px -10px rgba(168,45,190,0.9)`
139
+ }
140
+ };
141
+ /** Vertical rhythm, so sections on both pages breathe identically. */
142
+ export const section = {
143
+ px: 2,
144
+ py: { xs: 5, md: 7 }
145
+ };
146
+ /**
147
+ * The page gutter, as every layout and page should spell it.
148
+ *
149
+ * 16px on a phone is the narrowest that still keeps text off the screen's
150
+ * curved edge; widening it past `sm` is what stops a card looking stranded on
151
+ * a desktop. Pages that hardcoded `p: 3` lost 48px of a 360px screen to
152
+ * nothing.
153
+ */
154
+ export const gutter = { xs: 2, sm: 3 };
155
+ /**
156
+ * Minimum hit area for anything tapped, per the WCAG 2.2 target-size rule and
157
+ * both platform guidelines. MUI's medium button is 36px tall, which is a miss
158
+ * often enough to feel broken on a phone.
159
+ */
160
+ export const TOUCH_TARGET = 44;
161
+ /** Below `sm` — the phone layout. Matches `theme.breakpoints.down('sm')`. */
162
+ export const PHONE = '@media (max-width:599.95px)';
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@tumbaland/frontend-core",
3
- "version": "1.14.0",
4
- "description": "Shared frontend auth/group/API-client logic for Tumbaland frontends",
3
+ "version": "1.15.0",
4
+ "description": "Shared frontend logic, components and theme for Tumbaland frontends",
5
5
  "author": "Tumbaland",
6
6
  "license": "MIT",
7
+ "type": "module",
7
8
  "main": "dist/index.js",
8
9
  "types": "dist/index.d.ts",
9
10
  "files": [
@@ -22,12 +23,37 @@
22
23
  "tagPrefix": "frontend-core-v"
23
24
  },
24
25
  "dependencies": {
26
+ "@mui/icons-material": "^9.4.0",
27
+ "@mui/material": "^9.4.0",
25
28
  "web-vitals": "^6.2.1"
26
29
  },
27
30
  "devDependencies": {
31
+ "@esbuild/linux-x64": "^0.28.2",
32
+ "@rollup/rollup-linux-x64-gnu": "^4.63.3",
33
+ "@testing-library/jest-dom": "^7.0.1",
34
+ "@testing-library/react": "^16.3.3",
35
+ "@testing-library/user-event": "^14.6.7",
28
36
  "@types/node": "^26.5.1",
37
+ "@vitejs/plugin-react": "^6.1.1",
29
38
  "@vitest/coverage-v8": "^4.1.11",
30
39
  "commit-and-tag-version": "^13.2.1",
31
40
  "typescript": "^6.0.3"
41
+ },
42
+ "exports": {
43
+ ".": {
44
+ "types": "./dist/index.d.ts",
45
+ "import": "./dist/index.js",
46
+ "default": "./dist/index.js"
47
+ },
48
+ "./federation": {
49
+ "types": "./dist/federation.d.ts",
50
+ "import": "./dist/federation.js",
51
+ "default": "./dist/federation.js"
52
+ }
53
+ },
54
+ "peerDependencies": {
55
+ "react": "^19.2.7",
56
+ "react-dom": "^19.2.7",
57
+ "react-router": "^8.3.0"
32
58
  }
33
59
  }
@@ -1,9 +0,0 @@
1
- declare class MemoryStorage implements Storage {
2
- private store;
3
- get length(): number;
4
- clear(): void;
5
- getItem(key: string): string | null;
6
- key(index: number): string;
7
- removeItem(key: string): void;
8
- setItem(key: string, value: string): void;
9
- }
@@ -1,26 +0,0 @@
1
- "use strict";
2
- // This jsdom environment doesn't provide a working localStorage (window.localStorage
3
- // is undefined here) — polyfill it with a simple in-memory Storage.
4
- class MemoryStorage {
5
- store = new Map();
6
- get length() {
7
- return this.store.size;
8
- }
9
- clear() {
10
- this.store.clear();
11
- }
12
- getItem(key) {
13
- return this.store.has(key) ? this.store.get(key) : null;
14
- }
15
- key(index) {
16
- return Array.from(this.store.keys())[index] ?? null;
17
- }
18
- removeItem(key) {
19
- this.store.delete(key);
20
- }
21
- setItem(key, value) {
22
- this.store.set(key, String(value));
23
- }
24
- }
25
- Object.defineProperty(globalThis, 'localStorage', { value: new MemoryStorage(), configurable: true });
26
- Object.defineProperty(window, 'localStorage', { value: globalThis.localStorage, configurable: true });