@fonderie/react-admin-screens 0.7.0 → 1.0.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.
package/dist/index.cjs CHANGED
@@ -25,8 +25,8 @@ __export(index_exports, {
25
25
  AttentionScreen: () => AttentionScreen,
26
26
  AuditScreen: () => AuditScreen,
27
27
  CatalogScreen: () => CatalogScreen,
28
- ConfigScreen: () => ConfigScreen,
29
28
  DoctorScreen: () => DoctorScreen,
29
+ EnvironmentScreen: () => EnvironmentScreen,
30
30
  MigrationsScreen: () => MigrationsScreen,
31
31
  ModulesScreen: () => ModulesScreen,
32
32
  RoutesScreen: () => RoutesScreen,
@@ -42,20 +42,49 @@ var import_react_courier_admin_screens = require("@fonderie/react-courier-admin-
42
42
  var import_react5 = require("react");
43
43
 
44
44
  // src/styles.ts
45
+ var t = {
46
+ text: "var(--fonderie-text,#171717)",
47
+ muted: "var(--fonderie-text-muted,#5c5c5c)",
48
+ bg: "var(--fonderie-bg,#fafafa)",
49
+ surface: "var(--fonderie-surface,#fff)",
50
+ surfaceAlt: "var(--fonderie-surface-alt,#fafafa)",
51
+ border: "var(--fonderie-border,#e0e0e0)",
52
+ borderLight: "var(--fonderie-border-light,#f5f5f5)",
53
+ accent: "var(--fonderie-accent,#00d294)",
54
+ accentStrong: "var(--fonderie-accent-strong,#009767)",
55
+ warning: "var(--fonderie-warning,#f5a623)",
56
+ danger: "var(--fonderie-danger,#e00)",
57
+ font: 'var(--fonderie-font,Inter,"Inter Fallback",-apple-system,BlinkMacSystemFont,"Helvetica Neue",system-ui,sans-serif)',
58
+ mono: 'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace)',
59
+ radius: "var(--fonderie-radius,4px)",
60
+ radiusLg: "var(--fonderie-radius-lg,8px)",
61
+ trackingDisplay: "var(--fonderie-tracking-display,-0.05em)",
62
+ shadowCard: "var(--fonderie-shadow-card,0 2px 3px 0 rgba(0,0,0,.05))"
63
+ };
45
64
  var styles = {
46
65
  shell: {
47
66
  display: "flex",
48
67
  minHeight: "100vh",
49
- fontFamily: "system-ui, sans-serif",
50
- color: "#111"
68
+ fontFamily: t.font,
69
+ color: t.text,
70
+ background: t.bg
71
+ },
72
+ // The sidebar sits on the raised surface against the page canvas, which is
73
+ // what separates the two without a heavy rule between them.
74
+ nav: {
75
+ width: 220,
76
+ borderRight: `1px solid ${t.border}`,
77
+ padding: 16,
78
+ flexShrink: 0,
79
+ background: t.surface
51
80
  },
52
- nav: { width: 220, borderRight: "1px solid #eee", padding: 16, flexShrink: 0 },
53
81
  navGroup: {
54
82
  fontSize: 11,
55
83
  textTransform: "uppercase",
56
84
  letterSpacing: 0.6,
57
- color: "#888",
58
- margin: "16px 0 6px"
85
+ color: t.muted,
86
+ margin: "16px 0 6px",
87
+ fontWeight: 600
59
88
  },
60
89
  navItem: {
61
90
  display: "block",
@@ -63,51 +92,79 @@ var styles = {
63
92
  textAlign: "left",
64
93
  background: "none",
65
94
  border: "none",
66
- borderRadius: 6,
95
+ borderRadius: t.radius,
67
96
  padding: "6px 8px",
68
97
  cursor: "pointer",
69
98
  fontSize: 14,
70
- color: "#111"
99
+ color: t.text,
100
+ fontFamily: "inherit"
71
101
  },
72
- navItemActive: { background: "#f3f4f6", fontWeight: 600 },
102
+ navItemActive: { background: t.surfaceAlt, fontWeight: 600, color: t.accentStrong },
73
103
  main: { flex: 1, padding: 24, maxWidth: 960 },
74
104
  container: { padding: 24, maxWidth: 960 },
75
- title: { fontSize: 20, fontWeight: 700, marginTop: 0, marginBottom: 12 },
76
- subtitle: { fontSize: 15, fontWeight: 600, marginTop: 24, marginBottom: 8 },
77
- status: { padding: 12, color: "#666" },
78
- error: { color: "#e11d48", marginBottom: 12, fontSize: 14 },
79
- ok: { color: "#15803d", fontWeight: 600 },
80
- bad: { color: "#e11d48", fontWeight: 600 },
81
- advice: { color: "#b45309" },
82
- muted: { color: "#666", fontSize: 13 },
83
- mono: { fontFamily: "ui-monospace, monospace", fontSize: 13 },
105
+ title: {
106
+ fontSize: 20,
107
+ fontWeight: 600,
108
+ marginTop: 0,
109
+ marginBottom: 12,
110
+ letterSpacing: t.trackingDisplay
111
+ },
112
+ subtitle: {
113
+ fontSize: 15,
114
+ fontWeight: 600,
115
+ marginTop: 24,
116
+ marginBottom: 8,
117
+ letterSpacing: t.trackingDisplay
118
+ },
119
+ status: { padding: 12, color: t.muted },
120
+ error: { color: t.danger, marginBottom: 12, fontSize: 14 },
121
+ ok: { color: t.accentStrong, fontWeight: 600 },
122
+ bad: { color: t.danger, fontWeight: 600 },
123
+ advice: { color: t.warning },
124
+ muted: { color: t.muted, fontSize: 13 },
125
+ mono: { fontFamily: t.mono, fontSize: 13 },
84
126
  table: { width: "100%", borderCollapse: "collapse", fontSize: 14 },
85
127
  th: {
86
128
  textAlign: "left",
87
- borderBottom: "1px solid #ddd",
129
+ borderBottom: `1px solid ${t.border}`,
88
130
  padding: "6px 8px",
89
131
  fontWeight: 600,
90
- color: "#444"
132
+ color: t.muted
91
133
  },
92
- td: { borderBottom: "1px solid #eee", padding: "6px 8px", verticalAlign: "top" },
134
+ td: { borderBottom: `1px solid ${t.borderLight}`, padding: "6px 8px", verticalAlign: "top" },
93
135
  list: { listStyle: "none", padding: 0, margin: 0 },
94
- row: { borderBottom: "1px solid #eee", padding: "8px 0" },
136
+ row: { borderBottom: `1px solid ${t.borderLight}`, padding: "8px 0" },
95
137
  badge: {
96
138
  display: "inline-block",
97
139
  borderRadius: 999,
98
140
  padding: "1px 8px",
99
141
  fontSize: 12,
100
- background: "#f3f4f6"
142
+ background: t.surfaceAlt,
143
+ border: `1px solid ${t.border}`,
144
+ color: t.muted
101
145
  },
102
146
  button: {
103
- background: "none",
104
- border: "1px solid #ddd",
105
- borderRadius: 8,
147
+ background: t.surface,
148
+ border: `1px solid ${t.border}`,
149
+ borderRadius: t.radius,
106
150
  padding: "4px 10px",
107
151
  cursor: "pointer",
108
- fontSize: 13
152
+ fontSize: 13,
153
+ color: t.text,
154
+ fontFamily: "inherit",
155
+ boxShadow: t.shadowCard
156
+ },
157
+ toolbar: { display: "flex", gap: 8, alignItems: "center", marginBottom: 12 },
158
+ // Surfaces the screens compose themselves, kept here so a card looks the
159
+ // same on every page rather than being re-invented per screen.
160
+ card: {
161
+ background: t.surface,
162
+ border: `1px solid ${t.border}`,
163
+ borderRadius: t.radiusLg,
164
+ padding: 16,
165
+ boxShadow: t.shadowCard
109
166
  },
110
- toolbar: { display: "flex", gap: 8, alignItems: "center", marginBottom: 12 }
167
+ accent: { color: t.accent }
111
168
  };
112
169
 
113
170
  // src/screens/AdminLogScreen.tsx
@@ -206,11 +263,11 @@ function AttentionScreen({ client }) {
206
263
  ] });
207
264
  }
208
265
 
209
- // src/screens/ConfigScreen.tsx
266
+ // src/screens/EnvironmentScreen.tsx
210
267
  var import_react_admin3 = require("@fonderie/react-admin");
211
268
  var import_jsx_runtime3 = require("react/jsx-runtime");
212
- function ConfigScreen({ client }) {
213
- const { report, isLoading, error } = (0, import_react_admin3.useAdminConfig)(client);
269
+ function EnvironmentScreen({ client }) {
270
+ const { report, isLoading, error } = (0, import_react_admin3.useAdminEnvironment)(client);
214
271
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles.container, children: [
215
272
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h1", { style: styles.title, children: "Configuration" }),
216
273
  isLoading ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: styles.status, children: "Loading\u2026" }) : error ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: styles.error, role: "alert", children: error.explanation }) : report ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
