@pattern-stack/frontend-patterns 0.2.0-alpha.12 → 0.2.0-alpha.13

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/CHANGELOG.md CHANGED
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.0-alpha.13]
11
+
12
+ ### Changed
13
+ - **AppHeader defaults are now opt-in** (BREAKING):
14
+ - `showSearch`, `showUserMenu`, and `showConnectionStatus` now all default to `false`.
15
+ - The global search slot was previously rendered by default but is non-trivial to wire and looks broken when it's a no-op in consumer apps. Consumers must now explicitly pass `showSearch`, `showUserMenu`, or `showConnectionStatus` to enable each slot.
16
+ - **Migration**: if your app relied on these slots appearing automatically, pass `header={{ showSearch: true, showUserMenu: true, showConnectionStatus: true }}` (or whichever subset you need) when constructing `<AppLayout>` / `createReactApp`.
17
+ - **AppHeader search width reduced** when shown: `max-w-2xl` → `max-w-md`. The full-width search bar dominated the header; the trimmer width sits comfortably between branding and the right-hand cluster.
18
+
19
+ ### Added
20
+ - **`Sidebar` `footer` prop**: pass any `ReactNode` to render in the sidebar footer slot. When omitted, the entire footer (and its top border) is not rendered — no empty space.
21
+ - **`AppLayoutProps.sidebar`**: new `{ footer?: ReactNode }` prop on `<AppLayout>`, plumbed through to `<Sidebar>`.
22
+ - **`AppConfig.sidebar`**: `createReactApp` now accepts a `sidebar: { footer }` config that mirrors the existing `header` plumbing.
23
+
24
+ ### Fixed
25
+ - **`createReactApp` no longer leaks the built-in `<DefaultHome />` placeholder** to consumer apps that have registered their own routes. The "✅ Template integration successful" / "🌿 {title}" landing page used to win the `/` index route even when a consumer called `addRoutes('/', ...)`. `DefaultHome` is now only rendered in the zero-config case — when the consumer has not registered any routes at all.
26
+
27
+ ### Removed
28
+ - **Hardcoded "AloeVera v1.0" / "v1.0" sidebar footer text**. The sidebar no longer ships with template branding; consumers supply their own footer node (or none).
29
+
10
30
  ### Fixed
11
31
  - **TypeScript Build Errors**: Resolved all TypeScript compilation errors across codegen and auth modules
12
32
  - Added missing type imports in OpenAPI codegen (`ParsedParameter`, `ClientGeneratorOptions`)
package/dist/index.es.js CHANGED
@@ -10650,7 +10650,7 @@ const SidebarButton = ({
10650
10650
  }
10651
10651
  );
10652
10652
  };
10653
- const Sidebar = ({ className }) => {
10653
+ const Sidebar = ({ className, footer }) => {
10654
10654
  const { isExpanded, toggleSidebar } = useSidebar();
10655
10655
  const { navigation } = useNavigation();
10656
10656
  const location = useLocation();
@@ -10724,35 +10724,23 @@ const Sidebar = ({ className }) => {
10724
10724
  item.value
10725
10725
  );
10726
10726
  }) }),
10727
- /* @__PURE__ */ jsx(
10727
+ footer != null && /* @__PURE__ */ jsx(
10728
10728
  "div",
10729
10729
  {
10730
10730
  className: cn("p-4 border-t border-border", !isExpanded && "px-3"),
10731
10731
  "data-component-name": "SidebarFooter",
10732
- children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
10733
- /* @__PURE__ */ jsx(
10734
- "div",
10735
- {
10736
- className: cn(
10737
- "text-xs text-muted-foreground text-center",
10738
- "absolute inset-0 transition-opacity duration-200 ease-out",
10739
- !isExpanded ? "opacity-100" : "opacity-0"
10740
- ),
10741
- children: "v1.0"
10742
- }
10743
- ),
10744
- /* @__PURE__ */ jsx(
10745
- "div",
10746
- {
10747
- className: cn(
10748
- "text-xs text-muted-foreground whitespace-nowrap",
10749
- "transition-opacity duration-200 ease-out",
10750
- isExpanded ? "opacity-100" : "opacity-0"
10751
- ),
10752
- children: "AloeVera v1.0"
10753
- }
10754
- )
10755
- ] })
10732
+ children: /* @__PURE__ */ jsx(
10733
+ "div",
10734
+ {
10735
+ className: cn(
10736
+ "text-xs text-muted-foreground",
10737
+ "transition-opacity duration-200 ease-out",
10738
+ isExpanded ? "opacity-100" : "opacity-70",
10739
+ !isExpanded && "text-center"
10740
+ ),
10741
+ children: footer
10742
+ }
10743
+ )
10756
10744
  }
