@caqophony/ui 0.4.0 → 0.5.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.
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import {
3
3
  Icon
4
- } from "./chunk-BAW3RIMF.js";
4
+ } from "./chunk-ID7VBGJA.js";
5
5
  import {
6
6
  cn
7
7
  } from "./chunk-DP5WQAPO.js";
@@ -1,7 +1,8 @@
1
1
  'use client';
2
2
  import {
3
+ CONTENT_GUTTER,
3
4
  Icon
4
- } from "./chunk-BAW3RIMF.js";
5
+ } from "./chunk-ID7VBGJA.js";
5
6
  import {
6
7
  cn
7
8
  } from "./chunk-DP5WQAPO.js";
@@ -97,11 +98,6 @@ Button.displayName = "Button";
97
98
 
98
99
  // src/container.tsx
99
100
  import * as React2 from "react";
100
-
101
- // src/content-gutter.ts
102
- var CONTENT_GUTTER = "px-4 sm:px-6 lg:px-8";
103
-
104
- // src/container.tsx
105
101
  import { jsx as jsx3 } from "react/jsx-runtime";
106
102
  var SIZE_CLASSES = {
107
103
  sm: "max-w-content-sm",
@@ -229,7 +225,8 @@ function NavDrawer({
229
225
  closedFrom,
230
226
  defaultOpen,
231
227
  children,
232
- triggerClassName
228
+ triggerClassName,
229
+ surface
233
230
  }) {
234
231
  const [open, setOpen] = React4.useState(defaultOpen);
235
232
  const id = React4.useId();
@@ -288,6 +285,7 @@ function NavDrawer({
288
285
  role: "dialog",
289
286
  "aria-modal": "true",
290
287
  "aria-label": label,
288
+ "data-surface": surface,
291
289
  className: cn(
292
290
  "absolute inset-y-0 flex w-72 max-w-[calc(100%-3rem)] flex-col overflow-y-auto bg-card shadow-lg",
293
291
  left ? "left-0 border-r" : "right-0 border-l",
@@ -347,7 +345,8 @@ function NavbarMenu({
347
345
  actions,
348
346
  defaultOpen = false,
349
347
  triggerClassName,
350
- folded = false
348
+ folded = false,
349
+ surface
351
350
  }) {
352
351
  return /* @__PURE__ */ jsx5("div", { className: folded ? "ml-auto" : "ml-auto md:hidden", children: /* @__PURE__ */ jsxs4(
353
352
  NavDrawer,
@@ -357,6 +356,7 @@ function NavbarMenu({
357
356
  closedFrom: folded ? null : "md",
358
357
  defaultOpen,
359
358
  triggerClassName,
359
+ surface,
360
360
  children: [
361
361
  search && /* @__PURE__ */ jsx5("div", { className: "px-4 pb-3", children: search }),
362
362
  links && /* @__PURE__ */ jsx5("nav", { className: "flex flex-col px-4 pb-3 [&>a]:whitespace-normal [&>a]:py-2.5 [&>a]:text-base", children: links }),
@@ -373,7 +373,6 @@ export {
373
373
  usePanelRef,
374
374
  useModalSurface,
375
375
  NavDrawer,
376
- CONTENT_GUTTER,
377
376
  NavbarMenu,
378
377
  Container
379
378
  };
@@ -218,6 +218,9 @@ function ScrollHintXMark() {
218
218
  );
219
219
  }
220
220
 
221
+ // src/content-gutter.ts
222
+ var CONTENT_GUTTER = "px-4 sm:px-6 lg:px-8";
223
+
221
224
  export {
222
225
  ICONS,
223
226
  ICON_SIZES,
@@ -225,5 +228,6 @@ export {
225
228
  SCROLL_HINT_X,
226
229
  SCROLL_HINT_Y,
227
230
  SCROLL_HINT_Y_MARK,
228
- ScrollHintXMark
231
+ ScrollHintXMark,
232
+ CONTENT_GUTTER
229
233
  };
package/dist/index.js CHANGED
@@ -4,7 +4,6 @@ import {
4
4
  } from "./chunk-ODRGJV46.js";
5
5
  import {
6
6
  Button,
7
- CONTENT_GUTTER,
8
7
  Container,
9
8
  NavDrawer,
10
9
  NavbarMenu,
@@ -12,7 +11,7 @@ import {
12
11
  buttonVariants,
13
12
  useModalSurface,
14
13
  usePanelRef
15
- } from "./chunk-PKP3ZIRB.js";
14
+ } from "./chunk-I5DQCG6D.js";
16
15
  import {
17
16
  Alert,
18
17
  EMPTY_VALUE_GLYPH,
@@ -20,8 +19,9 @@ import {
20
19
  INTENT_SUBTLE_STYLES,
21
20
  IntentBadge,
22
21
  isEmptyValue
23
- } from "./chunk-Y6LCXEXZ.js";
22
+ } from "./chunk-44GEHNZP.js";
24
23
  import {
24
+ CONTENT_GUTTER,
25
25
  ICONS,
26
26
  ICON_SIZES,
27
27
  Icon,
@@ -29,7 +29,7 @@ import {
29
29
  SCROLL_HINT_Y,
30
30
  SCROLL_HINT_Y_MARK,
31
31
  ScrollHintXMark
32
- } from "./chunk-BAW3RIMF.js";
32
+ } from "./chunk-ID7VBGJA.js";
33
33
  import {
34
34
  cn
35
35
  } from "./chunk-DP5WQAPO.js";
@@ -22,16 +22,23 @@ interface MarketingHeaderProps {
22
22
  * Visual variant:
23
23
  * - "light" (default): white card bg, dark text
24
24
  * - "dark": dark glassmorphic bg, light text (v4 marketing pages)
25
+ * - "night": night glass over a night hero, directly before a
26
+ * `Band surface="night"`: the hero runs under it, and it reads in both
27
+ * schemes. Its actions are `MarketingCta ground="dark"`.
25
28
  */
26
- variant?: 'light' | 'dark';
29
+ variant?: 'light' | 'dark' | 'night';
27
30
  }
28
31
  /**
29
32
  * Marketing site header with logo, navigation, and CTA actions.
30
33
  * Sticky top navigation bar for product landing pages.
31
34
  *
32
- * Two variants:
35
+ * Three variants:
33
36
  * light — standard white bg for app pages
34
37
  * dark — glassmorphic dark bg for the v4 marketing landing
38
+ * night — night glass over a night hero (#5980), on its own night scope
39
+ * (`data-surface="night"`), so plain tokens read and nothing inverts. A
40
+ * `Band surface="night"` directly after it runs under it, so the scene shows
41
+ * through the bar; its drawer stands on the same scope.
35
42
  *
36
43
  * #5948: below `md` the links and actions fold into the library's one phone
37
44
  * drawer (`NavbarMenu`), in both variants. The drawer stands on the card
package/dist/marketing.js CHANGED
@@ -3,10 +3,10 @@ import {
3
3
  Button,
4
4
  Container,
5
5
  NavbarMenu
6
- } from "./chunk-PKP3ZIRB.js";
6
+ } from "./chunk-I5DQCG6D.js";
7
7
  import {
8
8
  ScrollHintXMark
9
- } from "./chunk-BAW3RIMF.js";
9
+ } from "./chunk-ID7VBGJA.js";
10
10
  import {
11
11
  cn
12
12
  } from "./chunk-DP5WQAPO.js";
@@ -15,11 +15,13 @@ import {
15
15
  import * as React from "react";
16
16
  import { createPortal } from "react-dom";
17
17
  import { jsx, jsxs } from "react/jsx-runtime";
18
+ var NIGHT_GROUND = "-mb-16 justify-between border-b border-border bg-night-0/80 backdrop-blur-md";
18
19
  var ON_DARK_GROUND = "text-background dark:text-foreground";
19
20
  var DARK_MENU_BUTTON = cn(
20
21
  ON_DARK_GROUND,
21
22
  "hover:bg-background/10 hover:text-background dark:hover:bg-foreground/10 dark:hover:text-foreground"
22
23
  );
24
+ var NIGHT_MENU_BUTTON = "size-11";
23
25
  var FOLDED_AWAY = "md:invisible md:absolute md:w-0 md:overflow-hidden";
24
26
  var px = (value) => parseFloat(value) || 0;
25
27
  function useFold(refs, actionsHost, hasLinks) {
@@ -69,6 +71,8 @@ function MarketingHeader({
69
71
  variant = "light"
70
72
  }) {
71
73
  const isDark = variant === "dark";
74
+ const isNight = variant === "night";
75
+ const isGlass = isDark || isNight;
72
76
  const hasLinks = navItems.length > 0;
73
77
  const bar = React.useRef(null);
74
78
  const brand = React.useRef(null);
@@ -109,9 +113,11 @@ function MarketingHeader({
109
113
  ref: bar,
110
114
  "data-testid": "marketing-header",
111
115
  "data-folded": folded ? "" : void 0,
116
+ "data-surface": isNight ? "night" : void 0,
117
+ "data-marketing-header": isNight ? "night" : void 0,
112
118
  className: cn(
113
119
  "sticky top-0 z-50 flex h-16 items-center px-6 lg:px-12",
114
- isDark ? "justify-between border-b border-primary-foreground/[0.06] bg-foreground/85 backdrop-blur-md dark:bg-background/85" : "border-b border-border bg-card dark:border-border dark:bg-card",
120
+ isNight ? NIGHT_GROUND : isDark ? "justify-between border-b border-primary-foreground/[0.06] bg-foreground/85 backdrop-blur-md dark:bg-background/85" : "border-b border-border bg-card dark:border-border dark:bg-card",
115
121
  className
116
122
  ),
117
123
  children: [
@@ -136,7 +142,7 @@ function MarketingHeader({
136
142
  ref: nav,
137
143
  className: cn(
138
144
  "hidden min-w-0 flex-1 overflow-x-clip md:flex",
139
- isDark ? "ml-6" : "ml-6 lg:ml-12",
145
+ isGlass ? "ml-6" : "ml-6 lg:ml-12",
140
146
  folded && FOLDED_AWAY
141
147
  ),
142
148
  children: /* @__PURE__ */ jsx(
@@ -145,7 +151,7 @@ function MarketingHeader({
145
151
  ref: links,
146
152
  className: cn(
147
153
  "flex w-max items-center gap-4 lg:gap-8",
148
- isDark && "mx-auto"
154
+ isGlass && "mx-auto"
149
155
  ),
150
156
  children: navItems.map((item) => /* @__PURE__ */ jsx(
151
157
  "a",
@@ -153,7 +159,10 @@ function MarketingHeader({
153
159
  href: item.href,
154
160
  className: cn(
155
161
  "whitespace-nowrap text-sm font-medium no-underline transition-colors",
156
- isDark ? "flex min-h-[44px] items-center text-background/70 hover:text-background dark:text-foreground/70 dark:hover:text-foreground" : item.active ? "text-primary-text font-semibold" : "text-muted-foreground hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground"
162
+ isNight ? cn(
163
+ "flex min-h-[44px] items-center hover:text-foreground",
164
+ item.active ? "font-semibold text-foreground" : "text-muted-foreground"
165
+ ) : isDark ? "flex min-h-[44px] items-center text-background/70 hover:text-background dark:text-foreground/70 dark:hover:text-foreground" : item.active ? "text-primary-text font-semibold" : "text-muted-foreground hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground"
157
166
  ),
158
167
  children: item.label
159
168
  },
@@ -172,14 +181,22 @@ function MarketingHeader({
172
181
  hasLinks ? "ml-6" : "ml-auto pl-6",
173
182
  folded && FOLDED_AWAY
174
183
  ),
175
- children: /* @__PURE__ */ jsx("div", { ref: actionsHome, className: "flex w-max items-center gap-3", children: actionsHost ? createPortal(actions, actionsHost) : actions })
184
+ children: /* @__PURE__ */ jsx(
185
+ "div",
186
+ {
187
+ ref: actionsHome,
188
+ className: "flex w-max items-center gap-3 whitespace-nowrap",
189
+ children: actionsHost ? createPortal(actions, actionsHost) : actions
190
+ }
191
+ )
176
192
  }
177
193
  ),
178
194
  (hasLinks || actions) && /* @__PURE__ */ jsx(
179
195
  NavbarMenu,
180
196
  {
181
197
  folded,
182
- triggerClassName: isDark ? DARK_MENU_BUTTON : void 0,
198
+ triggerClassName: isDark ? DARK_MENU_BUTTON : isNight ? NIGHT_MENU_BUTTON : void 0,
199
+ surface: isNight ? variant : void 0,
183
200
  links: hasLinks ? navItems.map((item) => /* @__PURE__ */ jsx(
184
201
  "a",
185
202
  {
@@ -103,23 +103,35 @@ interface ArtText extends ArtFilled {
103
103
  copy: string;
104
104
  }
105
105
  type ArtNode = ArtGroup | ArtPath | ArtRect | ArtCircle | ArtEllipse | ArtLine | ArtPoly | ArtText;
106
- /** One SVG: `0 0 width height`, covering its box. */
106
+ /** Where a frame stays when its box has another shape. */
107
+ type ArtAnchor = 'top' | 'center' | 'bottom' | 'right';
108
+ /** `cover` fills the box and may cut the frame; `contain` keeps all of it. */
109
+ type ArtFit = 'cover' | 'contain';
110
+ /** `phone`/`desktop` cut at `md`; `stack`/`side`, a `HeroScene`'s subject, cut at `lg`. */
111
+ type ArtOnly = 'phone' | 'desktop' | 'stack' | 'side';
112
+ /** One SVG: `0 0 width height`, in its box as `fit` says. */
107
113
  interface ArtFrame {
108
114
  width: number;
109
115
  height: number;
110
116
  /** Which part stays in view when the box's shape differs. */
111
- anchor: 'top' | 'center' | 'bottom' | 'right';
112
- /** Show only on a phone or only from `md` up. */
113
- only?: 'phone' | 'desktop';
117
+ anchor: ArtAnchor;
118
+ /** Absent: `cover`, as all art drew before #5978. */
119
+ fit?: ArtFit;
120
+ /** Show on one side of a cut only. */
121
+ only?: ArtOnly;
114
122
  nodes: readonly ArtNode[];
115
123
  }
116
- /** A piece of art: one frame, or a phone frame and a desktop frame. */
124
+ /** A piece of art: one frame, or a `phone` and `desktop` pair, or a `stack` and `side` pair. */
117
125
  interface ArtTree {
118
126
  frames: readonly ArtFrame[];
119
127
  }
128
+ /** The one writer of how a frame sits in its box, for `Art` and `SkyField`. */
129
+ declare const preserveOf: (anchor: ArtAnchor, fit?: ArtFit) => string;
130
+ /** The one writer of where frames are cut, for `Art` and `SkyField`. */
131
+ declare const frameClass: (only: ArtOnly | undefined) => string;
120
132
  /** Draws a piece of art, for a `Figure`'s slot or a mark. */
121
133
  declare function Art({ tree }: {
122
134
  tree: ArtTree;
123
135
  }): ReactElement;
124
136
 
125
- export { Art, type ArtCircle, type ArtDrawing, type ArtEllipse, type ArtFilled, type ArtFrame, type ArtGroup, type ArtLine, type ArtNode, type ArtPaint, type ArtPath, type ArtPoly, type ArtRect, type ArtText, type ArtTransform, type ArtTree };
137
+ export { Art, type ArtAnchor, type ArtCircle, type ArtDrawing, type ArtEllipse, type ArtFilled, type ArtFit, type ArtFrame, type ArtGroup, type ArtLine, type ArtNode, type ArtOnly, type ArtPaint, type ArtPath, type ArtPoly, type ArtRect, type ArtText, type ArtTransform, type ArtTree, frameClass, preserveOf };
@@ -43,15 +43,19 @@ var STROKE = {
43
43
  // src/material/art.tsx
44
44
  import { Fragment, jsx } from "react/jsx-runtime";
45
45
  var ANCHOR = {
46
- top: "xMidYMin slice",
47
- center: "xMidYMid slice",
48
- bottom: "xMidYMax slice",
49
- right: "xMaxYMid slice"
46
+ top: "xMidYMin",
47
+ center: "xMidYMid",
48
+ bottom: "xMidYMax",
49
+ right: "xMaxYMid"
50
50
  };
51
+ var preserveOf = (anchor, fit = "cover") => `${ANCHOR[anchor]} ${fit === "contain" ? "meet" : "slice"}`;
51
52
  var SHOWN = {
52
53
  phone: "size-full md:hidden",
53
- desktop: "hidden size-full md:block"
54
+ desktop: "hidden size-full md:block",
55
+ stack: "size-full lg:hidden",
56
+ side: "hidden size-full lg:block"
54
57
  };
58
+ var frameClass = (only) => only ? SHOWN[only] : "size-full";
55
59
  function classOf(table, paint, attribute) {
56
60
  if (!Object.prototype.hasOwnProperty.call(table, paint))
57
61
  throw new Error(
@@ -191,14 +195,16 @@ function Art({ tree }) {
191
195
  "svg",
192
196
  {
193
197
  viewBox: `0 0 ${frame.width} ${frame.height}`,
194
- preserveAspectRatio: ANCHOR[frame.anchor],
198
+ preserveAspectRatio: preserveOf(frame.anchor, frame.fit),
195
199
  "aria-hidden": "true",
196
- className: frame.only ? SHOWN[frame.only] : "size-full",
200
+ className: frameClass(frame.only),
197
201
  children: frame.nodes.map(render)
198
202
  },
199
203
  i
200
204
  )) });
201
205
  }
202
206
  export {
203
- Art
207
+ Art,
208
+ frameClass,
209
+ preserveOf
204
210
  };