@conduction/nextcloud-vue 2.3.0 → 2.4.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 +18 -2
- package/scripts/check-public-safe.js +115 -0
- package/src/public/__tests__/publicBlocks.spec.js +307 -0
- package/src/public/components/CnSiteCard.vue +178 -0
- package/src/public/components/CnSiteCardGrid.vue +98 -0
- package/src/public/components/CnSiteEmptyState.vue +172 -0
- package/src/public/components/CnSiteGlossary.vue +240 -0
- package/src/public/components/CnSiteHero.vue +239 -0
- package/src/public/components/CnSiteIcon.vue +90 -0
- package/src/public/components/CnSiteSearch.vue +173 -0
- package/src/public/components/CnSiteSection.vue +120 -0
- package/src/public/index.js +133 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
3
|
+
* SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
*
|
|
5
|
+
* PUBLIC-SAFE SITE BLOCKS — the entry point a portal renderer can import when
|
|
6
|
+
* it runs at a public origin with NO Nextcloud behind it.
|
|
7
|
+
*
|
|
8
|
+
* WHY THIS ENTRY POINT EXISTS AT ALL
|
|
9
|
+
*
|
|
10
|
+
* nc-vue's main entry is deeply coupled to the Nextcloud runtime: measured on
|
|
11
|
+
* the published build, 154 files reference `@nextcloud/axios` and 157
|
|
12
|
+
* reference `@nextcloud/router`. That is correct for an app rendering inside
|
|
13
|
+
* Nextcloud and fatal for one rendering at `https://portaal.gemeente.nl`,
|
|
14
|
+
* where there is no `OC` global, no session and no translation bundle.
|
|
15
|
+
*
|
|
16
|
+
* WHY THESE ARE NEW COMPONENTS RATHER THAN RE-EXPORTS
|
|
17
|
+
*
|
|
18
|
+
* The first plan was to re-export the existing widgets that "looked clean".
|
|
19
|
+
* A DIRECT import check agreed: 12 of 13 candidates had no `@nextcloud/*`
|
|
20
|
+
* import in their own file. A TRANSITIVE check — following relative imports
|
|
21
|
+
* through the tree — inverted that result completely:
|
|
22
|
+
*
|
|
23
|
+
* CnTextWidget -> @nextcloud/l10n
|
|
24
|
+
* CnHeaderWidget -> @nextcloud/l10n, @nextcloud/router
|
|
25
|
+
* CnCardGrid -> @nextcloud/l10n, @nextcloud/vue,
|
|
26
|
+
* @nextcloud/auth, @nextcloud/event-bus
|
|
27
|
+
* ... 12 of 13 unsafe
|
|
28
|
+
*
|
|
29
|
+
* Only `CnCard` was clean all the way down. Re-exporting the rest under a
|
|
30
|
+
* name promising public safety would have shipped a guarantee that the first
|
|
31
|
+
* public deployment disproved — and it would have failed at RUNTIME, in a
|
|
32
|
+
* browser, on a government portal, rather than at build time here.
|
|
33
|
+
*
|
|
34
|
+
* So these blocks take their strings as PROPS instead of calling `t()`. That
|
|
35
|
+
* single decision is what keeps them portable: `@nextcloud/l10n` is the
|
|
36
|
+
* dependency almost every existing widget trips over.
|
|
37
|
+
*
|
|
38
|
+
* THE GUARANTEE IS CHECKED, NOT ASSERTED. `npm run check:public-safe` walks
|
|
39
|
+
* this entry's transitive imports and fails on any `@nextcloud/*`. A comment
|
|
40
|
+
* claiming purity is worth nothing; the check is in CI.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
import CnSiteCard from './components/CnSiteCard.vue'
|
|
44
|
+
import CnSiteCardGrid from './components/CnSiteCardGrid.vue'
|
|
45
|
+
import CnSiteEmptyState from './components/CnSiteEmptyState.vue'
|
|
46
|
+
import CnSiteGlossary from './components/CnSiteGlossary.vue'
|
|
47
|
+
import CnSiteHero from './components/CnSiteHero.vue'
|
|
48
|
+
import CnSiteIcon from './components/CnSiteIcon.vue'
|
|
49
|
+
import CnSiteSearch from './components/CnSiteSearch.vue'
|
|
50
|
+
import CnSiteSection from './components/CnSiteSection.vue'
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
CnSiteCard,
|
|
54
|
+
CnSiteCardGrid,
|
|
55
|
+
CnSiteEmptyState,
|
|
56
|
+
CnSiteGlossary,
|
|
57
|
+
CnSiteHero,
|
|
58
|
+
CnSiteIcon,
|
|
59
|
+
CnSiteSearch,
|
|
60
|
+
CnSiteSection,
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The block vocabulary, keyed by the `widgetKey` a page body declares.
|
|
65
|
+
*
|
|
66
|
+
* A REGISTRY rather than a switch in the consumer. A consumer that resolves
|
|
67
|
+
* blocks with `if (key === 'markdown')` cannot be extended without editing the
|
|
68
|
+
* consumer, which is how portaliq ended up supporting exactly one block type
|
|
69
|
+
* while this library already shipped thirty-four.
|
|
70
|
+
*
|
|
71
|
+
* Anything not in this map is UNKNOWN, and a renderer must say so visibly
|
|
72
|
+
* rather than render nothing — a page silently missing a block looks identical
|
|
73
|
+
* to a page that was authored empty.
|
|
74
|
+
*
|
|
75
|
+
* @type {Record<string, object>}
|
|
76
|
+
*/
|
|
77
|
+
export const siteBlockRegistry = {
|
|
78
|
+
hero: CnSiteHero,
|
|
79
|
+
search: CnSiteSearch,
|
|
80
|
+
section: CnSiteSection,
|
|
81
|
+
cardGrid: CnSiteCardGrid,
|
|
82
|
+
card: CnSiteCard,
|
|
83
|
+
emptyState: CnSiteEmptyState,
|
|
84
|
+
glossary: CnSiteGlossary,
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Blocks that are FULL-BLEED BANDS and carry their own container.
|
|
89
|
+
*
|
|
90
|
+
* A band paints edge to edge and constrains its content itself. Rendering one
|
|
91
|
+
* inside a host's content column silently shrinks it: measured against the NL
|
|
92
|
+
* Design System reference, a hero nested in the page container came out
|
|
93
|
+
* 1168px wide against the design's 1280, and no amount of styling inside the
|
|
94
|
+
* hero could recover the missing width because the clamp was an ancestor.
|
|
95
|
+
*
|
|
96
|
+
* The reference's own structure is the model — `main` is full-bleed and every
|
|
97
|
+
* `section` brings a `.container` — so a host must ask this before deciding
|
|
98
|
+
* whether to wrap a block.
|
|
99
|
+
*
|
|
100
|
+
* @param {string} key The block key.
|
|
101
|
+
* @return {boolean} True when the block must NOT be wrapped in a container.
|
|
102
|
+
*/
|
|
103
|
+
export function siteBlockIsBand(key) {
|
|
104
|
+
return SITE_BAND_BLOCKS.includes(key)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @type {Array<string>} The band block keys.
|
|
109
|
+
*/
|
|
110
|
+
export const SITE_BAND_BLOCKS = ['hero', 'section']
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Resolve a block component by key.
|
|
114
|
+
*
|
|
115
|
+
* @param {string} key The `widgetKey` from a page body.
|
|
116
|
+
* @return {object|null} The component, or null when the key is unknown.
|
|
117
|
+
*/
|
|
118
|
+
export function siteBlockFor(key) {
|
|
119
|
+
return siteBlockRegistry[key] || null
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* The keys this entry point can render.
|
|
124
|
+
*
|
|
125
|
+
* Exported so a consumer — or a test — can assert the vocabulary it depends on
|
|
126
|
+
* is actually present, rather than discovering a missing block as a blank area
|
|
127
|
+
* on a live page.
|
|
128
|
+
*
|
|
129
|
+
* @return {Array<string>} The known block keys.
|
|
130
|
+
*/
|
|
131
|
+
export function listSiteBlocks() {
|
|
132
|
+
return Object.keys(siteBlockRegistry)
|
|
133
|
+
}
|