@uniweb/kit 0.19.1 → 0.19.3

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.19.1",
3
+ "version": "0.19.3",
4
4
  "description": "Standard component library for Uniweb foundations",
5
5
  "type": "module",
6
6
  "exports": {
@@ -43,10 +43,10 @@
43
43
  "shiki": "^3.0.0",
44
44
  "tailwind-merge": "^3.6.0",
45
45
  "temml": "^0.13.2",
46
- "@uniweb/core": "^0.29.2",
47
- "@uniweb/semantic-parser": "^1.4.0",
48
- "@uniweb/scene": "^0.1.3",
49
- "@uniweb/projections": "^0.7.2"
46
+ "@uniweb/semantic-parser": "^1.4.1",
47
+ "@uniweb/core": "^0.29.4",
48
+ "@uniweb/projections": "^0.7.3",
49
+ "@uniweb/scene": "^0.1.3"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "react": "^19.0.0",
@@ -43,7 +43,8 @@ import { useActiveRoute } from './useActiveRoute.js'
43
43
  * Pull headings out of the page's own content — available during prerender.
44
44
  *
45
45
  * Skips the headings the semantic parser claimed as the section's own
46
- * title/pretitle/subtitle. In this framework a leading `###` is a pretitle and
46
+ * title/pretitle/subtitle. In this framework a `#>` label line is a pretitle
47
+ * (as is a smaller ordinary heading above the title, the older spelling) and
47
48
  * the `##` after the title is a subtitle — structure, not body headings — so a
48
49
  * typed section would otherwise open every contents rail with two entries no
49
50
  * reader recognises as sections of the article. An untyped document has none of
@@ -37,6 +37,24 @@
37
37
  * `isServiceEnabled(name)` exported here: ask the method directly —
38
38
  * `useWebsite().website.isServiceEnabled('booking')`. A one-liner can be added
39
39
  * if a real case appears.
40
+ *
41
+ * ## ⭐ THE ROSTER — one predicate per service, and the one deliberate exception
42
+ *
43
+ * The five below are every predicate the framework ships. **`records` has none,
44
+ * and that is deliberate on two counts**, both worth knowing before adding one:
45
+ *
46
+ * 1. **A foundation never gates UI on it.** The runtime fetches and fills
47
+ * `content.data`; a component reads what it declared and renders the empty
48
+ * case. There is no "draw or don't draw" decision to make.
49
+ * 2. ⛔ **`isServiceEnabled('records')` would give a WRONG answer.** That goes
50
+ * through `resolveService`, which needs only an endpoint — while the records
51
+ * lane additionally requires a `{locale}` placeholder and refuses a row
52
+ * without one (`resolveRecordsService`, `@uniweb/core/records-service`). So
53
+ * the predicate would report enabled where the lane declines. Adding one
54
+ * would introduce a disagreement, not close a gap.
55
+ *
56
+ * ⚠️ `booking` above is an illustration of the open registry, not a service the
57
+ * framework knows.
40
58
  */
41
59
 
42
60
  import { getUniweb } from '@uniweb/core'
@@ -60,7 +78,15 @@ function activeWebsite() {
60
78
  /**
61
79
  * Does this site have an app backend — accounts, per-visitor data, member
62
80
  * writes? The question to ask before drawing a sign-in affordance or any
63
- * control only a backend can answer. Re-exported by `@uniweb/api`.
81
+ * control only a backend can answer.
82
+ *
83
+ * ⚠️ **`@uniweb/api` exports its OWN `isApiEnabled`, it does not re-export this
84
+ * one** — *this line claimed it did until 2026-09-15.* Theirs tests
85
+ * `resolveBase(website) !== null` and takes an optional website; this one calls
86
+ * `isServiceEnabled('api')` on the active site. They agree — both bottom out in
87
+ * `resolveService(website, 'api')`, and the input that would split them is
88
+ * unreachable — but they are two implementations, so a change to either is not a
89
+ * change to both.
64
90
  */
65
91
  export function isApiEnabled() {
66
92
  return activeWebsite()?.isServiceEnabled('api') ?? false
@@ -83,7 +109,19 @@ export function isSubmitEnabled() {
83
109
  return activeWebsite()?.isServiceEnabled('submit') ?? false
84
110
  }
85
111
 
86
- /** Does this site have somewhere to send analytics events? */
112
+ /**
113
+ * Does this site have somewhere to send analytics events?
114
+ *
115
+ * ⛔ **Not a gate for emitting one.** `block.track()` and `useTracker()` are safe
116
+ * with no destination — they return having done nothing — and `useTracker`'s own
117
+ * doc says never to wrap them in a check. This is for UI *about* tracking: a
118
+ * consent banner, a settings toggle.
119
+ *
120
+ * ⚠️ **And tracking is not a capability a foundation supplies.** The runtime
121
+ * emits `page_view` / `outbound_click` / `section_view` for every foundation
122
+ * alike, so calling this says nothing about what this foundation contributes,
123
+ * and a foundation that never calls it still gets those events.
124
+ */
87
125
  export function isTrackingEnabled() {
88
126
  return activeWebsite()?.isServiceEnabled('tracking') ?? false
89
127
  }