@cavuno/board 1.31.0 → 1.32.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.
@@ -0,0 +1,232 @@
1
+ /**
2
+ * The board-chrome copy CATALOG (ADR-0059) — every user-visible string the
3
+ * registry blocks (and the starter's public routes) render, as a typed
4
+ * record per board language, beside the salary lexicon it patterns after:
5
+ * plain strings plus functions-per-key where counts/interpolation demand it.
6
+ * No i18n runtime, no provider — pure and RSC-safe.
7
+ *
8
+ * Resolution order (mirrors the hosted `BoardLabels` semantics exactly):
9
+ * catalog floor (this file) ⊕ API-served operator overrides
10
+ * (`board.context().labels`, the stored `jobBoardSettings.config.*Labels`
11
+ * records) ⊕ per-board generated-code overrides. `uiCopy(language, labels)`
12
+ * performs the first two; overrides use the hosted `nestedStr` rule — an
13
+ * absent, non-string, or blank value never wins.
14
+ *
15
+ * Languages: `en` is the SOURCE — byte-identical to what the registry
16
+ * blocks rendered before the catalog existed (en boards do not change), and
17
+ * to the hosted defaults for the route-level groups (nav/footer/breadcrumbs/
18
+ * pagination/blog). `de` is transcribed from startup-insider's stored
19
+ * operator overrides (prod, 2026-07-03) with native fills in the same
20
+ * informal register for the keys the golden tenant left at English defaults;
21
+ * board-brand-specific values (e.g. its "© … GmbH" copyright) stay operator
22
+ * data, not catalog floor. `fr` is a fresh set with no golden board behind
23
+ * it — the abstraction-prover. Unseeded languages fall back to `en`.
24
+ *
25
+ * Override-key alignment: within each group, keys that have a hosted stored
26
+ * counterpart carry the hosted key NAME (e.g. `featuredLabel`,
27
+ * `keywordPlaceholder`), so applying a stored override record is a plain
28
+ * same-key merge — no mapping table to drift. Keys with no hosted
29
+ * counterpart yet are new names in the same style; they become overridable
30
+ * the day hosted stores them.
31
+ */
32
+ /**
33
+ * The public-surfaces label groups (stored `jobBoardSettings.config` group
34
+ * names) that ride the v1 board context as the `labels` bag. CANONICAL —
35
+ * the API's server-side allowlist must list the same names (gated by
36
+ * `labelGroupsAlignment.test.ts` in apps/web).
37
+ */
38
+ declare const PUBLIC_LABEL_GROUPS: readonly ["jobCardLabels", "navLabels", "breadcrumbsLabels", "footerLabels", "entityLabels", "jobSearchLabels", "globalPaginationLabels", "blogSharedLabels", "salaryLabels"];
39
+ /**
40
+ * The operator-override bag as served by `GET /v1/boards/:identifier`
41
+ * (`labels`): the stored `jobBoardSettings.config` label records, verbatim,
42
+ * keyed by their config group names. Boards without overrides serve `{}`.
43
+ */
44
+ type BoardLabelOverrides = Partial<Record<(typeof PUBLIC_LABEL_GROUPS)[number], Record<string, string>>>;
45
+ interface JobCardCopy {
46
+ featuredLabel: string;
47
+ aiRankedLabel: string;
48
+ sortNewestLabel: string;
49
+ sortSalaryHighLabel: string;
50
+ }
51
+ interface JobSearchCopy {
52
+ headingJobs: string;
53
+ keywordLabel: string;
54
+ keywordPlaceholder: string;
55
+ locationLabel: string;
56
+ locationPlaceholder: string;
57
+ workplacePlaceholder: string;
58
+ anyWorkplaceLabel: string;
59
+ typePlaceholder: string;
60
+ anyTypeLabel: string;
61
+ sortPlaceholder: string;
62
+ loadMoreLabel: string;
63
+ noJobsMatchText: string;
64
+ }
65
+ interface JobDetailCopy {
66
+ categoriesHeading: string;
67
+ skillsHeading: string;
68
+ additionalDetailsHeading: string;
69
+ customFieldYesLabel: string;
70
+ customFieldNoLabel: string;
71
+ locationsLabel: string;
72
+ workPermitsLabel: string;
73
+ timezonesLabel: string;
74
+ educationLabel: string;
75
+ experienceLabel: string;
76
+ worldwideLabel: string;
77
+ noExperienceRequiredLabel: string;
78
+ /** Fact-row value for a minimum-experience requirement, e.g. `3+ years`. */
79
+ experienceYears(years: number): string;
80
+ /** Header timestamp line, receives the already-formatted relative date. */
81
+ posted(published: string): string;
82
+ noDescriptionText: string;
83
+ viewCompanyProfileLabel: string;
84
+ similarJobsHeading: string;
85
+ breadcrumbAriaLabel: string;
86
+ }
87
+ interface ApplyCopy {
88
+ applyButtonText: string;
89
+ applyingLabel: string;
90
+ applyOnEmployerSiteLabel: string;
91
+ signInToApplyLabel: string;
92
+ verifyEmailToApplyLabel: string;
93
+ appliedViewApplicationsLabel: string;
94
+ applicationSubmitError: string;
95
+ }
96
+ interface AlertsCopy {
97
+ jobAlertTitle: string;
98
+ jobAlertEmailPlaceholder: string;
99
+ jobAlertButtonText: string;
100
+ subscribingLabel: string;
101
+ jobAlertSuccessToast: string;
102
+ jobAlertDuplicateToast: string;
103
+ jobAlertErrorToast: string;
104
+ sectionAriaLabel: string;
105
+ emailAriaLabel: string;
106
+ submitAriaLabel: string;
107
+ }
108
+ interface CopyLinkCopy {
109
+ copyLinkLabel: string;
110
+ copiedLabel: string;
111
+ ariaLabel: string;
112
+ }
113
+ interface SalaryCopy {
114
+ /** Headline over the average range — hosted `comparisonHeadlineAverage`. */
115
+ comparisonHeadlineAverage: string;
116
+ perYearSuffix: string;
117
+ comparisonPercentile25Label: string;
118
+ medianLabel: string;
119
+ comparisonPercentile75Label: string;
120
+ basedOnLabel: string;
121
+ seniorityTableHeaderLevel: string;
122
+ seniorityTableHeaderAvg: string;
123
+ boardBaselineLabel: string;
124
+ /** Diff column header of the seniority table — hosted `seniorityTableHeaderDiff`. */
125
+ seniorityTableHeaderDiff: string;
126
+ faqHeading: string;
127
+ }
128
+ interface NavCopy {
129
+ home: string;
130
+ companies: string;
131
+ pricing: string;
132
+ talent: string;
133
+ post: string;
134
+ blog: string;
135
+ }
136
+ interface FooterCopy {
137
+ forCandidatesHeading: string;
138
+ forCompaniesHeading: string;
139
+ resourcesHeading: string;
140
+ aboutHeading: string;
141
+ websiteLabel: string;
142
+ aboutLabel: string;
143
+ contactLabel: string;
144
+ locationsLabel: string;
145
+ salariesLabel: string;
146
+ sitemapLabel: string;
147
+ termsOfServiceLabel: string;
148
+ privacyPolicyLabel: string;
149
+ cookiePolicyLabel: string;
150
+ impressumLabel: string;
151
+ allRightsReservedText: string;
152
+ /** Template, supports `{{year}}` and `{{board_name}}`. */
153
+ copyrightPrefix: string;
154
+ poweredByText: string;
155
+ /** Template, supports `{{board_name}}`. */
156
+ defaultDescription: string;
157
+ }
158
+ interface BreadcrumbsCopy {
159
+ home: string;
160
+ jobs: string;
161
+ locations: string;
162
+ salaries: string;
163
+ companies: string;
164
+ skills: string;
165
+ titles: string;
166
+ blog: string;
167
+ post: string;
168
+ pricing: string;
169
+ about: string;
170
+ impressum: string;
171
+ termsOfService: string;
172
+ privacyPolicy: string;
173
+ cookiePolicy: string;
174
+ talent: string;
175
+ }
176
+ interface PaginationCopy {
177
+ ariaLabel: string;
178
+ previousLabel: string;
179
+ nextLabel: string;
180
+ }
181
+ interface BlogCopy {
182
+ bylineLabel: string;
183
+ readingTimeLabel: string;
184
+ searchLabel: string;
185
+ searchPlaceholder: string;
186
+ clearButtonLabel: string;
187
+ tagFilterLabel: string;
188
+ tagFilterAllLabel: string;
189
+ emptyTitle: string;
190
+ emptyDescription: string;
191
+ emptyResetLabel: string;
192
+ }
193
+ /**
194
+ * Entity nouns for count lines (`{count} {jobs}`). Lowercase in `en` —
195
+ * the registry blocks' existing inline form — where the hosted defaults
196
+ * capitalize; German capitalizes its nouns either way.
197
+ */
198
+ interface EntityCopy {
199
+ jobSingular: string;
200
+ jobPlural: string;
201
+ companySingular: string;
202
+ companyPlural: string;
203
+ }
204
+ interface UiCopy {
205
+ jobCard: JobCardCopy;
206
+ jobSearch: JobSearchCopy;
207
+ jobDetail: JobDetailCopy;
208
+ apply: ApplyCopy;
209
+ alerts: AlertsCopy;
210
+ copyLink: CopyLinkCopy;
211
+ salary: SalaryCopy;
212
+ nav: NavCopy;
213
+ footer: FooterCopy;
214
+ breadcrumbs: BreadcrumbsCopy;
215
+ pagination: PaginationCopy;
216
+ blog: BlogCopy;
217
+ entity: EntityCopy;
218
+ }
219
+ /**
220
+ * Resolve the chrome copy for a board language ⊕ its operator overrides
221
+ * (`board.context().labels`). Unseeded languages fall back to the English
222
+ * source. Pure and RSC-safe — call it wherever the `language` prop already
223
+ * flows.
224
+ *
225
+ * @example
226
+ * uiCopy('de').jobCard.featuredLabel; // "Hervorgehoben"
227
+ * uiCopy('de', board.labels).jobCard.featuredLabel; // "Top Job" (override)
228
+ * uiCopy('xx').jobCard.featuredLabel; // "Featured" (fallback)
229
+ */
230
+ declare function uiCopy(language: string | undefined, labels?: BoardLabelOverrides): UiCopy;
231
+
232
+ export { type AlertsCopy as A, type BoardLabelOverrides as B, type CopyLinkCopy as C, type EntityCopy as E, type FooterCopy as F, type JobCardCopy as J, type NavCopy as N, PUBLIC_LABEL_GROUPS as P, type SalaryCopy as S, type UiCopy as U, type ApplyCopy as a, type BlogCopy as b, type BreadcrumbsCopy as c, type JobDetailCopy as d, type JobSearchCopy as e, type PaginationCopy as f, uiCopy as u };
@@ -0,0 +1,232 @@
1
+ /**
2
+ * The board-chrome copy CATALOG (ADR-0059) — every user-visible string the
3
+ * registry blocks (and the starter's public routes) render, as a typed
4
+ * record per board language, beside the salary lexicon it patterns after:
5
+ * plain strings plus functions-per-key where counts/interpolation demand it.
6
+ * No i18n runtime, no provider — pure and RSC-safe.
7
+ *
8
+ * Resolution order (mirrors the hosted `BoardLabels` semantics exactly):
9
+ * catalog floor (this file) ⊕ API-served operator overrides
10
+ * (`board.context().labels`, the stored `jobBoardSettings.config.*Labels`
11
+ * records) ⊕ per-board generated-code overrides. `uiCopy(language, labels)`
12
+ * performs the first two; overrides use the hosted `nestedStr` rule — an
13
+ * absent, non-string, or blank value never wins.
14
+ *
15
+ * Languages: `en` is the SOURCE — byte-identical to what the registry
16
+ * blocks rendered before the catalog existed (en boards do not change), and
17
+ * to the hosted defaults for the route-level groups (nav/footer/breadcrumbs/
18
+ * pagination/blog). `de` is transcribed from startup-insider's stored
19
+ * operator overrides (prod, 2026-07-03) with native fills in the same
20
+ * informal register for the keys the golden tenant left at English defaults;
21
+ * board-brand-specific values (e.g. its "© … GmbH" copyright) stay operator
22
+ * data, not catalog floor. `fr` is a fresh set with no golden board behind
23
+ * it — the abstraction-prover. Unseeded languages fall back to `en`.
24
+ *
25
+ * Override-key alignment: within each group, keys that have a hosted stored
26
+ * counterpart carry the hosted key NAME (e.g. `featuredLabel`,
27
+ * `keywordPlaceholder`), so applying a stored override record is a plain
28
+ * same-key merge — no mapping table to drift. Keys with no hosted
29
+ * counterpart yet are new names in the same style; they become overridable
30
+ * the day hosted stores them.
31
+ */
32
+ /**
33
+ * The public-surfaces label groups (stored `jobBoardSettings.config` group
34
+ * names) that ride the v1 board context as the `labels` bag. CANONICAL —
35
+ * the API's server-side allowlist must list the same names (gated by
36
+ * `labelGroupsAlignment.test.ts` in apps/web).
37
+ */
38
+ declare const PUBLIC_LABEL_GROUPS: readonly ["jobCardLabels", "navLabels", "breadcrumbsLabels", "footerLabels", "entityLabels", "jobSearchLabels", "globalPaginationLabels", "blogSharedLabels", "salaryLabels"];
39
+ /**
40
+ * The operator-override bag as served by `GET /v1/boards/:identifier`
41
+ * (`labels`): the stored `jobBoardSettings.config` label records, verbatim,
42
+ * keyed by their config group names. Boards without overrides serve `{}`.
43
+ */
44
+ type BoardLabelOverrides = Partial<Record<(typeof PUBLIC_LABEL_GROUPS)[number], Record<string, string>>>;
45
+ interface JobCardCopy {
46
+ featuredLabel: string;
47
+ aiRankedLabel: string;
48
+ sortNewestLabel: string;
49
+ sortSalaryHighLabel: string;
50
+ }
51
+ interface JobSearchCopy {
52
+ headingJobs: string;
53
+ keywordLabel: string;
54
+ keywordPlaceholder: string;
55
+ locationLabel: string;
56
+ locationPlaceholder: string;
57
+ workplacePlaceholder: string;
58
+ anyWorkplaceLabel: string;
59
+ typePlaceholder: string;
60
+ anyTypeLabel: string;
61
+ sortPlaceholder: string;
62
+ loadMoreLabel: string;
63
+ noJobsMatchText: string;
64
+ }
65
+ interface JobDetailCopy {
66
+ categoriesHeading: string;
67
+ skillsHeading: string;
68
+ additionalDetailsHeading: string;
69
+ customFieldYesLabel: string;
70
+ customFieldNoLabel: string;
71
+ locationsLabel: string;
72
+ workPermitsLabel: string;
73
+ timezonesLabel: string;
74
+ educationLabel: string;
75
+ experienceLabel: string;
76
+ worldwideLabel: string;
77
+ noExperienceRequiredLabel: string;
78
+ /** Fact-row value for a minimum-experience requirement, e.g. `3+ years`. */
79
+ experienceYears(years: number): string;
80
+ /** Header timestamp line, receives the already-formatted relative date. */
81
+ posted(published: string): string;
82
+ noDescriptionText: string;
83
+ viewCompanyProfileLabel: string;
84
+ similarJobsHeading: string;
85
+ breadcrumbAriaLabel: string;
86
+ }
87
+ interface ApplyCopy {
88
+ applyButtonText: string;
89
+ applyingLabel: string;
90
+ applyOnEmployerSiteLabel: string;
91
+ signInToApplyLabel: string;
92
+ verifyEmailToApplyLabel: string;
93
+ appliedViewApplicationsLabel: string;
94
+ applicationSubmitError: string;
95
+ }
96
+ interface AlertsCopy {
97
+ jobAlertTitle: string;
98
+ jobAlertEmailPlaceholder: string;
99
+ jobAlertButtonText: string;
100
+ subscribingLabel: string;
101
+ jobAlertSuccessToast: string;
102
+ jobAlertDuplicateToast: string;
103
+ jobAlertErrorToast: string;
104
+ sectionAriaLabel: string;
105
+ emailAriaLabel: string;
106
+ submitAriaLabel: string;
107
+ }
108
+ interface CopyLinkCopy {
109
+ copyLinkLabel: string;
110
+ copiedLabel: string;
111
+ ariaLabel: string;
112
+ }
113
+ interface SalaryCopy {
114
+ /** Headline over the average range — hosted `comparisonHeadlineAverage`. */
115
+ comparisonHeadlineAverage: string;
116
+ perYearSuffix: string;
117
+ comparisonPercentile25Label: string;
118
+ medianLabel: string;
119
+ comparisonPercentile75Label: string;
120
+ basedOnLabel: string;
121
+ seniorityTableHeaderLevel: string;
122
+ seniorityTableHeaderAvg: string;
123
+ boardBaselineLabel: string;
124
+ /** Diff column header of the seniority table — hosted `seniorityTableHeaderDiff`. */
125
+ seniorityTableHeaderDiff: string;
126
+ faqHeading: string;
127
+ }
128
+ interface NavCopy {
129
+ home: string;
130
+ companies: string;
131
+ pricing: string;
132
+ talent: string;
133
+ post: string;
134
+ blog: string;
135
+ }
136
+ interface FooterCopy {
137
+ forCandidatesHeading: string;
138
+ forCompaniesHeading: string;
139
+ resourcesHeading: string;
140
+ aboutHeading: string;
141
+ websiteLabel: string;
142
+ aboutLabel: string;
143
+ contactLabel: string;
144
+ locationsLabel: string;
145
+ salariesLabel: string;
146
+ sitemapLabel: string;
147
+ termsOfServiceLabel: string;
148
+ privacyPolicyLabel: string;
149
+ cookiePolicyLabel: string;
150
+ impressumLabel: string;
151
+ allRightsReservedText: string;
152
+ /** Template, supports `{{year}}` and `{{board_name}}`. */
153
+ copyrightPrefix: string;
154
+ poweredByText: string;
155
+ /** Template, supports `{{board_name}}`. */
156
+ defaultDescription: string;
157
+ }
158
+ interface BreadcrumbsCopy {
159
+ home: string;
160
+ jobs: string;
161
+ locations: string;
162
+ salaries: string;
163
+ companies: string;
164
+ skills: string;
165
+ titles: string;
166
+ blog: string;
167
+ post: string;
168
+ pricing: string;
169
+ about: string;
170
+ impressum: string;
171
+ termsOfService: string;
172
+ privacyPolicy: string;
173
+ cookiePolicy: string;
174
+ talent: string;
175
+ }
176
+ interface PaginationCopy {
177
+ ariaLabel: string;
178
+ previousLabel: string;
179
+ nextLabel: string;
180
+ }
181
+ interface BlogCopy {
182
+ bylineLabel: string;
183
+ readingTimeLabel: string;
184
+ searchLabel: string;
185
+ searchPlaceholder: string;
186
+ clearButtonLabel: string;
187
+ tagFilterLabel: string;
188
+ tagFilterAllLabel: string;
189
+ emptyTitle: string;
190
+ emptyDescription: string;
191
+ emptyResetLabel: string;
192
+ }
193
+ /**
194
+ * Entity nouns for count lines (`{count} {jobs}`). Lowercase in `en` —
195
+ * the registry blocks' existing inline form — where the hosted defaults
196
+ * capitalize; German capitalizes its nouns either way.
197
+ */
198
+ interface EntityCopy {
199
+ jobSingular: string;
200
+ jobPlural: string;
201
+ companySingular: string;
202
+ companyPlural: string;
203
+ }
204
+ interface UiCopy {
205
+ jobCard: JobCardCopy;
206
+ jobSearch: JobSearchCopy;
207
+ jobDetail: JobDetailCopy;
208
+ apply: ApplyCopy;
209
+ alerts: AlertsCopy;
210
+ copyLink: CopyLinkCopy;
211
+ salary: SalaryCopy;
212
+ nav: NavCopy;
213
+ footer: FooterCopy;
214
+ breadcrumbs: BreadcrumbsCopy;
215
+ pagination: PaginationCopy;
216
+ blog: BlogCopy;
217
+ entity: EntityCopy;
218
+ }
219
+ /**
220
+ * Resolve the chrome copy for a board language ⊕ its operator overrides
221
+ * (`board.context().labels`). Unseeded languages fall back to the English
222
+ * source. Pure and RSC-safe — call it wherever the `language` prop already
223
+ * flows.
224
+ *
225
+ * @example
226
+ * uiCopy('de').jobCard.featuredLabel; // "Hervorgehoben"
227
+ * uiCopy('de', board.labels).jobCard.featuredLabel; // "Top Job" (override)
228
+ * uiCopy('xx').jobCard.featuredLabel; // "Featured" (fallback)
229
+ */
230
+ declare function uiCopy(language: string | undefined, labels?: BoardLabelOverrides): UiCopy;
231
+
232
+ export { type AlertsCopy as A, type BoardLabelOverrides as B, type CopyLinkCopy as C, type EntityCopy as E, type FooterCopy as F, type JobCardCopy as J, type NavCopy as N, PUBLIC_LABEL_GROUPS as P, type SalaryCopy as S, type UiCopy as U, type ApplyCopy as a, type BlogCopy as b, type BreadcrumbsCopy as c, type JobDetailCopy as d, type JobSearchCopy as e, type PaginationCopy as f, uiCopy as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cavuno/board",
3
- "version": "1.31.0",
3
+ "version": "1.32.0",
4
4
  "description": "Typed isomorphic client for the Cavuno Board API",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.31.0",
2
+ "version": "1.32.0",
3
3
  "skills": [
4
4
  {
5
5
  "name": "cavuno-board-account",