@chronogrove/ui 0.83.2 → 0.84.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chronogrove/ui",
3
- "version": "0.83.2",
3
+ "version": "0.84.0",
4
4
  "description": "Chronogrove Theme UI theme, color mode helpers, and shared UI primitives",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -142,6 +142,10 @@
142
142
  "import": "./src/article-column-container.js",
143
143
  "default": "./src/article-column-container.js"
144
144
  },
145
+ "./category-index-layout": {
146
+ "import": "./src/category-index-layout.js",
147
+ "default": "./src/category-index-layout.js"
148
+ },
145
149
  "./home-dashboard-layout": {
146
150
  "import": "./src/home-dashboard-layout.js",
147
151
  "default": "./src/home-dashboard-layout.js"
@@ -177,26 +181,26 @@
177
181
  "@emotion/cache": "^11.14.0",
178
182
  "@emotion/react": "^11.14.0",
179
183
  "@fortawesome/fontawesome-svg-core": "^7.2.0",
180
- "@fortawesome/react-fontawesome": "^3.3.0",
184
+ "@fortawesome/react-fontawesome": "^3.3.1",
181
185
  "@theme-toggles/react": "^4.1.0",
182
186
  "@theme-ui/components": "^0.17.4",
183
187
  "@theme-ui/presets": "^0.17.4",
184
188
  "react-intersection-observer": "^10.0.3",
185
189
  "theme-ui": "^0.17.4",
186
- "three": "^0.183.2"
190
+ "three": "^0.184.0"
187
191
  },
188
192
  "devDependencies": {
189
193
  "@babel/core": "^7.29.0",
190
- "@babel/preset-env": "^7.29.2",
194
+ "@babel/preset-env": "^7.29.5",
191
195
  "@babel/preset-react": "^7.28.5",
192
196
  "@testing-library/jest-dom": "^6.9.1",
193
197
  "@testing-library/react": "^16.3.2",
194
- "babel-jest": "^30.3.0",
195
- "jest": "^30.3.0",
196
- "jest-environment-jsdom": "^30.3.0",
197
- "next": "^16.2.3",
198
- "react": "^19.2.5",
199
- "react-dom": "^19.2.5"
198
+ "babel-jest": "^30.4.1",
199
+ "jest": "^30.4.2",
200
+ "jest-environment-jsdom": "^30.4.1",
201
+ "next": "^16.2.6",
202
+ "react": "^19.2.6",
203
+ "react-dom": "^19.2.6"
200
204
  },
201
205
  "scripts": {
202
206
  "test": "jest --config jest.config.cjs",
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Shared layout for category-style index pages (blog, travel, music, etc.)
3
+ * under the animated hero background.
4
+ */
5
+
6
+ import React, { Fragment } from 'react'
7
+ import { Box } from '@theme-ui/components'
8
+
9
+ import AnimatedPageBackground from './animated-page-background/index.js'
10
+
11
+ /** Outer column flex (below site chrome): stacks header + content with consistent vertical rhythm. */
12
+ export const categoryIndexMainColumnFlexSx = {
13
+ flexDirection: 'column',
14
+ flexGrow: 1,
15
+ position: 'relative',
16
+ py: 3
17
+ }
18
+
19
+ /** `sx` for the post list `<section>` (matches Travel index spacing). */
20
+ export const categoryIndexPostListSectionSx = {
21
+ display: 'grid',
22
+ gridGap: [2, 2, 3, 3],
23
+ gridTemplateColumns: '1fr',
24
+ mt: 4
25
+ }
26
+
27
+ /** `sx` for the empty-state wrapper under the header. */
28
+ export const categoryIndexEmptyStateBoxSx = {
29
+ textAlign: 'center',
30
+ py: 6,
31
+ mt: 4
32
+ }
33
+
34
+ /**
35
+ * Animated gradient hero + elevated content layer (same stacking as Travel/Music/Blog indexes).
36
+ *
37
+ * @param {object} props
38
+ * @param {React.ReactNode} props.children
39
+ * @param {string} [props.overlayHeight]
40
+ */
41
+ export function CategoryIndexHeroChrome({ children, overlayHeight = 'min(75vh, 1000px)' }) {
42
+ return (
43
+ <Fragment>
44
+ <AnimatedPageBackground overlayHeight={overlayHeight} />
45
+ <Box
46
+ sx={{
47
+ position: 'relative',
48
+ zIndex: 1
49
+ }}
50
+ >
51
+ {children}
52
+ </Box>
53
+ </Fragment>
54
+ )
55
+ }
@@ -0,0 +1,71 @@
1
+ import React from 'react'
2
+ import { render, screen } from '@testing-library/react'
3
+ import '@testing-library/jest-dom'
4
+
5
+ import {
6
+ CategoryIndexHeroChrome,
7
+ categoryIndexEmptyStateBoxSx,
8
+ categoryIndexMainColumnFlexSx,
9
+ categoryIndexPostListSectionSx
10
+ } from './category-index-layout.js'
11
+
12
+ jest.mock('./animated-page-background/index.js', () => ({
13
+ __esModule: true,
14
+ default: ({ overlayHeight }) => <div data-testid='animated-page-background' data-overlay={overlayHeight} />
15
+ }))
16
+
17
+ describe('categoryIndexPostListSectionSx', () => {
18
+ it('matches shared index grid layout', () => {
19
+ expect(categoryIndexPostListSectionSx).toMatchObject({
20
+ display: 'grid',
21
+ gridGap: [2, 2, 3, 3],
22
+ gridTemplateColumns: '1fr',
23
+ mt: 4
24
+ })
25
+ })
26
+ })
27
+
28
+ describe('categoryIndexEmptyStateBoxSx', () => {
29
+ it('matches shared empty state spacing', () => {
30
+ expect(categoryIndexEmptyStateBoxSx).toMatchObject({
31
+ textAlign: 'center',
32
+ py: 6,
33
+ mt: 4
34
+ })
35
+ })
36
+ })
37
+
38
+ describe('categoryIndexMainColumnFlexSx', () => {
39
+ it('matches main column flex rhythm', () => {
40
+ expect(categoryIndexMainColumnFlexSx).toMatchObject({
41
+ flexDirection: 'column',
42
+ flexGrow: 1,
43
+ position: 'relative',
44
+ py: 3
45
+ })
46
+ })
47
+ })
48
+
49
+ describe('CategoryIndexHeroChrome', () => {
50
+ it('defaults overlay height when omitted', () => {
51
+ render(
52
+ <CategoryIndexHeroChrome>
53
+ <div data-testid='inner'>Hello</div>
54
+ </CategoryIndexHeroChrome>
55
+ )
56
+
57
+ expect(screen.getByTestId('animated-page-background')).toHaveAttribute('data-overlay', 'min(75vh, 1000px)')
58
+ expect(screen.getByTestId('inner')).toHaveTextContent('Hello')
59
+ })
60
+
61
+ it('renders animated background and stacks children above it', () => {
62
+ render(
63
+ <CategoryIndexHeroChrome overlayHeight='42vh'>
64
+ <div data-testid='inner'>Hello</div>
65
+ </CategoryIndexHeroChrome>
66
+ )
67
+
68
+ expect(screen.getByTestId('animated-page-background')).toHaveAttribute('data-overlay', '42vh')
69
+ expect(screen.getByTestId('inner')).toHaveTextContent('Hello')
70
+ })
71
+ })