@@ -450,8 +507,8 @@ function TokensScreen({ client }) {
450
507
  name: name.trim(),
451
508
  scopes,
452
509
  ...days && Number.isInteger(d) && d > 0 ? { expiresInDays: d } : {}
453
- }).then((t) => {
454
- setMinted({ name: t.name, token: t.token });
510
+ }).then((t2) => {
511
+ setMinted({ name: t2.name, token: t2.token });
455
512
  setName("");
456
513
  setDays("");
457
514
  }).catch(() => {
@@ -504,35 +561,35 @@ function TokensScreen({ client }) {
504
561
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("th", { style: styles.th, children: "Last used" }),
505
562
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("th", { style: styles.th })
506
563
  ] }) }),
507
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("tbody", { children: report.issued.map((t) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("tr", { children: [
564
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("tbody", { children: report.issued.map((t2) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("tr", { children: [
508
565
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("td", { style: styles.td, children: [
509
- t.name,
510
- t.revokedAt ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: styles.badge, children: " revoked" }) : null
566
+ t2.name,
567
+ t2.revokedAt ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: styles.badge, children: " revoked" }) : null
511
568
  ] }),
512
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: { ...styles.td, ...styles.mono }, children: t.scopes.join(", ") }),
569
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: { ...styles.td, ...styles.mono }, children: t2.scopes.join(", ") }),
513
570
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("td", { style: { ...styles.td, ...styles.muted }, children: [
514
- new Date(t.createdAt).toLocaleDateString(),
571
+ new Date(t2.createdAt).toLocaleDateString(),
515
572
  " \xB7 ",
516
- t.createdBy
573
+ t2.createdBy
517
574
  ] }),
518
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: { ...styles.td, ...styles.muted }, children: t.expiresAt ? new Date(t.expiresAt).toLocaleDateString() : "never" }),
519
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: { ...styles.td, ...styles.muted }, children: t.lastUsedAt ? new Date(t.lastUsedAt).toLocaleString() : "never" }),
520
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: styles.td, children: t.revokedAt ? null : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
575
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: { ...styles.td, ...styles.muted }, children: t2.expiresAt ? new Date(t2.expiresAt).toLocaleDateString() : "never" }),
576
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: { ...styles.td, ...styles.muted }, children: t2.lastUsedAt ? new Date(t2.lastUsedAt).toLocaleString() : "never" }),
577
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: styles.td, children: t2.revokedAt ? null : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
521
578
  "button",
