bsmnt 0.4.0 → 0.4.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.
Files changed (26) hide show
  1. package/package.json +1 -1
  2. package/src/templates/next-pagebuilder/app/(content)/[[...slug]]/page.tsx +17 -8
  3. package/src/templates/next-pagebuilder/app/(content)/layout.tsx +19 -7
  4. package/src/templates/next-pagebuilder/app/actions/refresh.ts +5 -0
  5. package/src/templates/next-pagebuilder/components/layout/footer/index.tsx +15 -19
  6. package/src/templates/next-pagebuilder/components/layout/header/index.tsx +3 -5
  7. package/src/templates/next-pagebuilder/components/layout/json-ld/index.tsx +11 -10
  8. package/src/templates/next-pagebuilder/components/layout/wrapper/index.tsx +14 -4
  9. package/src/templates/next-pagebuilder/components/page-builder/components/{post-collection → content-collection}/content-card.tsx +3 -5
  10. package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/content-filters.tsx +93 -0
  11. package/src/templates/next-pagebuilder/components/page-builder/components/{post-collection → content-collection}/content-grid.tsx +7 -9
  12. package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/content-pagination-nav.tsx +71 -0
  13. package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/index.tsx +212 -0
  14. package/src/templates/next-pagebuilder/components/page-builder/components/{post-collection → content-collection}/types.ts +5 -4
  15. package/src/templates/next-pagebuilder/components/page-builder/renderer.tsx +13 -5
  16. package/src/templates/next-pagebuilder/components/page-document/index.tsx +9 -4
  17. package/src/templates/next-pagebuilder/components/sanity/visual-editing.tsx +2 -1
  18. package/src/templates/next-pagebuilder/lib/integrations/sanity/constants.ts +1 -0
  19. package/src/templates/next-pagebuilder/lib/integrations/sanity/fetchers/layout.ts +17 -18
  20. package/src/templates/next-pagebuilder/lib/integrations/sanity/live/index.tsx +29 -2
  21. package/src/templates/next-pagebuilder/lib/integrations/sanity/presentation.ts +118 -0
  22. package/src/templates/next-pagebuilder/lib/integrations/sanity/queries.ts +144 -31
  23. package/src/templates/next-pagebuilder/lib/integrations/sanity/sanity.config.ts +5 -100
  24. package/src/templates/next-pagebuilder/next.config.ts +3 -0
  25. package/src/templates/next-pagebuilder/package.json +1 -2
  26. package/src/templates/next-pagebuilder/components/page-builder/components/post-collection/index.tsx +0 -28
@@ -97,6 +97,13 @@ const pageProjection = `
97
97
  _updatedAt
98
98
  `
99
99
 
100
+ const pageMetadataProjection = `
101
+ _id,
102
+ title,
103
+ metadata,
104
+ _updatedAt
105
+ `
106
+
100
107
  export const PAGE_QUERY = defineQuery(`
101
108
  *[
102
109
  _type == "page" &&
@@ -109,6 +116,18 @@ export const PAGE_QUERY = defineQuery(`
109
116
  }
110
117
  `)
111
118
 
119
+ export const PAGE_METADATA_QUERY = defineQuery(`
120
+ *[
121
+ _type == "page" &&
122
+ (
123
+ ($slug == null && !defined(pageFolder._ref) && (!defined(slug.current) || slug.current == "" || slug.current == "/")) ||
124
+ ${pageResolvedSlugExpression} == $slug
125
+ )
126
+ ][0] {
127
+ ${pageMetadataProjection}
128
+ }
129
+ `)
130
+
112
131
  export const ALL_PAGE_SLUGS_QUERY = defineQuery(`