10757
10745
  )
10758
10746
  ]
@@ -10766,9 +10754,9 @@ const AppHeader = ({
10766
10754
  className,
10767
10755
  branding,
10768
10756
  searchPlaceholder = "Search models, tests, jobs, and components...",
10769
- showSearch = true,
10770
- showUserMenu = true,
10771
- showConnectionStatus = true
10757
+ showSearch = false,
10758
+ showUserMenu = false,
10759
+ showConnectionStatus = false
10772
10760
  }) => {
10773
10761
  const isTrialMode = false;
10774
10762
  const brandingNode = (() => {
@@ -10797,7 +10785,7 @@ const AppHeader = ({
10797
10785
  ),
10798
10786
  children: /* @__PURE__ */ jsx("div", { className: "mx-auto max-w-7xl px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxs("div", { className: "flex h-16 items-center justify-between", children: [
10799
10787
  /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3", children: brandingNode }),
10800
- showSearch && /* @__PURE__ */ jsx("div", { className: "flex-1 max-w-2xl mx-8", children: /* @__PURE__ */ jsx(GlobalSearch, { className: "w-full", placeholder: searchPlaceholder }) }),
10788
+ showSearch && /* @__PURE__ */ jsx("div", { className: "flex-1 max-w-md mx-8", children: /* @__PURE__ */ jsx(GlobalSearch, { className: "w-full", placeholder: searchPlaceholder }) }),
10801
10789
  /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-4", children: [
10802
10790
  showConnectionStatus && /* @__PURE__ */ jsx(ConnectionStatus, {}),
10803
10791
  showUserMenu && /* @__PURE__ */ jsx(UserMenu, { category: 8 })
@@ -10806,12 +10794,12 @@ const AppHeader = ({
10806
10794
  }
10807
10795
  );
10808
10796
  };
10809
- const AppLayout = ({ header } = {}) => {
10797
+ const AppLayout = ({ header, sidebar } = {}) => {
10810
10798
  const { isExpanded } = useSidebar();
10811
10799
  const hideHeader = header === false;
10812
10800
  return /* @__PURE__ */ jsxs("div", { className: "min-h-screen bg-background", children: [
10813
10801
  !hideHeader && /* @__PURE__ */ jsx(AppHeader, { ...header ?? {} }),
10814
- /* @__PURE__ */ jsx(Sidebar, {}),
10802
+ /* @__PURE__ */ jsx(Sidebar, { footer: sidebar == null ? void 0 : sidebar.footer }),
10815
10803
  /* @__PURE__ */ jsx(
10816
10804
  "main",
10817
10805
  {
@@ -15620,6 +15608,7 @@ function createReactApp(config) {
15620
15608
  navigation,
15621
15609
  customProviders = [],
15622
15610
  header,
15611
+ sidebar,
15623
15612
  persistQueryCache = false,
15624
15613
  queryCacheKey = "PATTERN_STACK_QUERY_CACHE"
15625
15614
  } = appConfig;
@@ -15715,8 +15704,10 @@ function createReactApp(config) {
15715
15704
  }
15716
15705
  return component;
15717
15706
  };
15718
- const AppContent = () => /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-screen", children: "Loading..." }), children: /* @__PURE__ */ jsx(Routes, { children: /* @__PURE__ */ jsxs(Route, { path: "/", element: /* @__PURE__ */ jsx(AppLayout, { header }), children: [
15719
- /* @__PURE__ */ jsx(Route, { index: true, element: wrapWithProtection("/", /* @__PURE__ */ jsx(DefaultHome, {})) }),
15707
+ const consumerHasRoot = routes.some((r) => r.path === "/");
15708
+ const showDefaultHome = routes.length === 0;
15709
+ const AppContent = () => /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-screen", children: "Loading..." }), children: /* @__PURE__ */ jsx(Routes, { children: /* @__PURE__ */ jsxs(Route, { path: "/", element: /* @__PURE__ */ jsx(AppLayout, { header, sidebar }), children: [
15710
+ showDefaultHome && !consumerHasRoot && /* @__PURE__ */ jsx(Route, { index: true, element: wrapWithProtection("/", /* @__PURE__ */ jsx(DefaultHome, {})) }),
15720
15711
  routes.map(({ path, component }, index) => /* @__PURE__ */ jsx(Route, { path, element: wrapWithProtection(path, component) }, index))
15721
15712
  ] }) }) });
15722
15713
  return createProviderTree(/* @__PURE__ */ jsx(AppContent, {}));