522
579
  {
523
580
  type: "button",
524
581
  style: styles.button,
525
582
  onClick: () => {
526
583
  if (window.confirm(
527
- `Revoke "${t.name}"? Anything using it stops working immediately.`
584
+ `Revoke "${t2.name}"? Anything using it stops working immediately.`
528
585
  ))
529
- void revoke(t.id).catch(() => {
586
+ void revoke(t2.id).catch(() => {
530
587
  });
531
588
  },
532
589
  children: "Revoke"
533
590
  }
534
591
  ) })
535
- ] }, t.id)) })
592
+ ] }, t2.id)) })
536
593
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { style: styles.muted, children: "None issued." })
537
594
  ] }),
538
595
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h2", { style: styles.subtitle, children: "Legacy per-brick tokens" }),
@@ -768,7 +825,7 @@ function CatalogScreen({ client }) {
768
825
  isLoading && !catalog ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: styles.status, children: "Loading\u2026" }) : null,
769
826
  catalog ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
770
827
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { style: styles.subtitle, children: "Configured (code)" }),
771
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("pre", { style: { ...styles.mono, background: "#f9fafb", padding: 12, overflowX: "auto" }, children: JSON.stringify(catalog.configured, null, 2) }),
828
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("pre", { style: { ...styles.mono, background: "var(--fonderie-surface-alt,#fafafa)", padding: 12, overflowX: "auto" }, children: JSON.stringify(catalog.configured, null, 2) }),
772
829
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { style: styles.subtitle, children: "Stored (database)" }),
773
830
  catalog.stored.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: styles.muted, children: "No stored plans." }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("table", { style: styles.table, children: [
774
831
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("tr", { children: [
@@ -826,11 +883,11 @@ function SubscriberScreen({ client, pageSize = 50 }) {
826
883
  const [amount, setAmount] = (0, import_react3.useState)("");
827
884
  const [note, setNote] = (0, import_react3.useState)("");
828
885
  const [granted, setGranted] = (0, import_react3.useState)(null);
829
- const open = (t, id) => {
886
+ const open = (t2, id) => {
830
887
  setGranted(null);
831
- setType(t);
888
+ setType(t2);
832
889
  setIdInput(id);
833
- setSubscriber({ type: t, id });
890
+ setSubscriber({ type: t2, id });
834
891
  };
835
892
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.container, children: [
836
893
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { style: styles.title, children: "Subscriber" }),
@@ -1041,12 +1098,12 @@ function SubscriberScreen({ client, pageSize = 50 }) {
1041
1098
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { style: styles.th, children: "Amount" }),
1042
1099
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { style: styles.th, children: "Note" })
1043
1100
  ] }) }),
1044
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tbody", { children: ledger.map((t) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("tr", { children: [
1045
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { style: { ...styles.td, ...styles.muted }, children: new Date(t.createdAt).toLocaleString() }),
1046
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { style: styles.td, children: t.type }),
1047
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { style: { ...styles.td, ...styles.mono }, children: t.amount }),
1048
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { style: { ...styles.td, ...styles.muted }, children: t.description ?? "" })
1049
- ] }, t.id)) })
1101
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tbody", { children: ledger.map((t2) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("tr", { children: [
1102
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { style: { ...styles.td, ...styles.muted }, children: new Date(t2.createdAt).toLocaleString() }),
1103
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { style: styles.td, children: t2.type }),
1104
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { style: { ...styles.td, ...styles.mono }, children: t2.amount }),
1105
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { style: { ...styles.td, ...styles.muted }, children: t2.description ?? "" })
1106
+ ] }, t2.id)) })
1050
1107
  ] }),
