@cueplusplus/ui 0.20.0 → 0.20.1

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
@@ -1,5 +1,24 @@
1
1
  # @cueplusplus/ui
2
2
 
3
+ ## 0.20.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 62ab44c: Four small fixes to the components added in 0.20.0:
8
+
9
+ - **`Reveal` no longer flashes visible before the page hydrates.** The server's markup now starts hidden, through a `styles.css` rule that applies only where scripting is on and motion is welcome, so readers without JavaScript and readers who prefer reduced motion still see the content at once.
10
+ - **`useFrameClock` with `loop={false}` stops scheduling frames** once it reaches its last one.
11
+ - **`ParticleLogo` deletes a shader that compiled when its partner failed**, rather than leaking it.
12
+ - **`ParticleLogo`'s still image under `fit="contain"` now fits inside `containFill` of both dimensions**, as the particle field does, so it no longer changes size when motion is reduced.
13
+
14
+ - fc318ec: Nothing you import changed. The published `package.json` lists two more development dependencies,
15
+ `css-tree` and `@types/css-tree`, which the library's own test suite uses to check that an
16
+ arbitrary-value class such as `w-[12pxx]` compiles to CSS a browser keeps. Neither is installed with
17
+ the package. Two doc comments in `@cueplusplus/ui/system` now count the base font pairings
18
+ right: fourteen, not twelve.
19
+ - Updated dependencies [fc318ec]
20
+ - @cueplusplus/tokens@0.20.1
21
+
3
22
  ## 0.20.0
4
23
 
5
24
  ### Minor Changes
