@synerise/ds-item-picker 1.17.26 → 1.17.27

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/CLAUDE.md +326 -0
  3. package/package.json +24 -23
package/CHANGELOG.md CHANGED
@@ -3,6 +3,10 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.17.27](https://github.com/Synerise/synerise-design/compare/@synerise/ds-item-picker@1.17.26...@synerise/ds-item-picker@1.17.27) (2026-07-23)
7
+
8
+ **Note:** Version bump only for package @synerise/ds-item-picker
9
+
6
10
  ## [1.17.26](https://github.com/Synerise/synerise-design/compare/@synerise/ds-item-picker@1.17.25...@synerise/ds-item-picker@1.17.26) (2026-07-16)
7
11
 
8
12
  **Note:** Version bump only for package @synerise/ds-item-picker
package/CLAUDE.md ADDED
@@ -0,0 +1,326 @@
1
+ # ItemPicker (`@synerise/ds-item-picker`)
2
+
3
+ > A dropdown-based single-item selector with search, sections, folder navigation, async infinite loading, and action items, available in a current ("new") API and a deprecated legacy API.
4
+
5
+ ## Package structure
6
+
7
+ ```
8
+ src/
9
+ ItemPicker.tsx — default export; router that dispatches to ItemPickerNew or ItemPickerLegacy based on `isNewVersion` prop
10
+ ItemPicker.styles.ts — minimal wrapper styled-component
11
+ index.ts — public exports
12
+ hooks/
13
+ useDefaultTexts.tsx — resolves all i18n text defaults via react-intl
14
+ modules.d.ts — ambient module declarations
15
+ components/
16
+ ItemPickerNew/
17
+ ItemPickerNew.tsx — current picker: FormField + Dropdown + Trigger + ItemPickerList
18
+ ItemPickerNew.types.ts — ItemPickerProps (new), ItemPickerListProps, ItemLoaderConfig, etc.
19
+ types/
20
+ actions.types.ts — Action union type (redirect | custom | searchBy | searchIn)
21
+ baseItemSectionType.types.ts — BaseItemType, BaseSectionType, BaseSectionTypeWithFolders
22
+ itemPickerListTexts.types.ts — ItemPickerListTexts (all 23 text keys)
23
+ ItemPickerList/
24
+ ItemPickerList.tsx — virtualised list (react-window VariableSizeList), search, sections, keyboard nav
25
+ ItemPickerList.types.ts — ItemPickerListAPI, ItemSelectHandler, ItemPickerListRef
26
+ ItemPickerList.styles.ts
27
+ constants.ts — ITEM_SIZE, ITEMS_PER_PAGE (150), ITEMS_PER_SECTION (4), DEFAULT_HEIGHT (420)
28
+ types/renderMode.ts — RENDER_MODES enum
29
+ hooks/
30
+ useItemsInSections.tsx — core state machine: section/folder navigation, async loading, infinite scroll, search
31
+ useItemsInSections.utils.tsx
32
+ useFlattenFolders.ts — resolves nested folder structure
33
+ useListHeight.ts — calculates outer/list/offset heights from containerHeight config
34
+ utils/
35
+ actionItemsUtils.tsx — builds action rows in the list
36
+ createTitleFromTitlePath.ts
37
+ findSectionById.ts — exported utility
38
+ getContextAwareActions.ts
39
+ getSearchByActionItems.tsx
40
+ isNavKey.ts
41
+ resolveSectionId.ts
42
+ typeguards.utils.ts
43
+ components/
44
+ EmptyListMessage.tsx — empty state with optional "search all folders" CTA
45
+ ErrorItem.tsx / ErrorMessage.tsx — error state
46
+ InfiniteLoaderItem.tsx — loading-more / all-loaded / error-more row
47
+ ItemPickerListFooter.tsx — optional refresh button footer
48
+ ItemPickerListRow.tsx — react-window row renderer
49
+ ItemPickerListSkeleton.tsx — initial loading skeleton
50
+ ListSearchInput.tsx — search bar with searchBy param chip
51
+ LoadingItem.tsx / NoMoreItem.tsx
52
+ ItemPickerLegacy/
53
+ ItemPickerLegacy.tsx — @deprecated; uses ItemPickerDropdown + Trigger
54
+ ItemPickerLegacy.types.ts — ItemPickerProps (legacy)
55
+ ItemPicker.spec.tsx — Vitest tests
56
+ ItemPickerDropdown/
57
+ ItemPickerDropdown.tsx — @deprecated internal dropdown for legacy picker
58
+ ItemPickerDropdown.types.ts
59
+ ItemPickerDropdown.style.ts
60
+ ItemPickerTrigger/
61
+ Trigger.tsx — shared trigger button (selected value / placeholder, clear icon, change button)
62
+ Trigger.types.ts — ItemPickerTriggerProps
63
+ Trigger.styles.ts
64
+ ```
65
+
66
+ ## Public exports
67
+
68
+ ### Default export — `ItemPicker`
69
+
70
+ A polymorphic `forwardRef` component. Renders `ItemPickerNew` when `isNewVersion: true`, otherwise renders `ItemPickerLegacy`.
71
+
72
+ ```ts
73
+ type ItemPickerType = <ItemType extends BaseItemType, SectionType extends BaseSectionType>(
74
+ p: ItemPickerProps | (ItemPickerPropsNew<ItemType, SectionType> & { ref?: ItemPickerListRef })
75
+ ) => JSX.Element;
76
+ ```
77
+
78
+ ---
79
+
80
+ ### `ItemPickerNew` (named export)
81
+
82
+ Current API. Generic over `ItemType extends BaseItemType` and `SectionType extends BaseSectionType | undefined`.
83
+
84
+ | Prop | Type | Default | Description |
85
+ |------|------|---------|-------------|
86
+ | `isNewVersion` | `true` | — | **Required** discriminant to select this branch via `ItemPicker` default export |
87
+ | `items` | `ItemType[] \| ItemsConfig<ItemType> \| ItemLoaderConfig<ItemType>` | — | Fixed array, array-with-limit config, or async loader config |
88
+ | `selectedItem?` | `ItemType` | — | Currently selected item |
89
+ | `onChange?` | `(item: ItemType) => void` | — | Called when an item is selected; dropdown closes automatically |
90
+ | `onClear?` | `() => void` | — | Called when the trigger clear icon is clicked |
91
+ | `sections?` | `BaseSectionTypeWithFolders<SectionType>[]` | — | Section/folder tree; enables section-navigation mode |
92
+ | `recents?` | `ItemType[]` | — | Recent items shown at top |
93
+ | `actions?` | `Action[]` | — | Action rows (redirect / custom / searchBy / searchIn); shown on `/` keystroke |
94
+ | `isLoading?` | `boolean` | — | External loading state (shows skeleton) |
95
+ | `onRefresh?` | `() => void` | — | Enables footer refresh button (async items also get an auto refresh) |
96
+ | `onSectionChange?` | `(section?) => void` | — | Fired when the user navigates into a section |
97
+ | `containerHeight?` | `'fitContent' \| 'fillSpace' \| HeightConfig` | preset (420px) | List height strategy |
98
+ | `showItemsSectionLabel?` | `boolean` | `true` | Show "Items" section title row |
99
+ | `noResultsIcon?` / `emptyListIcon?` | `ReactNode` | — | Custom empty-state icons |
100
+ | `getItemHeight?` | `(item) => number` | — | Override per-item height |
101
+ | `scrollbarProps?` | `ScrollbarAdditionalProps` | — | Passed to `@synerise/ds-scrollbar` |
102
+ | `searchBarProps?` | `Omit<SearchBarProps, 'value' \| 'onSearchChange' \| 'placeholder'>` | — | Extra props for the search bar |
103
+ | `includeFooter?` | `boolean` | `true` | Show refresh footer |
104
+ | `includeSearchBar?` | `boolean` | `true` | Show search bar |
105
+ | `texts?` | `Partial<ItemPickerTexts>` | (react-intl defaults) | Override any of the 23 localised text strings |
106
+ | `triggerProps?` | `{ size?, allowClear?, withChangeButton?, withClearConfirmation?, informationCardTooltipProps? }` | — | Props forwarded to the default `Trigger` |
107
+ | `renderTrigger?` | `(props) => ReactNode` | — | Completely replace the trigger; receives `{ selected, openDropdown, closeDropdown, error, disabled }` |
108
+ | `placeholder?` | `ReactNode` | — | Trigger placeholder text |
109
+ | `placeholderIcon?` | `ReactNode` | — | Icon shown in placeholder state |
110
+ | `label?` | `ReactNode` | — | `FormField` label |
111
+ | `description?` | `ReactNode` | — | `FormField` description |
112
+ | `tooltip?` | `ReactNode` | — | `FormField` tooltip |
113
+ | `tooltipConfig?` | `FormFieldCommonProps['tooltipConfig']` | — | `FormField` tooltip config |
114
+ | `error?` | `boolean` | — | Error state on trigger and FormField |
115
+ | `errorText?` | `FormFieldCommonProps['errorText']` | — | Preferred error message |
116
+ | `errorMessage?` | `FormFieldCommonProps['errorText']` | — | **@deprecated** — use `errorText` |
117
+ | `disabled?` | `boolean` | — | Disables trigger and dropdown |
118
+ | `onFocus?` / `onBlur?` | `() => void` | — | Fired on dropdown open/close |
119
+ | `onLoadedData?` | `OnLoadedData` | — | Callback after each async page loads |
120
+ | `dropdownProps?` | `Partial<Omit<DropdownSharedProps, 'children' \| 'overlay' \| 'disabled'>>` | — | Extra props for `@synerise/ds-dropdown` |
121
+
122
+ `ref` (via `forwardRef`) exposes `ItemPickerListAPI`:
123
+
124
+ | Method / Property | Description |
125
+ |-------------------|-------------|
126
+ | `reloadActiveSection()` | Re-fetches the currently active section from page 0 |
127
+ | `currentSection` | The currently active section object |
128
+ | `activeSectionId` | `string \| undefined` |
129
+
130
+ ---
131
+
132
+ ### `ItemPickerList` (named export)
133
+
134
+ Standalone list panel without the trigger/dropdown shell. Accepts `ItemPickerListProps<ItemType, SectionType>` — a superset of the props above plus:
135
+
136
+ | Prop | Type | Notes |
137
+ |------|------|-------|
138
+ | `onItemSelect` | `ItemSelectHandler<ItemType, SectionType>` | **Required** |
139
+ | `isVisible?` | `boolean` | Controls reset-on-open behaviour |
140
+ | `isDropdown?` | `boolean` | Suppresses scroll-end events when not visible |
141
+ | `containerRef?` | `Ref<HTMLDivElement>` | Additional ref combined with internal ref |
142
+
143
+ ---
144
+
145
+ ### `ItemPickerLegacy` (named export) — **@deprecated**
146
+
147
+ Use `ItemPicker` (default) with `isNewVersion` instead.
148
+
149
+ | Prop | Type | Default | Description |
150
+ |------|------|---------|-------------|
151
+ | `dataSource` | `ListItemProps[]` | — | Items array |
152
+ | `onChange` | `(item: ListItemProps) => void` | — | Selection callback |
153
+ | `onClear?` | `() => void` | — | Clear callback |
154
+ | `placeholder` | `ReactNode` | — | Trigger placeholder |
155
+ | `selectedItem?` | `ListItemProps` | — | Selected item |
156
+ | `size?` | `'small' \| 'large'` | `'small'` | Trigger size |
157
+ | `dropdownVisibleRows?` | `number` | `10` | Max visible rows in dropdown |
158
+ | `dropdownRowHeight?` | `number` | `32` | Row height (px) |
159
+ | `dropdownBottomAction?` | `ReactNode` | — | Bottom slot |
160
+ | `closeOnBottomAction?` | `boolean` | `false` | Close on bottom action click |
161
+ | `searchPlaceholder?` | `string` | `'Search'` | Search bar placeholder |
162
+ | `noResults?` | `string` | `'No results'` | No-results message |
163
+ | `clear?` | `ReactNode` | `'Clear'` | Clear tooltip |
164
+ | `changeButtonLabel?` | `ReactNode` | `'Change'` | Change button label (large size) |
165
+ | `withClearConfirmation?` | `boolean` | — | Show Popconfirm before clearing |
166
+ | `clearConfirmTitle?` | `string` | `'Please confirm'` | Popconfirm title |
167
+ | `yesText?` / `noText?` | `string` | `'Yes'` / `'No'` | Popconfirm buttons |
168
+ | `error?` | `boolean` | — | Error state |
169
+ | `errorMessage?` | `ReactNode` | — | Error text |
170
+ | `disabled?` | `boolean` | — | Disabled state |
171
+ | `hideSearchBar?` | `boolean` | — | Hide search bar |
172
+ | `searchBarProps?` | `Partial<SearchBarProps>` | — | Extra search bar props |
173
+ | `scrollbarProps?` | `ScrollbarAdditionalProps` | — | Scrollbar config |
174
+ | `informationCardTooltipProps?` | `Omit<InformationCardTooltipProps, 'children'>` | — | Info card tooltip on trigger |
175
+ | `label?`, `description?`, `tooltip?`, `tooltipConfig?` | `FormFieldCommonProps` fields | — | FormField meta |
176
+ | `onBlur?` / `onFocus?` | `() => void` | — | Open/close side-effects |
177
+
178
+ ---
179
+
180
+ ### `ItemPickerTrigger` (named export)
181
+
182
+ The standalone trigger button, exported for custom dropdown implementations.
183
+
184
+ ---
185
+
186
+ ### Type exports
187
+
188
+ | Symbol | Source |
189
+ |--------|--------|
190
+ | `ItemPickerProps` | Legacy props (re-exported from `ItemPickerLegacy.types`) |
191
+ | `ItemPickerPropsNew` | New picker props |
192
+ | `ItemPickerListProps` | Standalone list props |
193
+ | `ItemLoaderConfig<ItemType>` | Async loader configuration |
194
+ | `ItemLoaderResponse<ItemType>` | Return type of `loadItems` |
195
+ | `LoaderProps` | Argument to `loadItems` |
196
+ | `OnLoadedData` | Callback type for `onLoadedData` |
197
+ | `ItemSelectHandler` | `onItemSelect` callback type |
198
+ | `ItemPickerListAPI` | Ref handle type |
199
+ | `BaseItemType` | Minimum item shape |
200
+ | `BaseSectionType` | Minimum section shape |
201
+ | `BaseSectionTypeWithFolders` | Section with optional `folders` tree |
202
+ | `ItemPickerListTexts` | All 23 localisation text keys |
203
+ | `Action` | Union of action types |
204
+ | `findSectionById` | Utility: finds a section by id in a nested section tree |
205
+
206
+ ---
207
+
208
+ ## Usage patterns
209
+
210
+ ### Minimal — flat list
211
+
212
+ ```tsx
213
+ import ItemPicker from '@synerise/ds-item-picker';
214
+
215
+ const [selected, setSelected] = useState<MyItem | undefined>();
216
+
217
+ <ItemPicker
218
+ isNewVersion
219
+ placeholder="Select an item"
220
+ items={myItems}
221
+ selectedItem={selected}
222
+ onChange={setSelected}
223
+ onClear={() => setSelected(undefined)}
224
+ />
225
+ ```
226
+
227
+ ### Async infinite scroll
228
+
229
+ ```tsx
230
+ import ItemPicker, { type ItemLoaderConfig } from '@synerise/ds-item-picker';
231
+
232
+ const loaderConfig: ItemLoaderConfig<MyItem> = {
233
+ limitPerPage: 50,
234
+ loadItems: async ({ page, limit, searchQuery, sectionId, abortController }) => {
235
+ const data = await fetchItems({ page, limit, searchQuery, sectionId });
236
+ return { items: data.results, total: data.total };
237
+ },
238
+ };
239
+
240
+ <ItemPicker isNewVersion items={loaderConfig} placeholder="Pick…" onChange={handleChange} />
241
+ ```
242
+
243
+ ### With sections and folders
244
+
245
+ ```tsx
246
+ <ItemPicker
247
+ isNewVersion
248
+ items={loaderConfig}
249
+ sections={[
250
+ { id: 'seg', text: 'Segmentations', folders: [{ id: 'f1', text: 'Folder A' }] },
251
+ ]}
252
+ onSectionChange={(section) => console.log('navigated to', section)}
253
+ onChange={handleChange}
254
+ placeholder="Pick segmentation"
255
+ />
256
+ ```
257
+
258
+ ### Imperative reload via ref
259
+
260
+ ```tsx
261
+ import ItemPicker, { type ItemPickerListAPI } from '@synerise/ds-item-picker';
262
+ import { useRef } from 'react';
263
+
264
+ const ref = useRef<ItemPickerListAPI | null>(null);
265
+
266
+ <ItemPicker isNewVersion ref={ref} items={loaderConfig} onChange={handleChange} placeholder="…" />
267
+
268
+ // Reload after an external mutation:
269
+ ref.current?.reloadActiveSection();
270
+ ```
271
+
272
+ ### Standalone list (no trigger)
273
+
274
+ ```tsx
275
+ import { ItemPickerList } from '@synerise/ds-item-picker';
276
+
277
+ <ItemPickerList items={myItems} onItemSelect={(item) => console.log(item)} />
278
+ ```
279
+
280
+ ---
281
+
282
+ ## Styling
283
+
284
+ - All styled-components; no hardcoded colours — uses `@synerise/ds-core` theme tokens.
285
+ - The outer wrapper is `S.ItemPickerWrapper` (just `position: relative`).
286
+ - List layout driven by `useListHeight`; default height 420 px, drops to 350 px below 800 px viewport threshold.
287
+ - `containerHeight` prop accepts `'fitContent'` (shrinks to content), `'fillSpace'` (100%), or an explicit `HeightConfig` object.
288
+
289
+ ---
290
+
291
+ ## Key dependencies
292
+
293
+ | Package | Role |
294
+ |---------|------|
295
+ | `react-window` | Virtualised `VariableSizeList` for item rows |
296
+ | `@synerise/ds-dropdown` | Popover shell (Floating UI-based) |
297
+ | `@synerise/ds-form-field` | Label / description / error / tooltip wrapper |
298
+ | `@synerise/ds-list-item` | Row components and `itemSizes` constants |
299
+ | `@synerise/ds-scrollbar` | Custom scrollbar wrapping the list |
300
+ | `@synerise/ds-search-bar` | Search input in list header |
301
+ | `@synerise/ds-popconfirm` | Clear-confirmation dialog |
302
+ | `@synerise/ds-information-card` | Optional info tooltip on trigger |
303
+ | `lodash.debounce` | 300 ms debounce on search query |
304
+ | `uuid` | Unique class-name per list instance (used by `focusWithArrowKeys`) |
305
+ | `react-intl` | All default text strings |
306
+
307
+ ---
308
+
309
+ ## Implementation notes
310
+
311
+ - **Version switch**: `ItemPicker` (default) checks `'isNewVersion' in props && props.isNewVersion` at render time. No runtime flag registry — purely prop-driven.
312
+ - **Async loading race prevention**: `useItemsInSections` tracks a `requestIdRef` UUID and discards stale responses.
313
+ - **AbortController**: each `loadItems` call gets a fresh `AbortController`; the previous one is aborted on re-trigger (section change, search, refresh).
314
+ - **Search action trigger**: typing `/` into the search bar activates the global actions list (`listActions = searchQuery === '/'`).
315
+ - **Infinite scroll**: only active for `ItemLoaderConfig` items in `LIST_ITEMS` render mode. Pages are tracked via `pageToLoad.current`; deduplication relies on the caller returning accurate `total`.
316
+ - **Section/folder rendering modes** (`renderMode.ts`):
317
+ - `LIST_ITEMS` — flat list
318
+ - `LIST_ITEMS_IN_SECTIONS` — items grouped under section headers
319
+ - `LIST_FOLDERS_IN_SECTIONS` — folder tiles (no items loaded yet)
320
+ - **`ItemPickerLegacy` is marked `@deprecated`** in source with a JSDoc comment on the component itself.
321
+ - **`errorMessage` prop** on `ItemPickerNew` is marked `@deprecated`; prefer `errorText` (from `FormFieldCommonProps`).
322
+ - **Several `ItemPickerTriggerProps` fields are `@deprecated`**: `clear`, `changeButtonLabel`, `clearConfirmTitle`, `yesText`, `noText` — move to `texts` object.
323
+ - **`Props` alias** in `Trigger.types.ts` is marked `@deprecated`; use `ItemPickerTriggerProps`.
324
+ - **Tests use Jest** (`jest.config.js` present); the package has not been migrated to Vitest.
325
+ - The search-bar `searchPlaceholder` in `ItemPickerNew` must be overridden via `texts.searchPlaceholder` (not a top-level prop), unlike `ItemPickerLegacy` where it is a direct prop.
326
+ - `ItemPickerList` generates a unique per-instance CSS class via `uuid()` on mount; `focusWithArrowKeys` from `@synerise/ds-utils` uses this class for keyboard navigation.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synerise/ds-item-picker",
3
- "version": "1.17.26",
3
+ "version": "1.17.27",
4
4
  "description": "ItemPicker UI Component for the Synerise Design System",
5
5
  "license": "ISC",
6
6
  "repository": "Synerise/synerise-design",
@@ -17,6 +17,7 @@
17
17
  "files": [
18
18
  "/dist",
19
19
  "CHANGELOG.md",
20
+ "CLAUDE.md",
20
21
  "README.md",
21
22
  "package.json",
22
23
  "LICENSE.md"
@@ -41,27 +42,27 @@
41
42
  ],
42
43
  "types": "dist/index.d.ts",
43
44
  "dependencies": {
44
- "@synerise/ds-alert": "^1.1.61",
45
- "@synerise/ds-avatar": "^1.3.18",
46
- "@synerise/ds-button": "^1.5.34",
47
- "@synerise/ds-dropdown": "^1.3.19",
48
- "@synerise/ds-empty-states": "^1.0.48",
49
- "@synerise/ds-flag": "^1.0.12",
50
- "@synerise/ds-form-field": "^1.3.23",
51
- "@synerise/ds-icon": "^1.18.4",
52
- "@synerise/ds-information-card": "^1.7.7",
53
- "@synerise/ds-list-item": "^1.6.1",
54
- "@synerise/ds-loader": "^1.0.17",
55
- "@synerise/ds-popconfirm": "^1.4.1",
56
- "@synerise/ds-result": "^1.0.65",
57
- "@synerise/ds-scrollbar": "^1.5.1",
58
- "@synerise/ds-search": "^1.5.33",
59
- "@synerise/ds-search-bar": "^1.4.34",
60
- "@synerise/ds-short-cuts": "^1.0.55",
61
- "@synerise/ds-skeleton": "^1.0.59",
62
- "@synerise/ds-tooltip": "^1.5.3",
63
- "@synerise/ds-typography": "^1.1.26",
64
- "@synerise/ds-utils": "^1.10.1",
45
+ "@synerise/ds-alert": "^1.1.62",
46
+ "@synerise/ds-avatar": "^1.3.19",
47
+ "@synerise/ds-button": "^1.5.35",
48
+ "@synerise/ds-dropdown": "^1.3.20",
49
+ "@synerise/ds-empty-states": "^1.0.49",
50
+ "@synerise/ds-flag": "^1.0.13",
51
+ "@synerise/ds-form-field": "^1.3.24",
52
+ "@synerise/ds-icon": "^1.18.5",
53
+ "@synerise/ds-information-card": "^1.7.8",
54
+ "@synerise/ds-list-item": "^1.6.2",
55
+ "@synerise/ds-loader": "^1.0.18",
56
+ "@synerise/ds-popconfirm": "^1.4.2",
57
+ "@synerise/ds-result": "^1.0.66",
58
+ "@synerise/ds-scrollbar": "^1.5.2",
59
+ "@synerise/ds-search": "^1.5.34",
60
+ "@synerise/ds-search-bar": "^1.4.35",
61
+ "@synerise/ds-short-cuts": "^1.0.56",
62
+ "@synerise/ds-skeleton": "^1.0.60",
63
+ "@synerise/ds-tooltip": "^1.5.4",
64
+ "@synerise/ds-typography": "^1.1.27",
65
+ "@synerise/ds-utils": "^1.10.2",
65
66
  "lodash.debounce": "^4.0.8",
66
67
  "react-window": "^1.8.11",
67
68
  "uuid": "^8.3.2"
@@ -76,5 +77,5 @@
76
77
  "styled-components": "^5.3.3",
77
78
  "vitest": "4"
78
79
  },
79
- "gitHead": "a81ab6519d49a3dea9c0cfebcdc9104cbb4f4226"
80
+ "gitHead": "d0a43cc43d8528a36f105aceea52ab470edb71d9"
80
81
  }