@developer-overheid-nl/don-register-components 1.3.0 → 1.3.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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @developer-overheid-nl/don-register-components
2
2
 
3
+ ## 1.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - d8a39db: Bugfixes pagination parsers en facetfilters, description toegevoegd aan single-select.
8
+ - e5f0a52: Keep the publiccode filter state explicit in the OSS register.
9
+ Toggle filters now preserve both `true` and `false` values in the query string, and selected filter badges correctly toggle the publiccode filter instead of removing it.
10
+ - 0f983ad: Upgraded Astro to 6.4.2
11
+ - Updated dependencies [de238a8]
12
+ - Updated dependencies [0f983ad]
13
+ - @developer-overheid-nl/don-register-locales@1.2.1
14
+
3
15
  ## 1.3.0
4
16
 
5
17
  ### Minor Changes
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "license": "EUPL-1.2",
6
6
  "private": false,
7
7
  "type": "module",
8
- "version": "1.3.0",
8
+ "version": "1.3.1",
9
9
  "keywords": [],
10
10
  "publishConfig": {
11
11
  "access": "public"
@@ -29,19 +29,17 @@
29
29
  "@rijkshuisstijl-community/design-tokens": "11.0.0",
30
30
  "@types/parse-link-header": "^2.0.3",
31
31
  "clsx": "2.1.1",
32
- "i18next": "25.8.4",
32
+ "i18next": "26.3.1",
33
33
  "parse-link-header": "^2.0.0",
34
- "react-i18next": "16.5.4",
34
+ "react-i18next": "17.0.8",
35
35
  "react-markdown": "10.1.0",
36
36
  "remark-behead": "^3.1.0",
37
- "@developer-overheid-nl/don-register-locales": "1.2.0"
37
+ "@developer-overheid-nl/don-register-locales": "1.2.1"
38
38
  },
39
39
  "devDependencies": {
40
- "@vitejs/plugin-react": "^5.1.2",
41
40
  "rimraf": "^6.1.2",
42
41
  "typescript": "5.9.3",
43
- "vite": "7.1.7",
44
- "vite-plugin-dts": "^4.5.4"
42
+ "vite": "7.1.7"
45
43
  },