@@ -40,7 +40,11 @@ function compile(gl, type, source) {
40
40
  function build(gl, raster, sampled) {
41
41
  const vertex = compile(gl, gl.VERTEX_SHADER, VERTEX_SHADER);
42
42
  const fragment = compile(gl, gl.FRAGMENT_SHADER, FRAGMENT_SHADER);
43
- if (vertex === null || fragment === null) return null;
43
+ if (vertex === null || fragment === null) {
44
+ if (vertex !== null) gl.deleteShader(vertex);
45
+ if (fragment !== null) gl.deleteShader(fragment);
46
+ return null;
47
+ }
44
48
  const program = gl.createProgram();
45
49
  gl.attachShader(program, vertex);
46
50
  gl.attachShader(program, fragment);
@@ -426,9 +430,13 @@ const ParticleLogo = React.forwardRef(function ParticleLogo({ src, fit = "logo",
426
430
  alt: "",
427
431
  "aria-hidden": "true",
428
432
  className: "absolute inset-0 m-auto object-contain",
429
- style: {
430
- height: fit === "logo" ? "26%" : `${containFill * 100}%`,
433
+ style: fit === "logo" ? {
434
+ height: "26%",
431
435
  width: "auto"
436
+ } : {
437
+ width: `${containFill * 100}%`,
438
+ height: `${containFill * 100}%`,
439
+ objectFit: "contain"
432
440
  }
433
441
  }) : null]
434
442
  });
@@ -23,9 +23,10 @@ const EASE_OUT = "cubic-bezier(0, 0, 0.58, 1)";
23
23
  * <div data-reveal-item>Reason</div>
24
24
  * </Reveal>
25
25
  */
26
- const Reveal = React.forwardRef(function Reveal({ distance = 28, rootMargin = "-12% 0px", duration = 500, stagger = 0, className, children, ...props }, ref) {
26
+ const Reveal = React.forwardRef(function Reveal({ distance = 28, rootMargin = "-12% 0px", duration = 500, stagger = 0, className, style, children, ...props }, ref) {
27
27
  const box = React.useRef(null);
28
28
  const still = useStill();
29
+ const [mounted, setMounted] = React.useState(false);
29
30
  const entered = React.useRef(false);
30
31
  const targets = React.useCallback(() => {
31
32
  const element = box.current;
@@ -33,11 +34,11 @@ const Reveal = React.forwardRef(function Reveal({ distance = 28, rootMargin = "-
33
34
  return stagger > 0 ? [...element.querySelectorAll("[data-reveal-item]")] : [element];
34
35
  }, [stagger]);
35
36
  React.useLayoutEffect(() => {
36
- if (still || entered.current) return;
37
- for (const target of targets()) {
37
+ if (!still && !entered.current) for (const target of targets()) {
38
38
  target.style.opacity = "0";
39
39
  target.style.transform = `translateY(${distance}px)`;
40
40
  }
41
+ setMounted(true);
41
42
  }, [
42
43
  still,
43
44
  distance,
@@ -97,7 +98,12 @@ const Reveal = React.forwardRef(function Reveal({ distance = 28, rootMargin = "-
97
98
  else if (ref !== null) ref.current = node;
98
99
  },
99
100
  "data-slot": "reveal",
100
- className: cn(className),
101
+ "data-reveal-stagger": stagger > 0 ? "" : void 0,
102
+ className: cn(!still && !mounted && "cue-reveal-pending", className),
103
+ style: !still && !mounted ? {
104
+ ...style,
105
+ "--cue-reveal-distance": `${distance}px`
106
+ } : style,
101
107
  ...props,
102
108
  children
103
109
  });
@@ -2,7 +2,7 @@ import { ClassProp, VariantProps } from "../lib/cva.js";
2
2
  import * as React from "react";
3
3
  //#region src/primitives/chip.d.ts
4
4
  declare const chipVariants: (props?: ({
5
- tone?: "info" | "warn" | "danger" | "accent" | "ok" | "busy" | "neutral" | null | undefined;
5
+ tone?: "danger" | "info" | "warn" | "accent" | "ok" | "busy" | "neutral" | null | undefined;
6
6
  variant?: "outline" | "tinted" | "tag" | null | undefined;
7
7
  interactive?: boolean | null | undefined;
8
8
  } & ClassProp) | undefined) => string;
package/dist/styles.css CHANGED
@@ -115,6 +115,18 @@
115
115
  clip-path: none;
116
116
  }
117
117
 
118
+ /* `Reveal`'s server render (`layout/reveal.tsx`): pending content is hidden before hydration, so
119
+ * it is never shown visible and then hidden by the client. Only where scripting is on — a reader
120
+ * with no JavaScript sees it — and where motion is welcome, as the client's own entrance is. A
121
+ * staggered block stays visible and hides the items it marks, as the client does. */
122
+ @media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
123
+ .cue-reveal-pending:not([data-reveal-stagger]),
124
+ .cue-reveal-pending[data-reveal-stagger] [data-reveal-item] {
125
+ opacity: 0;
126
+ transform: translateY(var(--cue-reveal-distance, 28px));
127
+ }
128
+ }
129
+
118
130
  @media (forced-colors: active) {
119
131
  .cue-cut,
120
132
  .cue-cut-secondary {
@@ -32,6 +32,7 @@ function useFrameClock({ fps = 30, durationInFrames, loop = true, playing = true
32
32
  last = now;
33
33
  const total = Math.floor(elapsed.current * fps / 1e3);
34
34
  setFrame(loop ? total % durationInFrames : Math.min(total, durationInFrames - 1));
35
+ if (!loop && total >= durationInFrames - 1) return;
35
36
  handle = requestAnimationFrame(step);
36
37
  });
37
38
  const onVisibility = () => {
@@ -41,7 +41,7 @@ declare function useThemes(): readonly ThemeManifest[];
41
41
  */
42
42
  declare function useDensities(): readonly DensityEntry[];
43
43
  /**
44
- * The font pairings, by the same rule: the base twelve, then the active theme's.
44
+ * The font pairings, by the same rule: the base fourteen, then the active theme's.
45
45
  *
46
46
  * @throws If called outside a `<ThemeProvider>`.
47
47
  * @example
@@ -68,7 +68,7 @@ function useDensities() {
68
68
  return useRegistry("useDensities", (registry) => registry.densities);
69
69
  }
70
70
  /**
71
- * The font pairings, by the same rule: the base twelve, then the active theme's.
71
+ * The font pairings, by the same rule: the base fourteen, then the active theme's.
72
72
  *
73
73
  * @throws If called outside a `<ThemeProvider>`.
74
74
  * @example
@@ -66,7 +66,9 @@
66
66
  "parts": [],
67
67
  "variants": {},
68
68
  "defaultVariants": {},
69
- "tokensUsed": [],
69
+ "tokensUsed": [
70
+ "--cue-reveal-distance"
71
+ ],
70
72
  "summary": "Content that rises into place the first time it scrolls into view, once — cueplusplus.com's section entrance, with an optional stagger over the items you mark.",
71
73
  "examples": [
72
74
  {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "library": "@cueplusplus/ui",
4
- "version": "0.20.0",
4
+ "version": "0.20.1",
5
5
  "generatedAt": "1970-01-01T00:00:00.000Z",
6
6
  "themes": [
7
7
  "command",
@@ -38,7 +38,7 @@
38
38
  ],
39
39
  "tokens": {
40
40
  "path": "./tokens.json",
41
- "sha256": "ea5e034356318b8bf63b03dd1e4c263472dce4971c446df9d8c22105c13ebbff"
41
+ "sha256": "29cf733428fc4919b808a76fd8740364aa316c9ad86e45e985754417fc142eaa"
42
42
  },
43
43
  "systemApis": [
44
44
  {
@@ -4218,7 +4218,7 @@
4218
4218
  "mdUrl": "/docs/components/reveal.md",
4219
4219
  "jsonUrl": "/r/components/reveal.json",
4220
4220
  "path": "./components/reveal.json",
4221
- "sha256": "27a4037baaaea249ff9e7724b0febd645747267ca60b864140c8be050e303cba"
4221
+ "sha256": "404391de89464afe62311ed18e69df69f0207b4327b57760f91504b94b81c816"
4222
4222
  },
4223
4223
  {
4224
4224
  "name": "Sidebar",
@@ -5213,12 +5213,12 @@
5213
5213
  "importPath": "@cueplusplus/ui",
5214
5214
  "peerDependencies": [],
5215
5215
  "clientOnly": true,
5216
- "description": "The font pairings, by the same rule: the base twelve, then the active theme's.",
5216
+ "description": "The font pairings, by the same rule: the base fourteen, then the active theme's.",
5217
5217
  "signature": "(): readonly FontEntry[]",
5218
5218
  "params": [],
5219
5219
  "returns": "",
5220
5220
  "throws": "If called outside a `<ThemeProvider>`.",
5221
- "summary": "The font pairings, by the same rule: the base twelve, then the active theme's.",
5221
+ "summary": "The font pairings, by the same rule: the base fourteen, then the active theme's.",
5222
5222
  "examples": [
5223
5223
  {
5224
5224
  "title": "Usage",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "library": "@cueplusplus/tokens",
4
- "version": "0.20.0",
4
+ "version": "0.20.1",
5
5
  "themes": [
6
6
  {
7
7
  "name": "command",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cueplusplus/ui",
3
- "version": "0.20.0",
3
+ "version": "0.20.1",
4
4
  "description": "CUE++ design system components: Tailwind v4 styled wrappers over Base UI, driven by @cueplusplus/tokens.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -145,8 +145,8 @@
145
145
  "clsx": "^2.1.1",
146
146
  "culori": "^4.0.2",
147
147
  "tailwind-merge": "^3.6.0",
148
- "@cueplusplus/tokens": "0.20.0",
149
- "@cueplusplus/theme-base": "^1.3.0"
148
+ "@cueplusplus/theme-base": "^1.3.0",
149
+ "@cueplusplus/tokens": "0.20.1"
150
150
  },
151
151
  "peerDependencies": {
152
152
  "@assistant-ui/react": "^0.15.16",
@@ -234,6 +234,7 @@
234
234
  "@testing-library/jest-dom": "^7.0.1",
235
235
  "@testing-library/react": "^16.3.2",
236
236
  "@testing-library/user-event": "^14.6.4",
237
+ "@types/css-tree": "^3.2.0",
237
238
  "@types/culori": "^4.0.1",
238
239
  "@types/node": "^24.0.0",
239
240
  "@types/react": "^19.2.0",
@@ -241,6 +242,7 @@
241
242
  "@vitejs/plugin-react": "^6.0.5",
242
243
  "@xyflow/react": "^12.11.3",
243
244
  "anser": "^2.3.5",
245
+ "css-tree": "^3.2.1",
244
246
  "date-fns": "^4.4.0",
245
247
  "embla-carousel-react": "^8.6.0",
246
248
  "eslint": "^9.17.0",
@@ -260,10 +262,10 @@
260
262
  "tsdown": "0.22.14",
261
263
  "typescript": "^5.7.0",
262
264
  "vitest": "^4.1.10",
263
- "@repo/docgen": "0.0.0",
265
+ "@repo/eslint-config": "0.0.0",
264
266
  "@cueplusplus/theme-tools": "1.2.0",
265
- "@repo/typescript-config": "0.0.0",
266
- "@repo/eslint-config": "0.0.0"
267
+ "@repo/docgen": "0.0.0",
268
+ "@repo/typescript-config": "0.0.0"
267
269
  },
268
270
  "scripts": {
269
271
  "build": "pnpm run check:manifest && tsdown",