@uniweb/kit 0.9.0 → 0.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniweb/kit",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "Standard component library for Uniweb foundations",
5
5
  "type": "module",
6
6
  "exports": {
@@ -38,7 +38,7 @@
38
38
  "fuse.js": "^7.0.0",
39
39
  "shiki": "^3.0.0",
40
40
  "tailwind-merge": "^2.6.0",
41
- "@uniweb/core": "0.7.0"
41
+ "@uniweb/core": "0.7.1"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "react": "^18.0.0 || ^19.0.0",
@@ -3,11 +3,26 @@
3
3
  *
4
4
  * When a collection declares `deferred: [...]` in `site.yml`, the cascade
5
5
  * payload omits the deferred fields. The full record (with deferred
6
- * fields included) lives in a per-record file at
7
- * `/data/<collection>/<slug>.json`. On dynamic-route pages, the framework
8
- * routes the singular detail there automatically. Anywhere else (a card
9
- * grid that wants to show a hover-card preview, a modal that opens an
10
- * article body) use this hook.
6
+ * fields included) lives somewhere — either at a per-record file the
7
+ * build emits, or at an author-declared API endpoint. This hook fetches
8
+ * that full record on demand.
9
+ *
10
+ * Two source patterns, picked automatically from the collection's
11
+ * declaration:
12
+ *
13
+ * - Markdown-backed collections (declared with `path:` in site.yml).
14
+ * The build emits `/data/<collection>/<slug>.json` per record. The
15
+ * hook fetches that path.
16
+ *
17
+ * - API-backed collections (declared with `url:` in site.yml plus a
18
+ * `detailUrl:` pattern). The hook substitutes `{slug}` in the
19
+ * pattern and fetches that URL.
20
+ *
21
+ * On dynamic-route pages the framework routes the singular detail to
22
+ * the same source automatically (entity-store auto-injection). This
23
+ * hook is for the elsewhere case — a hover-card preview, a modal that
24
+ * opens an article body, a related-items strip that wants summaries
25
+ * everywhere except the one being highlighted.
11
26
  *
12
27
  * Returns `{ data, error, loading }` like `useFetched`. Shares the same
13
28
  * cache. Pass null/undefined to skip without subscribing.
@@ -29,6 +44,7 @@
29
44
  * }
30
45
  */
31
46
 
47
+ import { getUniweb } from '@uniweb/core'
32
48
  import { useFetched } from './useFetched.js'
33
49
 
34
50
  /**
@@ -36,16 +52,39 @@ import { useFetched } from './useFetched.js'
36
52
  * Must have a `slug` field. Pass null/undefined to skip the fetch.
37
53
  * @param {Object} [options]
38
54
  * @param {string} options.collection - The collection name (e.g., 'articles').
39
- * Required when record is non-null. Used to build the per-record file URL
55
+ * Required when record is non-null. Used to look up the collection's
56
+ * `detailUrl:` (if declared) or fall back to the static-file default
40
57
  * `/data/<collection>/<slug>.json`.
41
58
  * @returns {{ data: any, error: string|null, loading: boolean }}
42
59
  */
43
60
  export function useEntityDetail(record, options = {}) {
44
61
  const collection = options?.collection
45
- const request = (record && record.slug && collection)
46
- ? { path: `/data/${collection}/${record.slug}.json`, schema: collection }
47
- : null
62
+ const request = buildDetailRequest(record, collection)
48
63
  return useFetched(request)
49
64
  }
50
65
 
66
+ function buildDetailRequest(record, collection) {
67
+ const slug = record?.slug
68
+ if (!slug || !collection) return null
69
+
70
+ // Look up the collection's per-record source pattern. Authors with
71
+ // API-backed collections declare `detailUrl:` in site.yml; markdown
72
+ // collections leave it null and use the static-file default.
73
+ const website = getUniweb()?.activeWebsite
74
+ const collConfig = website?.config?.collections?.[collection]
75
+ const detailUrl = (collConfig && typeof collConfig.detailUrl === 'string')
76
+ ? collConfig.detailUrl
77
+ : null
78
+
79
+ if (detailUrl) {
80
+ // Substitute {slug} into the author-declared pattern and use url:
81
+ // (the source is remote).
82
+ const url = detailUrl.replace(/\{slug\}/g, encodeURIComponent(slug))
83
+ return { url, schema: collection }
84
+ }
85
+
86
+ // Static-file default — the build emitted per-record JSON files.
87
+ return { path: `/data/${collection}/${slug}.json`, schema: collection }
88
+ }
89
+
51
90
  export default useEntityDetail