1051
1108
  hasMoreLedger ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1052
1109
  "button",
@@ -1155,7 +1212,7 @@ var NAV = [
1155
1212
  group: "System",
1156
1213
  items: [
1157
1214
  { page: "modules", label: "Modules" },
1158
- { page: "config", label: "Configuration" },
1215
+ { page: "environment", label: "Environment" },
1159
1216
  { page: "doctor", label: "Doctor" },
1160
1217
  { page: "routes", label: "Routes" }
1161
1218
  ]
@@ -1216,8 +1273,8 @@ function AdminShell({
1216
1273
  case "doctor":
1217
1274
  body = /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DoctorScreen, { client });
1218
1275
  break;
1219
- case "config":
1220
- body = /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ConfigScreen, { client });
1276
+ case "environment":
1277
+ body = /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(EnvironmentScreen, { client });
1221
1278
  break;
1222
1279
  case "routes":
1223
1280
  body = /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(RoutesScreen, { client });
@@ -1281,7 +1338,7 @@ function AdminShell({
1281
1338
  import_react_courier_admin_screens.TemplateListScreen,
1282
1339
  {
1283
1340
  client: courierClient,
1284
- onSelectTemplate: (t) => setEditing({ kind: "template", type: t.type })
1341
+ onSelectTemplate: (t2) => setEditing({ kind: "template", type: t2.type })
1285
1342
  }
1286
1343
  );
1287
1344
  break;
@@ -1318,8 +1375,8 @@ function AdminShell({
1318
1375
  AttentionScreen,
1319
1376
  AuditScreen,
1320
1377
  CatalogScreen,
1321
- ConfigScreen,
1322
1378
  DoctorScreen,
1379
+ EnvironmentScreen,
1323
1380
  MigrationsScreen,
1324
1381
  ModulesScreen,
1325
1382
  RoutesScreen,