@ctrl-ui/react 0.8.9 → 0.8.10

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.
@@ -0,0 +1,4 @@
1
+ //#region src/knob-contracts/app-shell-header-knobs.d.ts
2
+ export declare const appShellHeaderKnobs: readonly ["--cui-app-shell-header-height", "--cui-app-shell-header-padding-inline", "--cui-app-shell-header-background", "--cui-app-shell-header-border-color", "--cui-app-shell-header-border-width"];
3
+ export type AppShellHeaderKnobStyle = Partial<Record<(typeof appShellHeaderKnobs)[number], string>>;
4
+ //#endregion
@@ -0,0 +1,10 @@
1
+ //#region src/knob-contracts/app-shell-header-knobs.ts
2
+ const appShellHeaderKnobs = [
3
+ "--cui-app-shell-header-height",
4
+ "--cui-app-shell-header-padding-inline",
5
+ "--cui-app-shell-header-background",
6
+ "--cui-app-shell-header-border-color",
7
+ "--cui-app-shell-header-border-width"
8
+ ];
9
+ //#endregion
10
+ export { appShellHeaderKnobs };
@@ -13,6 +13,12 @@
13
13
  @import "./recipes/popup-controls.css";
14
14
  @import "./recipes/popup-lists.css";
15
15
  @import "./recipes/popup-motion.css";
16
+ @import "./recipes/page-layout.css";
17
+ @import "./recipes/track-highlight.css";
18
+ @import "./recipes/sidebar.css";
19
+ @import "./recipes/sidebar-menu.css";
20
+ @import "./recipes/sidebar-parts.css";
21
+ @import "./recipes/app-shell-header.css";
16
22
  @import "./recipes/audio-visualizer.css";
17
23
  @import "./recipes/audio-recorder.css";
18
24
  @import "./recipes/field.css";
@@ -20,7 +26,6 @@
20
26
  @import "./recipes/avatar.css";
21
27
  @import "./recipes/badge.css";
22
28
  @import "./recipes/breadcrumb.css";
23
- @import "./recipes/track-highlight.css";
24
29
  @import "./recipes/button-group.css";
25
30
  @import "./recipes/calendar.css";
26
31
  @import "./recipes/card.css";
@@ -35,9 +40,6 @@
35
40
  @import "./code.css";
36
41
  @import "./recipes/code.css";
37
42
  @import "./recipes/code-diff.css";
38
- @import "./recipes/sidebar.css";
39
- @import "./recipes/sidebar-menu.css";
40
- @import "./recipes/sidebar-parts.css";
41
43
  @import "./recipes/color-picker.css";
42
44
  @import "./recipes/color-picker-details.css";
43
45
  @import "./recipes/color-picker-values.css";
@@ -66,7 +68,6 @@
66
68
  @import "./recipes/markdown-block.css";
67
69
  @import "./recipes/range.css";
68
70
  @import "./recipes/morphing-panel.css";
69
- @import "./recipes/page-layout.css";
70
71
  @import "./recipes/pagination.css";
71
72
  @import "./recipes/phone-input.css";
72
73
  @import "./recipes/rich-tooltip.css";
