@spark-web/design-system 5.1.6 → 5.1.8

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": "@spark-web/design-system",
3
- "version": "5.1.6",
3
+ "version": "5.1.8",
4
4
  "license": "MIT",
5
5
  "main": "dist/spark-web-design-system.cjs.js",
6
6
  "module": "dist/spark-web-design-system.esm.js",
@@ -20,7 +20,7 @@
20
20
  "@spark-web/button": "5.6.1",
21
21
  "@spark-web/checkbox": "5.1.2",
22
22
  "@spark-web/columns": "5.1.1",
23
- "@spark-web/combobox": "6.1.0",
23
+ "@spark-web/combobox": "6.2.0",
24
24
  "@spark-web/container": "5.1.1",
25
25
  "@spark-web/control-label": "5.1.0",
26
26
  "@spark-web/core": "5.2.0",
@@ -163,3 +163,84 @@ Props used by the patterns:
163
163
 
164
164
  This is a confirmed COMPONENT GAP — no `@spark-web` pagination component exists
165
165
  yet. Until one ships, every consumer supplies its own pagination component.
166
+
167
+ ---
168
+
169
+ ## Multi-select with per-item toggle rows
170
+
171
+ When a multi-select picks N items and each selected item also needs its own
172
+ on/off flag, pair the selector with a list of **toggle rows generated from the
173
+ current selection** — one bordered row per item, label on the left and an
174
+ `@spark-web/switch` `Switch` on the right. The toggle list binds to a
175
+ react-hook-form field whose value is a `string[]` of the IDs currently switched
176
+ on.
177
+
178
+ Use it when a per-item boolean accompanies a multi-select choice (e.g. flagging
179
+ some of the selected vendors as Authority Contacts). For a single form-wide
180
+ boolean use `ToggleField`; for choosing items with no per-item flag, the
181
+ multi-select alone is enough.
182
+
183
+ Two parts:
184
+
185
+ - **Selector** — `ComboboxField isMulti` or `MultiSelectField` from
186
+ `@brighte/ui-components` (never `@spark-web/multi-select` directly — see
187
+ Filter fields above). Its value is the set of selected items.
188
+ - **Toggle rows** — derive `{ id, name }[]` from the current selection and
189
+ render one row each, bound to a separate `string[]` field of the "on" IDs.
190
+ Render nothing when the selection is empty.
191
+
192
+ Each row is a bordered card wrapping a space-between flex row, with the Switch's
193
+ accessible name supplied via `aria-label` (so the name isn't rendered twice;
194
+ target a row with `getByRole('switch', { name })`):
195
+
196
+ ```tsx
197
+ <Box border="field" borderRadius="medium" padding="medium">
198
+ <Box
199
+ display="flex"
200
+ alignItems="center"
201
+ justifyContent="spaceBetween"
202
+ gap="medium"
203
+ >
204
+ <Text>{item.name}</Text>
205
+ <Switch
206
+ aria-label={item.name}
207
+ checked={value.includes(item.id)}
208
+ onCheckedChange={() => toggle(item.id)}
209
+ >
210
+ {''}
211
+ </Switch>
212
+ </Box>
213
+ </Box>
214
+ ```
215
+
216
+ Keep the toggle field consistent with the selection:
217
+
218
+ - **Prune on change** — when an item is deselected (or an upstream condition
219
+ turns the section off), drop its id from the toggle field. Do this in the
220
+ consumer (a small `useEffect`/watch) and keep the row list presentational.
221
+ - **Shape the payload in one place** — map `(selectedIds, onIds)` →
222
+ `[{ id, <flag>: onIds.includes(id) }]` in a single helper so the field's wire
223
+ shape lives in one spot.
224
+
225
+ Reference implementation — Authority Contacts on the Create/Edit vendor-user
226
+ flows:
227
+
228
+ - `apps/admin-portal/src/components/AuthorityContactToggleList` — the row list
229
+ (props: `name`, `control`, `vendors: { id; name }[]`, optional
230
+ `label`/`description`/`rules`).
231
+ - `apps/admin-portal/src/utils/authorityContact` → `buildVendorAcPayload` —
232
+ payload shaping.
233
+ - `apps/admin-portal/src/hooks/useAuthorityContactSync` — prunes the field on
234
+ role/selection change.
235
+
236
+ Do NOTs (portal-hub):
237
+
238
+ - NEVER pass raw CSS to Spark `Box` layout props — they take token KEYS:
239
+ `justifyContent="spaceBetween"` (NOT `"space-between"`),
240
+ `alignItems`=`start|center|end|stretch`. An unrecognised value is silently
241
+ dropped and the row falls back to `flex-start` (the switch clumps next to the
242
+ label instead of aligning right).
243
+ - NEVER render a toggle row for an item that can't be changed in the current
244
+ flow — show those as read-only `Badge`s instead.
245
+ - NEVER put visibility/eligibility logic inside the row list — the consumer
246
+ gates it and owns pruning the field.