46
44
  "peerDependencies": {
47
45
  "@types/react": ">=19.2 <19.3",
@@ -23,6 +23,7 @@ const CardsList = (props: PropsWithChildren<CardsListProps>) => {
23
23
  <ol className={clsx(styles.cardsList, className)} id={id}>
24
24
  {items && items.length > 0
25
25
  ? items.map((item, index, array) => (
26
+ // biome-ignore-start lint/suspicious/noArrayIndexKey: no stable ID's https://legacy.reactjs.org/docs/lists-and-keys.html#keys
26
27
  <CardsListItem
27
28
  key={`${id || "don-cards"}_${index}`}
28
29
  index={index}
@@ -30,6 +31,7 @@ const CardsList = (props: PropsWithChildren<CardsListProps>) => {
30
31
  >
31
32
  {item as unknown as ReactNode}
32
33
  </CardsListItem>
34
+ // biome-ignore-end lint/suspicious/noArrayIndexKey: no stable ID's https://legacy.reactjs.org/docs/lists-and-keys.html#keys
33
35
  ))
34
36
  : children}
35
37
  </ol>
@@ -9,9 +9,9 @@
9
9
  }
10
10
 
11
11
  :global(
12
- .rhc-card-as-link:hover
13
- .rhc-card-as-link__heading.rhc-card-as-link__heading
14
- ) {
12
+ .rhc-card-as-link:hover
13
+ .rhc-card-as-link__heading.rhc-card-as-link__heading
14
+ ) {
15
15
  /* TODO: specifity */
16
16
  :global(.nl-heading) {
17
17
  text-decoration: underline;
@@ -1,4 +1,30 @@
1
1
  .donDataBadge.donDataBadge {
2
+ .badgeLink {
3
+ display: inline-block;
4
+ padding-block: 0.25rem;
5
+ color: inherit;
6
+ text-decoration: inherit;
7
+
8
+ &:focus-visible {
9
+ outline: none;
10
+ }
11
+
12
+ /* fix for non-clickable icons bug */
13
+ &::before {
14
+ position: absolute;
15
+ top: 0;
16
+ left: 0;
17
+ display: block;
18
+ width: 100%;
19
+ height: 100%;
20
+ content: '';
21
+ border-radius: var(
22
+ --utrecht-data-badge-border-radius,
23
+ var(--utrecht-badge-border-radius, 0.5ch)
24
+ );
25
+ }
26
+ }
27
+
2
28
  &.primary {
3
29
  --_utrecht-data-badge-color: oklch(
4
30
  from var(--utrecht-data-badge-color) calc(l - 0.1) c h
@@ -41,6 +67,10 @@
41
67
  color: var(--_utrecht-data-badge-color);
42
68
  background-color: var(--_utrecht-data-badge-background-color);
43
69
 
70
+ .badgeLink {
71
+ text-decoration: underline;
72
+ }
73
+
44
74
  &:hover {
45
75
  background-color: var(--rhc-color-cool-grey-100);
46
76
 
@@ -48,10 +78,6 @@
48
78
  text-decoration: none;
49
79
  }
50
80
  }
51
-
52
- .badgeLink {
53
- text-decoration: underline;
54
- }
55
81
  }
56
82
 
57
83
  &:focus-within {
@@ -61,29 +87,3 @@
61
87
  outline-offset: var(--utrecht-focus-outline-offset, revert);
62
88
  }
63
89
  }
64
-
65
- .badgeLink {
66
- display: inline-block;
67
- padding-block: 0.25rem;
68
- color: inherit;
69
- text-decoration: inherit;
70
-
71
- &:focus-visible {
72
- outline: none;
73
- }
74
-
75
- /* fix for non-clickable icons bug */
76
- &::before {
77
- position: absolute;
78
- top: 0;
79
- left: 0;
80
- display: block;
81
- width: 100%;
82
- height: 100%;
83
- content: '';
84
- border-radius: var(
85
- --utrecht-data-badge-border-radius,
86
- var(--utrecht-badge-border-radius, 0.5ch)
87
- );
88
- }
89
- }
@@ -74,6 +74,8 @@ type SelectedFiltersMap = Map<
74
74
  Array<string | [string, string]>
75
75
  >;
76
76
 
77
+ type ActiveFilters = Record<string, string | string[] | undefined>;
78
+
77
79
  export interface FacetFiltersProps extends HTMLProps<HTMLDivElement> {
78
80
  title?: string;
79
81
  startHeadingLevel?: HeadingProps["level"];
@@ -139,6 +141,7 @@ export const getSelectedFilters = (
139
141
  export const getSelectedFiltersMap = (
140
142
  filters: FilterData[] | null | undefined,
141
143
  withLabels = false,
144
+ activeFilters: ActiveFilters = {},
142
145
  ): SelectedFiltersMap => {
143
146
  return (
144
147
  filters?.reduce((acc, filter) => {
@@ -153,10 +156,22 @@ export const getSelectedFiltersMap = (
153
156
  ? acc.set([filter.key, filter.label], keys)
154
157
  : acc.set(filter.key, keys);
155
158
  }
156
- } else if (filter.type === FilterType.Toggle && filter.value) {
157
- withLabels
158
- ? acc.set([filter.key, filter.label], [["true", filter.label]])
159
- : acc.set(filter.key, ["true"]);
159
+ } else if (filter.type === FilterType.Toggle) {
160
+ const activeValue = activeFilters[filter.key];
161
+ const values = Array.isArray(activeValue) ? activeValue : [activeValue];
162
+ const isExplicitFalse = values.includes("false");
163
+
164
+ if (filter.value || isExplicitFalse) {
165
+ const value = filter.value ? "true" : "false";
166
+ const label =
167
+ value === "true"
168
+ ? filter.label
169
+ : filter.label.replace(/^Heeft\s+/i, "Heeft geen ");
170
+
171
+ withLabels
172
+ ? acc.set([filter.key, filter.label], [[value, label]])
173
+ : acc.set(filter.key, [value]);
174
+ }
160
175
  } else if (filter.type === FilterType.Date && filter.value) {
161
176
  withLabels
162
177
  ? acc.set([filter.key, filter.label], [[filter.value, filter.label]])
@@ -184,8 +199,16 @@ const updateFilters = (
184
199
  filterKey: string,
185
200
  filterValue: string,
186
201
  checked: boolean,
202
+ type: FilterType,
187
203
  ) => {
188
- const newSelectedFilters = {
204
+ if (type === FilterType.Toggle) {
205
+ return {
206
+ ...selectedFilters,
207
+ [filterKey]: [checked ? filterValue : "false"],
208
+ };
209
+ }
210
+
211
+ return {
189
212
  ...selectedFilters,
190
213
  [filterKey]: checked
191
214
  ? [...(selectedFilters[filterKey] || []), filterValue]
@@ -193,7 +216,6 @@ const updateFilters = (
193
216
  (value) => value !== filterValue,
194
217
  ),
195
218
  };
196
- return newSelectedFilters;
197
219
  };
198
220
 
199
221
  const debounce = <T extends unknown[]>(
@@ -242,12 +264,14 @@ const FacetFilters = (props: PropsWithChildren<FacetFiltersProps>) => {
242
264
  const handleChange = (
243
265
  event: ChangeEvent<HTMLInputElement>,
244
266
  type: FilterType,
267
+ filterKey = event.target.name,
245
268
  ) => {
246
269
  const newSelectedFilters = updateFilters(
247
270
  selectedFilters,
248
- event.target.name,
271
+ filterKey,
249
272
  event.target.value,
250
273
  event.target.checked,
274
+ type,
251
275
  );
252
276
 
253
277
  if (debounceTypes.includes(type)) {
@@ -257,6 +281,19 @@ const FacetFilters = (props: PropsWithChildren<FacetFiltersProps>) => {
257
281
  }
258
282
  };
259
283
 
284
+ const handleToggleChange = (
285
+ event: ChangeEvent<HTMLInputElement>,
286
+ filterKey: string,
287
+ ) => {
288
+ const hiddenInput = event.target.form?.elements.namedItem(filterKey);
289
+
290
+ if (hiddenInput instanceof HTMLInputElement) {
291
+ hiddenInput.value = event.target.checked ? "true" : "false";
292
+ }
293
+
294
+ handleChange(event, FilterType.Toggle, filterKey);
295
+ };
296
+
260
297
  return (
261
298
  <div
262
299
  ref={thisRef}
@@ -287,19 +324,25 @@ const FacetFilters = (props: PropsWithChildren<FacetFiltersProps>) => {
287
324
  {facet.description}
288
325
  </Paragraph>
289
326
  {facet.type === "toggle" ? (
290
- <FormFieldSwitch
291
- label=""
292
- labelledById={`${facet.key}-label`}
293
- name={facet.key}
294
- defaultChecked={facet.value}
295
- value="true"
296
- amount={facet.count || 0}
297
- labels={{
298
- on: t("components.filter-on"),
299
- off: t("components.filter-off"),
300
- }}
301
- onChange={(event) => handleChange(event, facet.type)}
302
- />
327
+ <>
328
+ <input
329
+ type="hidden"
330
+ name={facet.key}
331
+ defaultValue={facet.value ? "true" : "false"}
332
+ />
333
+ <FormFieldSwitch
334
+ label=""
335
+ labelledById={`${facet.key}-label`}
336
+ defaultChecked={facet.value}
337
+ value="true"
338
+ amount={facet.count || 0}
339
+ labels={{
340
+ on: t("components.filter-on"),
341
+ off: t("components.filter-off"),
342
+ }}
343
+ onChange={(event) => handleToggleChange(event, facet.key)}
344
+ />
345
+ </>
303
346
  ) : null}
304
347
  {/* TODO: Date selector
305
348
  {facet.type === "date" ? <div>TODO</div> : null}
@@ -346,7 +389,16 @@ const FacetFilters = (props: PropsWithChildren<FacetFiltersProps>) => {
346
389
  defaultChecked={option.selected}
347
390
  amount={option.count}
348
391
  onChange={(event) => handleChange(event, facet.type)}
349
- />
392
+ >
393
+ {option.description ? (
394
+ <ToolTip
395
+ text={option.description}
396
+ aria-label={t("components.info-about", {
397
+ subject: option.label,
398
+ })}
399
+ />
400
+ ) : null}
401
+ </FormFieldRadioOption>
350
402
  ))}
351
403
  </FormFieldRadioGroup>
352
404
  ) : null}
@@ -14,7 +14,7 @@ export interface FormFieldSwitchProps
14
14
  "label" | "statusId" | "errorMessageId" | "descriptionId" | "input"
15
15
  >,
16
16
  AmountLabelProps {
17
- name: string;
17
+ name?: string;
18
18
  value: string;
19
19
  checked?: boolean;
20
20
  defaultChecked?: boolean;
@@ -61,8 +61,8 @@
61
61
 
62
62
  .link.link:any-link:hover {
63
63
  text-decoration-line: underline;
64
- /* first skip-ink needed for Chromium browsers, otherwise .nl-link `none` is used */
65
64
  text-decoration-skip-ink: auto;
65
+ /* biome-ignore lint/suspicious/noDuplicateProperties: ↰ first skip-ink needed for Chromium browsers, otherwise .nl-link `none` is used */
66
66
  text-decoration-skip-ink: all; /* bugged in Chromium */
67
67
 
68
68
  .icon {
@@ -18,8 +18,8 @@
18
18
  }
19
19
 
20
20
  :global(
21
- .utrecht-pagination__page-link.utrecht-pagination__page-link--current:hover
22
- ) {
21
+ .utrecht-pagination__page-link.utrecht-pagination__page-link--current:hover
22
+ ) {
23
23
  color: var(--utrecht-pagination-page-link-current-color);
24
24
  background-color: var(
25
25
  --utrecht-pagination-page-link-current-background-color