@@ -0,0 +1,43 @@
1
+ @layer components {
2
+ :where([data-control-family="app-shell-header"][data-slot="root"]) {
3
+ --cui-app-shell-header-height: calc(var(--spacing) * 14);
4
+ --cui-app-shell-header-padding-inline: calc(var(--spacing) * 4);
5
+ --cui-app-shell-header-background: var(--background);
6
+ --cui-app-shell-header-border-width: 1px;
7
+ --cui-app-shell-header-border-color: var(--border);
8
+ min-height: var(--cui-app-shell-header-height);
9
+ padding-inline: var(--cui-app-shell-header-padding-inline);
10
+ background: var(--cui-app-shell-header-background);
11
+ border-block-end: var(--cui-app-shell-header-border-width) solid var(--cui-app-shell-header-border-color);
12
+ }
13
+ }
14
+
15
+ @property --cui-app-shell-header-height {
16
+ syntax: "<length>";
17
+ inherits: true;
18
+ initial-value: 0px;
19
+ }
20
+
21
+ @property --cui-app-shell-header-padding-inline {
22
+ syntax: "<length>";
23
+ inherits: true;
24
+ initial-value: 0px;
25
+ }
26
+
27
+ @property --cui-app-shell-header-background {
28
+ syntax: "<color>";
29
+ inherits: true;
30
+ initial-value: transparent;
31
+ }
32
+
33
+ @property --cui-app-shell-header-border-color {
34
+ syntax: "<color>";
35
+ inherits: true;
36
+ initial-value: transparent;
37
+ }
38
+
39
+ @property --cui-app-shell-header-border-width {
40
+ syntax: "<length>";
41
+ inherits: true;
42
+ initial-value: 0px;
43
+ }
@@ -0,0 +1,16 @@
1
+ import { SidebarProviderProps } from "./sidebar-provider.js";
2
+ import { SidebarInsetProps } from "./sidebar.js";
3
+ import { AppShellHeaderKnobStyle } from "../knob-contracts/app-shell-header-knobs.js";
4
+ import { PageScroll } from "./page-layout.js";
5
+ import { CSSProperties, ComponentProps } from "react";
6
+ //#region src/ui/app-shell.d.ts
7
+ export type AppShellProps = SidebarProviderProps & {
8
+ scroll?: PageScroll;
9
+ };
10
+ export declare function AppShell({ scroll, layout, className, ...props }: AppShellProps): import("react").JSX.Element;
11
+ export declare function AppShellContent({ className, ...props }: SidebarInsetProps): import("react").JSX.Element;
12
+ export type AppShellHeaderProps = Omit<ComponentProps<"header">, "style"> & {
13
+ style?: CSSProperties & AppShellHeaderKnobStyle;
14
+ };
15
+ export declare function AppShellHeader({ className, ...props }: AppShellHeaderProps): import("react").JSX.Element;
16
+ //#endregion
@@ -0,0 +1,39 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { SidebarProvider } from "./sidebar-provider.js";
4
+ import { SidebarInset } from "./sidebar.js";
5
+ import { PageScrollContext, usePageScroll } from "./page-layout.js";
6
+ import { jsx } from "react/jsx-runtime";
7
+ //#region src/ui/app-shell.tsx
8
+ function AppShell({ scroll = "auto", layout = "viewport", className, ...props }) {
9
+ const resolvedScroll = usePageScroll(scroll);
10
+ return /* @__PURE__ */ jsx(PageScrollContext.Provider, {
11
+ value: resolvedScroll,
12
+ children: /* @__PURE__ */ jsx(SidebarProvider, {
13
+ "data-app-shell": "",
14
+ "data-scroll": resolvedScroll,
15
+ layout,
16
+ className: cn(layout === "viewport" && (resolvedScroll === "page" ? "min-h-dvh" : "h-dvh min-h-0 overflow-hidden"), className),
17
+ ...props
18
+ })
19
+ });
20
+ }
21
+ function AppShellContent({ className, ...props }) {
22
+ const scroll = usePageScroll();
23
+ return /* @__PURE__ */ jsx(SidebarInset, {
24
+ "data-app-shell-content": "",
25
+ className: cn("min-h-0", scroll !== "page" && "overflow-hidden", className),
26
+ ...props
27
+ });
28
+ }
29
+ function AppShellHeader({ className, ...props }) {
30
+ return /* @__PURE__ */ jsx("header", {
31
+ "data-control-ui": "app-shell",
32
+ "data-control-family": "app-shell-header",
33
+ "data-slot": "root",
34
+ className: cn("sticky top-0 z-30 flex shrink-0 items-center gap-2", className),
35
+ ...props
36
+ });
37
+ }
38
+ //#endregion
39
+ export { AppShell, AppShellContent, AppShellHeader };
@@ -10,6 +10,7 @@ export type PageScroll = PageScrollMode | "auto";
10
10
  export declare const pageHeaderVariants: readonly ["flow", "sticky", "floating"];
11
11
  export type PageHeaderVariant = (typeof pageHeaderVariants)[number];
12
12
  type PageStyle = CSSProperties & PageLayoutKnobStyle;
13
+ export declare const PageScrollContext: import("react").Context<"inset" | "none" | "page" | null>;
13
14
  export declare function usePageScroll(scroll?: PageScroll): PageScrollMode;
14
15
  export type PageLayoutProps = Omit<ComponentProps<"div">, "style"> & {
15
16
  scroll?: PageScroll;
@@ -2,6 +2,7 @@
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { useSkin } from "../skin-provider.js";
4
4
  import { ScrollArea } from "./scroll-area.js";
5
+ import { createContext, useContext } from "react";
5
6
  import { jsx, jsxs } from "react/jsx-runtime";
6
7
  //#region src/ui/page-layout.tsx
7
8
  const pageWidths = [
@@ -20,9 +21,12 @@ const pageHeaderVariants = [
20
21
  "sticky",
21
22
  "floating"
22
23
  ];
24
+ const PageScrollContext = createContext(null);
23
25
  function usePageScroll(scroll = "auto") {
24
26
  const skin = useSkin();
27
+ const inheritedScroll = useContext(PageScrollContext);
25
28
  if (scroll !== "auto") return scroll;
29
+ if (inheritedScroll) return inheritedScroll;
26
30
  return skin.sidebarLayout === "page" ? "page" : "inset";
27
31
  }
28
32
  function PageLayout({ scroll = "auto", width = "prose", scrollViewportRef, children, className, ...props }) {
@@ -34,7 +38,7 @@ function PageLayout({ scroll = "auto", width = "prose", scrollViewportRef, child
34
38
  "data-slot": "root",
35
39
  "data-scroll": resolvedScroll,
36
40
  "data-width": width,
37
- className: cn("flex w-full flex-col", resolvedScroll !== "page" && "min-h-0 flex-1 overflow-hidden", className),
41
+ className: cn("flex min-w-0 w-full flex-col", resolvedScroll === "page" ? "grow" : "min-h-0 flex-1 overflow-hidden", className),
38
42
  ...props,
39
43
  children: scrollsInset ? /* @__PURE__ */ jsx(ScrollArea, {
40
44
  className: "min-h-0 flex-1",
@@ -103,4 +107,4 @@ function PageBody({ aside, contentClassName, children, className, ...props }) {
103
107
  });
104
108
  }
105
109
  //#endregion
106
- export { PageActions, PageBody, PageDescription, PageHeader, PageLayout, PageTitle, pageHeaderVariants, pageScrollModes, pageWidths, usePageScroll };
110
+ export { PageActions, PageBody, PageDescription, PageHeader, PageLayout, PageScrollContext, PageTitle, pageHeaderVariants, pageScrollModes, pageWidths, usePageScroll };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctrl-ui/react",
3
- "version": "0.8.9",
3
+ "version": "0.8.10",
4
4
  "description": "Control UI components, blocks, and primitives with neutral defaults and consumer-owned themes.",
5
5
  "license": "MIT",
6
6
  "repository": {