@groveback/ui 0.2.0 → 0.3.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.js CHANGED
@@ -969,7 +969,7 @@ function resolveRoute(routes, path) {
969
969
  return null;
970
970
  }
971
971
  function GroveRoutes(props) {
972
- const { routes, context, fallback, children } = props;
972
+ const { routes, context, fallback, children, gate } = props;
973
973
  const [path, setPath] = useState4(() => window.location.pathname);
974
974
  useEffect3(() => {
975
975
  const onPop = () => setPath(window.location.pathname);
@@ -983,9 +983,10 @@ function GroveRoutes(props) {
983
983
  const value = useMemo2(() => ({ ...context, navigate }), [context, navigate]);
984
984
  const hit = resolveRoute(routes, path);
985
985
  const isRoot = (path.replace(/\/+$/, "") || "/") === "/";
986
- const screen = hit ? hit.route.render(hit.params) : fallback ?? (isRoot ? /* @__PURE__ */ jsx5(RouteIndex, {
986
+ const matched = hit ? hit.route.render(hit.params) : fallback ?? (isRoot ? /* @__PURE__ */ jsx5(RouteIndex, {
987
987
  routes
988
988
  }) : /* @__PURE__ */ jsx5(NotFound, {}));
989
+ const screen = gate && hit && hit.route.requiresAuth !== false ? gate(matched) : matched;
989
990
  return /* @__PURE__ */ jsxs4(GroveUiProvider, {
990
991
  value,
991
992
  children: [
package/dist/routes.d.ts CHANGED
@@ -17,6 +17,11 @@ export interface GroveRoute {
17
17
  path: string;
18
18
  /** Title authored in the Studio, when the screen has one. */
19
19
  title?: string | undefined;
20
+ /**
21
+ * Whether a visitor must be signed in to see this route (D81). Absent means REQUIRED, so a
22
+ * route table written before this existed keeps behaving as it did.
23
+ */
24
+ requiresAuth?: boolean | undefined;
20
25
  render: (params: Record<string, string>) => ReactNode;
21
26
  }
22
27
  /**
@@ -58,10 +63,18 @@ export declare function GroveRoutes(props: {
58
63
  fallback?: ReactNode | undefined;
59
64
  /**
60
65
  * Rendered inside the provider, ahead of the screen — where an app puts its own chrome.
61
- * A sign-in gate goes OUTSIDE instead (`<SignIn><GroveRoutes …/></SignIn>`): it needs no
62
- * provider, and wrapping the router is what keeps every route behind it at once.
66
+ * A gate that covers EVERY route goes outside instead (`<SignIn><GroveRoutes …/></SignIn>`).
63
67
  */
64
68
  children?: ReactNode | undefined;
69
+ /**
70
+ * Rendered in place of a route whose `requiresAuth` is not false while nobody is signed in
71
+ * (D81) — the generated app passes its `<SignIn>`. Per route rather than around the whole
72
+ * router, so one app can serve a public landing page and a private dashboard.
73
+ *
74
+ * Absent means no gate at all: a route table with no public/private distinction renders as
75
+ * it always did, and an app that wraps the router keeps working unchanged.
76
+ */
77
+ gate?: ((screen: ReactNode) => ReactNode) | undefined;
65
78
  }): import("react").JSX.Element;
66
79
  /**
67
80
  * The pages of the document, for a root with no screen of its own. Only routes with no
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groveback/ui",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "React primitives for Groveback Studio screens — tables, forms, detail views and relation pickers that read through the Groveback SDK, so every query passes the policy engine.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",