113
132
  *[_type == "page" && (defined(pageFolder->slug.current) || defined(slug.current))] | order(title asc) {
114
133
  title,
@@ -193,6 +212,68 @@ export const ALL_BLOG_ARTICLES_QUERY = defineQuery(`
193
212
  }
194
213
  `)
195
214
 
215
+ export const BLOG_ARTICLES_PAGINATED_QUERY = defineQuery(`
216
+ *[
217
+ _type == "page" &&
218
+ pageFolder->slug.current == "blog" &&
219
+ defined(slug.current) &&
220
+ slug.current != "" &&
221
+ slug.current != "/" &&
222
+ (
223
+ !defined($category) ||
224
+ $category == "" ||
225
+ $category in pageBuilder[_ref in *[_type == "blogContent"]._id][0]->categories[]->slug.current
226
+ )
227
+ ] | order(_updatedAt desc)[$offset...$offset + $limit] {
228
+ _id,
229
+ title,
230
+ "slug": slug,
231
+ "resolvedSlug": ${pageResolvedSlugExpression},
232
+ "blogContent": pageBuilder[_ref in *[_type == "blogContent"]._id][0]->{
233
+ thumbnail{
234
+ ...,
235
+ alt
236
+ },
237
+ categories[]->{
238
+ _id,
239
+ title,
240
+ slug
241
+ },
242
+ date,
243
+ author->{
244
+ _id,
245
+ name,
246
+ avatar
247
+ }
248
+ },
249
+ metadata,
250
+ _updatedAt
251
+ }
252
+ `)
253
+
254
+ export const BLOG_ARTICLES_COUNT_QUERY = defineQuery(`
255
+ count(*[
256
+ _type == "page" &&
257
+ pageFolder->slug.current == "blog" &&
258
+ defined(slug.current) &&
259
+ slug.current != "" &&
260
+ slug.current != "/" &&
261
+ (
262
+ !defined($category) ||
263
+ $category == "" ||
264
+ $category in pageBuilder[_ref in *[_type == "blogContent"]._id][0]->categories[]->slug.current
265
+ )
266
+ ])
267
+ `)
268
+
269
+ export const ALL_BLOG_CATEGORIES_QUERY = defineQuery(`
270
+ *[_type == "blogCategory"] | order(title asc) {
271
+ _id,
272
+ title,
273
+ slug
274
+ }
275
+ `)
276
+
196
277
  // Company Data
197
278
  export const COMPANY_DATA_QUERY = defineQuery(`
198
279
  *[_type == "companyData"][0]{
@@ -235,47 +316,79 @@ const navMegaMenuProjection = `
235
316
  }
236
317
  `
237
318
 
238
- export const NAVBAR_QUERY = defineQuery(`
239
- *[_type == "navbar"][0]{
240
- logo{
241
- ...,
242
- asset->{
243
- _id,
244
- url,
245
- metadata { dimensions }
246
- }
247
- },
248
- navigationItems[]{
249
- _key,
250
- title,
251
- itemType,
252
- ${navLinkProjection},
253
- megaMenu{
254
- ${navMegaMenuProjection}
255
- }
319
+ const navbarProjection = `
320
+ logo{
321
+ ...,
322
+ asset->{
323
+ _id,
324
+ url,
325
+ metadata { dimensions }
326
+ }
327
+ },
328
+ navigationItems[]{
329
+ _key,
330
+ title,
331
+ itemType,
332
+ ${navLinkProjection},
333
+ megaMenu{
334
+ ${navMegaMenuProjection}
335
+ }
336
+ },
337
+ ctaButtons[]{
338
+ _key,
339
+ label,
340
+ "link": link[0]{
341
+ ${linkItemProjection}
256
342
  },
257
- ctaButtons[]{
343
+ variant
344
+ }
345
+ `
346
+
347
+ const footerProjection = `
348
+ links[]{
349
+ _key,
350
+ title,
351
+ items[]{
258
352
  _key,
259
353
  label,
260
- "link": link[0]{
261
- ${linkItemProjection}
262
- },
263
- variant
354
+ href
264
355
  }
265
356
  }
357
+ `
358
+
359
+ const companyDataProjection = `
360
+ socialLinks[]{
361
+ _key,
362
+ name,
363
+ icon,
364
+ url,
365
+ label
366
+ }
367
+ `
368
+
369
+ export const NAVBAR_QUERY = defineQuery(`
370
+ *[_type == "navbar"][0]{
371
+ ${navbarProjection}
372
+ }
266
373
  `)
267
374
 
268
375
  // Footer
269
376
  export const FOOTER_QUERY = defineQuery(`
270
377
  *[_type == "footer"][0]{
271
- links[]{
272
- _key,
273
- title,
274
- items[]{
275
- _key,
276
- label,
277
- href
278
- }
378
+ ${footerProjection}
379
+ }
380
+ `)
381
+
382
+ export const SITE_LAYOUT_QUERY = defineQuery(`
383
+ {
384
+ "navbar": *[_type == "navbar"][0]{
385
+ ${navbarProjection}
386
+ },
387
+ "footer": *[_type == "footer"][0]{
388
+ ${footerProjection}
389
+ },
390
+ "companyData": *[_type == "companyData"][0]{
391
+ ${companyDataProjection}
279
392
  }
280
393
  }
281
394
  `)
@@ -1,14 +1,11 @@
1
1
  import { table } from "@sanity/table"
2
2
  import { defineConfig } from "sanity"
3
- import {
4
- defineDocuments,
5
- defineLocations,
6
- presentationTool,
7
- } from "sanity/presentation"
8
3
  import { structureTool } from "sanity/structure"
9
4
  import { media } from "sanity-plugin-media"
10
5
  import { createConfirmPublishAction } from "./confirm-publish-action"
11
- import { dataset, previewURL, projectId } from "./env"
6
+ import { HOMEPAGE_DOCUMENT_ID } from "./constants"
7
+ import { dataset, projectId } from "./env"
8
+ import { presentation } from "./presentation"
12
9
  import { schema } from "./schemas"
13
10
  import { singletonComponentTypes } from "./singletons"
14
11
  import { structure } from "./structure"
@@ -23,46 +20,7 @@ const singletonDocumentActions = new Set([
23
20
 
24
21
  const isSingletonDocument = (schemaType: string, documentId?: string) =>
25
22
  singletonComponentTypes.has(schemaType) ||
26
- (schemaType === "page" && documentId === "page-homepage")
27
-
28
- const MAX_FOLDER_DEPTH = 6
29
-
30
- const buildNestedSlugExpression = (
31
- parentReferenceField: string,
32
- leafSlugField: string
33
- ) => {
34
- const cases = Array.from({ length: MAX_FOLDER_DEPTH }, (_, index) => {
35
- const depth = MAX_FOLDER_DEPTH - index
36
- const parentSlugRefs = Array.from({ length: depth }, (_, parentIndex) => {
37
- const remainingDepth = depth - parentIndex - 1
38
- return `${parentReferenceField}${"->parentFolder".repeat(remainingDepth)}->slug.current`
39
- })
40
-
41
- const pathDefinedChecks = parentSlugRefs
42
- .map((field) => `defined(${field})`)
43
- .join(" && ")
44
-
45
- const childPath = [...parentSlugRefs, leafSlugField].join(' + "/" + ')
46
- const folderRootPath = parentSlugRefs.join(' + "/" + ')
47
-
48
- return [
49
- `${pathDefinedChecks} && ${leafSlugField} == "/" => ${folderRootPath}`,
50
- `${pathDefinedChecks} && defined(${leafSlugField}) => ${childPath}`,
51
- ]
52
- }).flat()
53
-
54
- return `
55
- select(
56
- ${cases.join(",\n ")},
57
- ${leafSlugField}
58
- )
59
- `
60
- }
61
-
62
- const pageResolvedSlugExpression = buildNestedSlugExpression(
63
- "pageFolder",
64
- "slug.current"
65
- )
23
+ (schemaType === "page" && documentId === HOMEPAGE_DOCUMENT_ID)
66
24
 
67
25
  export default defineConfig({
68
26
  basePath: "/studio",
@@ -151,60 +109,7 @@ export default defineConfig({
151
109
  },
152
110
  plugins: [
153
111
  structureTool({ structure }),
154
-
155
- presentationTool({
156
- name: "preview",
157
- title: "Preview",
158
- resolve: {
159
- // Map routes to documents and GROQ filters
160
- mainDocuments: defineDocuments([
161
- {
162
- route: "/",
163
- filter: '_type == "page" && _id == "page-homepage"',
164
- },
165
- // Page builder pages - all other slugs (supports nested paths)
166
- {
167
- route: "/:slug+",
168
- filter: `_type == "page" && ${pageResolvedSlugExpression} == $slug`,
169
- },
170
- ]),
171
- locations: {
172
- page: defineLocations({
173
- select: {
174
- _id: "_id",
175
- title: "title",
176
- slug: "slug.current",
177
- resolvedSlug: pageResolvedSlugExpression,
178
- },
179
- resolve: (doc) => {
180
- if (doc?._id === "page-homepage") {
181
- return {
182
- locations: [{ title: doc?.title || "Homepage", href: "/" }],
183
- }
184
- }
185
- if (doc?.resolvedSlug) {
186
- return {
187
- locations: [
188
- {
189
- title: doc?.title || "Page",
190
- href: `/${doc.resolvedSlug}`,
191
- },
192
- ],
193
- }
194
- }
195
- return { locations: [] }
196
- },
197
- }),
198
- },
199
- },
200
- previewUrl: {
201
- origin: previewURL,
202
- draftMode: {
203
- enable: "/api/draft-mode/enable",
204
- disable: "/api/draft-mode/disable",
205
- },
206
- },
207
- }),
112
+ presentation,
208
113
  media(),
209
114
  table(),
210
115
  ],
@@ -1,6 +1,8 @@
1
1
  import withBundleAnalyzer from "@next/bundle-analyzer"
2
2
  import type { NextConfig } from "next"
3
3
 
4
+
5
+
4
6
  const nextConfig: NextConfig = {
5
7
  reactStrictMode: true,
6
8
  reactCompiler: true,
@@ -62,6 +64,7 @@ const nextConfig: NextConfig = {
62
64
  browserToTerminal: true,
63
65
  },
64
66
  experimental: {
67
+ prefetchInlining: true,
65
68
  optimizePackageImports: [
66
69
  "@react-three/drei",
67
70
  "@react-three/fiber",
@@ -39,13 +39,11 @@
39
39
  "react-use": "^17.6.0",
40
40
  "sanity": "^5.17.1",
41
41
  "sanity-plugin-media": "^4.1.1",
42
- "schema-dts": "^2.0.0",
43
42
  "tailwind-merge": "^3.5.0",
44
43
  "zod": "^4.3.6"
45
44
  },
46
45
  "devDependencies": {
47
46
  "@biomejs/biome": "2.4.8",
48
- "@clack/prompts": "^1.1.0",
49
47
  "@csstools/postcss-global-data": "^4.0.0",
50
48
  "@next/bundle-analyzer": "16.2.1",
51
49
  "@svgr/webpack": "^8.1.0",
@@ -59,6 +57,7 @@
59
57
  "cross-env": "^10.1.0",
60
58
  "postcss-functions": "^4.0.2",
61
59
  "postcss-preset-env": "^11.2.0",
60
+ "schema-dts": "^2.0.0",
62
61
  "tailwindcss": "^4.2.2",
63
62
  "typescript": "^5.9.3"
64
63
  },
@@ -1,28 +0,0 @@
1
- import { sanityFetch } from "@/lib/integrations/sanity/live"
2
- import { ALL_BLOG_ARTICLES_QUERY } from "@/lib/integrations/sanity/queries"
3
- import { ContentGrid } from "./content-grid"
4
- import type { ContentCollectionBlock } from "./types"
5
-
6
- type ContentCollectionProps = {
7
- block: ContentCollectionBlock
8
- }
9
-
10
- export async function ContentCollection({ block }: ContentCollectionProps) {
11
- const { data: articles } = await sanityFetch({
12
- query: ALL_BLOG_ARTICLES_QUERY,
13
- })
14
-
15
- // @ts-ignore
16
- if (!articles?.length) return null
17
-
18
- return (
19
- <section className="flex flex-col gap-8 py-8">
20
- {block.subtitle ? (
21
- <h2 className="font-medium text-2xl leading-tight">
22
- {block.subtitle}
23
- </h2>
24
- ) : null}
25
- <ContentGrid articles={articles} />
26
- </section>
27
- )
28
- }