@stealthscale/component-actions 0.1.0 → 0.2.2

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/README.md CHANGED
@@ -1,8 +1,11 @@
1
1
  # @stealthscale/component-actions
2
2
 
3
- Draws what a person presses: the button, and the square button that holds one glyph. Every component
4
- binds a recipe and draws nothing of its own, so a theme restyles all of them by extending the
5
- recipe. The preset under `./theme` registers the recipes with an application's compiler.
3
+ Renders what a person presses: the button, the square button that contains one glyph, the group of
4
+ buttons that stay pressed, the two marks a button swaps between, the toggle between light and dark,
5
+ the clipboard whose trigger copies a value, and the trigger that saves a file built in the page.
6
+ Every component binds a recipe or composes one and does not add styles of its own, so a theme
7
+ restyles every component by extending its recipe. The preset under `./theme` registers the recipes
8
+ with an application's compiler.
6
9
 
7
10
  Every value a theme can change on a component is an axis of its recipe, so a caller sets it as a
8
11
  prop and writes no style. A caller changes the element a component draws with `as`.
@@ -13,17 +16,18 @@ prop and writes no style. A caller changes the element a component draws with `a
13
16
  pnpm add @stealthscale/component-actions
14
17
  ```
15
18
 
16
- The package peers on `react` and `@stealthscale/theme`. An application lists the preset under
17
- `./theme` among the presets its compiler installs.
19
+ The package peers on `react`, `@stealthscale/theme`, `@stealthscale/hooks` and
20
+ `@stealthscale/provider-color-mode`, whose `useColorMode` the color mode toggle reads. An
21
+ application lists the preset under `./theme` among the presets its compiler installs.
18
22
 
19
23
  ## Button
20
24
 
21
- Draws the element a person presses, in a look, a size and a status, raised off the page and glowing
22
- or rippling where a page sets that effect. Under a press the look fills to its pressed colour, the
23
- box scales to 98 percent, and an elevated button drops towards the page. A button that opens with a
24
- mark leads with one step less inset, so the room before the mark is the width of the gap after it
25
- rather than a word's worth. The element is `button`, and `type` defaults to `button` so one inside a
26
- form does not send it.
25
+ Renders a control that runs an action when pressed. The element is `button`, and `type` defaults to
26
+ `button`, so a button inside a form does not submit it. An element that `as` names takes a `type`
27
+ only from the caller, because an `a` reads `type` as the media type of the page it opens. A press
28
+ changes the fill, spreads a ripple from the middle of the box and lowers an elevated button, and the
29
+ box does not move. A button whose first child is an icon starts with one inset step less, so the
30
+ space before the icon matches the gap after it.
27
31
 
28
32
  ```tsx
29
33
  import { Button, ButtonPropsProvider } from "@stealthscale/component-actions";
@@ -31,6 +35,10 @@ import { Button, ButtonPropsProvider } from "@stealthscale/component-actions";
31
35
  <Button size="lg" variant="outline">
32
36
  Save
33
37
  </Button>;
38
+ <Button palette="error">Delete</Button>;
39
+ <Button effect="glow" palette="accent">
40
+ Upgrade
41
+ </Button>;
34
42
  <Button as="a">Read on</Button>;
35
43
  <ButtonPropsProvider value={{ size: "sm", variant: "subtle" }}>
36
44
  <Button>Cancel</Button>
@@ -38,29 +46,32 @@ import { Button, ButtonPropsProvider } from "@stealthscale/component-actions";
38
46
  </ButtonPropsProvider>;
39
47
  ```
40
48
 
41
- `ButtonPropsProvider` sets the variants of every button below it. A prop on the button itself
42
- overrides the provider's.
49
+ `ButtonPropsProvider` sets the variants of every button below it. A prop on the button overrides the
50
+ provider's value.
51
+
52
+ `palette` sets the palette every look reads. Without it the button draws in `primary`. `neutral`
53
+ draws a control in the ink of the text around it, for a button in a toolbar.
43
54
 
44
- The `glass` look is translucent, so the contrast of its label depends on what sits behind it. The
45
- theme's contrast gate measures the opaque looks alone, and a page puts a glass button on a surface
46
- it has checked.
55
+ The `glass` look is translucent, so the contrast of its label depends on the surface behind it. The
56
+ theme's contrast gate measures the opaque looks only. Put a glass button on a surface you have
57
+ checked.
47
58
 
48
59
  | Axis | Values | Default |
49
60
  | ----------- | ------------------------------------------------------------------ | ------- |
50
61
  | `variant` | `solid`, `subtle`, `surface`, `outline`, `ghost`, `plain`, `glass` | `solid` |
51
62
  | `size` | `xs`, `sm`, `md`, `lg`, `xl`, `2xl`, `3xl`, `4xl` | `md` |
52
- | `status` | `info`, `success`, `warning`, `error` | primary |
63
+ | `palette` | `primary`, `secondary`, `accent`, `neutral`, and the four statuses | primary |
53
64
  | `shape` | `square` | none |
54
- | `effect` | `glow`, `ripple` | none |
65
+ | `effect` | `glow`, `pulse` | none |
55
66
  | `elevation` | `raised`, `floating` | flat |
56
67
 
57
68
  ## IconButton
58
69
 
59
- Draws a button that holds one glyph and no words. It binds the button's recipe with the square shape
60
- as its default, so it takes every axis a button takes and a theme that moves the button moves it
61
- too. A glyph names nothing, so the props require an accessible name: `aria-label`, or
62
- `aria-labelledby` pointing at the element that holds the words. The type refuses an icon button
63
- without one.
70
+ Renders a square button that contains one icon and no text. It binds the button recipe with `shape`
71
+ defaulting to `square`, so it takes every axis a button takes, and a theme that restyles the button
72
+ restyles it too. An icon doesn't provide an accessible name, so the props require `aria-label`, or
73
+ `aria-labelledby` pointing at the element whose text names the control. An icon button with neither
74
+ is a type error.
64
75
 
65
76
  ```tsx
66
77
  import { IconButton } from "@stealthscale/component-actions";
@@ -73,6 +84,278 @@ import { Icon } from "@stealthscale/component-typography";
73
84
  </IconButton>;
74
85
  ```
75
86
 
87
+ A toggle is a button with `aria-pressed`. The recipe fills it while the attribute is true, so the
88
+ fill matches what a screen reader announces:
89
+
90
+ ```tsx
91
+ <IconButton aria-label="Dark mode" aria-pressed={dark} onClick={toggle} variant="ghost">
92
+ {dark ? <Moon /> : <Sun />}
93
+ </IconButton>
94
+ ```
95
+
96
+ A link rendered as a button in a bar of sections sets `aria-current="page"` on the current section,
97
+ and the recipe fills it the same way, in semibold. The ghost, glass, outline and plain looks take
98
+ the palette's subtle fill while on, the subtle and surface looks take the muted fill, and the solid
99
+ look draws an inset shadow. Under forced colors a button that is on fills with `Highlight` in every
100
+ look.
101
+
102
+ A control in a toolbar uses the ink of the text beside it. Set `palette="neutral"`.
103
+
104
+ ## ToggleGroup
105
+
106
+ Renders buttons that stay pressed: one at a time, as a choice, or several at once, as a set of
107
+ toggles. The root runs the Zag toggle group machine and renders the layout package's `Group`, and
108
+ each item renders `Button`.
109
+
110
+ ```tsx
111
+ import { ToggleGroup } from "@stealthscale/component-actions";
112
+
113
+ <ToggleGroup.Root aria-label="Text style" defaultValue={["bold"]} multiple variant="outline">
114
+ <ToggleGroup.Item aria-label="Bold" shape="square" value="bold">
115
+ <BoldIcon size="1em" />
116
+ </ToggleGroup.Item>
117
+ <ToggleGroup.Item aria-label="Italic" shape="square" value="italic">
118
+ <ItalicIcon size="1em" />
119
+ </ToggleGroup.Item>
120
+ </ToggleGroup.Root>;
121
+ ```
122
+
123
+ | Part | Element | What it renders |
124
+ | ------ | -------- | ---------------------------------------------- |
125
+ | `Root` | `div` | The layout's `Group`, attached by default |
126
+ | `Item` | `button` | The package's `Button`, pressed while it is on |
127
+
128
+ - `ToggleGroup.Root` takes `value`, `defaultValue`, `onValueChange`, `multiple`, `deselectable`
129
+ (true by default), `orientation`, `disabled`, `loopFocus`, `rovingFocus`, `dir`, `id` and `ids`.
130
+ `ToggleGroup.Item` takes `value` and `disabled`, and every prop of `Button`.
131
+ - Without `multiple` the root is a `radiogroup` and every item a radio with `aria-checked`. With
132
+ `multiple` the root is a `group` and every item reports `aria-pressed`. Name the root with
133
+ `aria-label` or `aria-labelledby`.
134
+ - The root passes `size`, `variant` and `palette` to every item. An item that is on takes its look's
135
+ pressed fill. The solid look marks it with an inset shadow and a semibold label, which an icon
136
+ does not show.
137
+ - `attached={false}` spaces the items by the group's `gap`. The group's other props, such as `grow`,
138
+ pass through.
139
+ - The arrow keys, Home and End move focus between the items and skip a disabled one. Space and Enter
140
+ toggle the focused item. In a `toolbar` the focus stops at either end.
141
+ - The group is one stop in the tab order. Tab enters it on its first item, and Shift+Tab returns to
142
+ the item focused last.
143
+
144
+ ## Swap
145
+
146
+ Renders two marks in one place and shows one of them. When the control around it changes state, one
147
+ mark leaves while the other enters. Both marks keep their room. The swap takes the size of the
148
+ larger mark and nothing beside it moves.
149
+
150
+ ```tsx
151
+ import { Volume2Icon, VolumeXIcon } from "lucide-react";
152
+
153
+ import { IconButton, Swap } from "@stealthscale/component-actions";
154
+
155
+ <IconButton aria-label="Mute" aria-pressed={muted} onClick={toggle}>
156
+ <Swap.Root swap={muted}>
157
+ <Swap.Indicator type="on">
158
+ <VolumeXIcon aria-hidden size="1em" />
159
+ </Swap.Indicator>
160
+ <Swap.Indicator type="off">
161
+ <Volume2Icon aria-hidden size="1em" />
162
+ </Swap.Indicator>
163
+ </Swap.Root>
164
+ </IconButton>;
165
+ ```
166
+
167
+ | Part | Element | What it renders |
168
+ | ----------- | ------- | ------------------------------------------------------------ |
169
+ | `Root` | `span` | The inline grid whose one cell both marks share |
170
+ | `Indicator` | `span` | One mark: `on` while `swap` is true, `off` while it is false |
171
+
172
+ | Axis | Values | Default |
173
+ | -------- | -------------------------------- | ------- |
174
+ | `motion` | `scale`, `fade`, `slide`, `none` | `scale` |
175
+
176
+ - `Swap.Root` takes `swap`, false by default, and writes `data-swap` as `on` or `off`. `lazyMount`
177
+ renders a mark only once it first shows. `unmountOnExit` removes a mark once it has left. Both are
178
+ false by default and leave both marks in the document.
179
+ - The mark that leaves runs its exit motion while the other runs its entry. It is `inert` meanwhile
180
+ and then carries `data-hidden`. The recipe renders `data-hidden` as `visibility: hidden`: a hidden
181
+ mark keeps its room and leaves the accessibility tree. A swap that first renders shows its mark at
182
+ rest.
183
+ - `scale` grows the entering mark from half its size and shrinks the leaving one, with a fade.
184
+ `fade` fades them. `slide` moves the entering mark up from below and the leaving one up and out.
185
+ `none` swaps them at once. Every motion swaps at once under reduced motion.
186
+ - The swap has no role and no name. The control around it states the state: a toggle button keeps
187
+ one name and sets `aria-pressed`, and a button whose words change names the action a press takes
188
+ and sets no `aria-pressed`. An icon mark is `aria-hidden`.
189
+
190
+ The swap does not offer these:
191
+
192
+ - `RootProvider` and `useSwap`. A caller passes `swap` from its own state.
193
+ - `hideMode`. A hidden mark keeps its room in every case.
194
+
195
+ ## ColorModeToggle
196
+
197
+ Renders the button that switches the page between light and dark. It reads and sets the mode through
198
+ `useColorMode` from `@stealthscale/provider-color-mode`, so it needs a `ColorModeProvider` above it,
199
+ which the shell provider renders.
200
+
201
+ ```tsx
202
+ import { MoonIcon, SunIcon } from "lucide-react";
203
+
204
+ import { ColorModeToggle } from "@stealthscale/component-actions";
205
+
206
+ <ColorModeToggle
207
+ dark={<MoonIcon aria-hidden size="1em" />}
208
+ light={<SunIcon aria-hidden size="1em" />}
209
+ />;
210
+ ```
211
+
212
+ - The toggle is the package's `Button` as a ghost, neutral square. Every button prop passes through,
213
+ so a bar sets the size and the look its other controls use.
214
+ - `aria-pressed` is true while the page is dark. The name, "Dark mode" unless `label` is passed,
215
+ stays the same in both states.
216
+ - The toggle shows the resolved mode. While the choice follows the operating system, it shows the
217
+ mode the system chose, and a press stores the other mode as an explicit choice.
218
+ - `dark` and `light` are the caller's glyphs. They change places through `Swap` with its default
219
+ motion.
220
+ - `onClick` runs before the mode changes, and a handler that calls `preventDefault` keeps the mode.
221
+
222
+ The toggle does not offer a choice to follow the operating system. A picker of light, dark and
223
+ system sets `setColorMode` from `useColorMode` itself.
224
+
225
+ ## Clipboard
226
+
227
+ Copies a value when its trigger is pressed and shows the copied state for a moment. The root runs
228
+ the Zag clipboard machine and holds the value. The parts:
229
+
230
+ - `Trigger` copies the value.
231
+ - `Indicator` shows `children` in the idle state and `copied` in the copied state.
232
+ - `Label` names the value, `Input` shows it read-only, and `ValueText` renders it inline.
233
+
234
+ `Clipboard.Trigger` takes its accessible name from `label`, "Copy to clipboard" by default, and from
235
+ `copiedLabel`, "Copied to clipboard" by default, during the copied state. A trigger with visible
236
+ text passes that text as `label` and shows `copiedLabel` during the copied state, so the accessible
237
+ name contains the visible label in both states (WCAG 2.5.3).
238
+
239
+ The trigger has no control styles. Render it as `Button` or `IconButton` with `as`, and set the
240
+ button variants through `ButtonPropsProvider`, because `as` does not retype the forwarded props.
241
+
242
+ ```tsx
243
+ import { Button, ButtonPropsProvider, Clipboard } from "@stealthscale/component-actions";
244
+
245
+ <Clipboard.Root value="https://stealthscale.io/payouts/4109">
246
+ <ButtonPropsProvider value={{ size: "sm", variant: "outline" }}>
247
+ <Clipboard.Trigger as={Button} copiedLabel="Copied" label="Copy the link">
248
+ <Clipboard.Indicator copied={<CheckIcon size="1em" />}>
249
+ <CopyIcon size="1em" />
250
+ </Clipboard.Indicator>
251
+ <Clipboard.Indicator copied="Copied">Copy the link</Clipboard.Indicator>
252
+ </Clipboard.Trigger>
253
+ </ButtonPropsProvider>
254
+ </Clipboard.Root>;
255
+ ```
256
+
257
+ Next to a field, the label names the input. The input is read-only but focusable and selectable, so
258
+ a person can copy by hand when the browser denies clipboard access:
259
+
260
+ ```tsx
261
+ <Clipboard.Root value={link}>
262
+ <Clipboard.Label>Link to the payout</Clipboard.Label>
263
+ <Clipboard.Control>
264
+ <Clipboard.Input as={Input} />
265
+ <Clipboard.Trigger as={IconButton}>
266
+ <Clipboard.Indicator copied={<CheckIcon size="1em" />}>
267
+ <CopyIcon size="1em" />
268
+ </Clipboard.Indicator>
269
+ </Clipboard.Trigger>
270
+ </Clipboard.Control>
271
+ </Clipboard.Root>
272
+ ```
273
+
274
+ `Clipboard.Consumer` passes the machine's API to a render function, for a custom control or for text
275
+ that changes with the state:
276
+
277
+ ```tsx
278
+ <Clipboard.Root value={link}>
279
+ <Clipboard.Consumer>
280
+ {(api) => (
281
+ <Button onClick={api.copy} palette={api.copied ? "success" : "neutral"}>
282
+ {api.copied ? "Copied" : "Copy the link"}
283
+ </Button>
284
+ )}
285
+ </Clipboard.Consumer>
286
+ </Clipboard.Root>
287
+ ```
288
+
289
+ The root takes the machine options: `value` or `defaultValue`, `timeout` in milliseconds (3000 by
290
+ default), `onStatusChange`, `onValueChange` and `ids`. The root `size` sets the label and the gaps.
291
+ The field and the button take their size through `InputPropsProvider` and `ButtonPropsProvider`. The
292
+ clipboard has no colour or surface of its own, so it offers no `palette` or `effect` axis.
293
+
294
+ | Axis | Values | Default |
295
+ | ------ | ---------------- | ------- |
296
+ | `size` | `sm`, `md`, `lg` | `md` |
297
+
298
+ ## DownloadTrigger
299
+
300
+ Saves a file built in the page when pressed. The browser receives the file through an anchor with a
301
+ `download` attribute and an object URL that points at data in the page. The trigger renders
302
+ `Button`, and it takes the axes listed under [Button](#button) and the variants a
303
+ `ButtonPropsProvider` sets.
304
+
305
+ - `data` is a string, a `Blob` or a `File`, or a function that returns one or a promise of one. The
306
+ trigger calls the function on each press to build the file when the reader asks for it.
307
+ - `fileName` is the name the browser saves the file under.
308
+ - `mimeType` sets the type of string data. A `Blob` or a `File` keeps its own type.
309
+
310
+ ```tsx
311
+ import { download, DownloadTrigger } from "@stealthscale/component-actions";
312
+
313
+ <DownloadTrigger data={csv} fileName="ledger.csv" mimeType="text/csv" variant="outline">
314
+ <DownloadIcon size="1em" />
315
+ Download the ledger
316
+ </DownloadTrigger>;
317
+ <DownloadTrigger
318
+ aria-label="Download ledger.csv"
319
+ data={csv}
320
+ fileName="ledger.csv"
321
+ shape="square"
322
+ variant="ghost"
323
+ >
324
+ <DownloadIcon size="1em" />
325
+ </DownloadTrigger>;
326
+ ```
327
+
328
+ `onClick` runs before the download. A handler that calls `preventDefault` cancels it.
329
+
330
+ While a `data` promise is pending, a page sets `aria-disabled` on the trigger and cancels a second
331
+ press in `onClick`. The trigger has no pending state of its own. `aria-disabled` keeps focus on the
332
+ trigger, where `disabled` would drop it:
333
+
334
+ ```tsx
335
+ <DownloadTrigger
336
+ aria-disabled={pending}
337
+ data={compress}
338
+ fileName="payouts.csv.gz"
339
+ onClick={(event) => {
340
+ if (pending) event.preventDefault();
341
+ }}
342
+ >
343
+ Download all payouts
344
+ </DownloadTrigger>
345
+ ```
346
+
347
+ A control that is not a button, such as a menu row, calls `download` with the same options. The
348
+ promise it returns rejects when the `data` function throws or its promise rejects.
349
+
350
+ ```tsx
351
+ <Menu.Root
352
+ onSelect={() => void download({ data: csv, fileName: "ledger.csv", mimeType: "text/csv" })}
353
+ >
354
+ ```
355
+
356
+ `download` saves text exactly as given and does not prepend a byte order mark. It creates its anchor
357
+ in the document of the window it runs in. It revokes the object URL one task after the click.
358
+
76
359
  ## Licence
77
360
 
78
361
  MIT. See [LICENSE](LICENSE).
@@ -1 +1 @@
1
- {"$schema":"http://cyclonedx.org/schema/bom-1.7.schema.json","bomFormat":"CycloneDX","specVersion":"1.7","version":1,"metadata":{"lifecycles":[{"phase":"build"}],"tools":{"components":[{"type":"application","name":"rolldown","version":"1.2.7"},{"type":"application","name":"vite","version":"8.2.2"},{"type":"library","name":"core","group":"@arethetypeswrong","version":"0.18.5","bom-ref":"pkg:npm/%40arethetypeswrong/core@0.18.5","author":"Andrew Branch","description":"The API behind arethetypeswrong.github.io","hashes":[{"alg":"SHA-512","content":"f72b63cc6c318e6f54cfb23d6af7dbb79be542deae93db914444b3263aabce797a58abc8e9dc184e8faf277534d96aeafe64778aa97f3f386f1e129d2480230d"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40arethetypeswrong/core@0.18.5","externalReferences":[{"url":"https://github.com/arethetypeswrong/arethetypeswrong.github.io.git#packages/core","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=20"}]},{"type":"library","name":"theme","group":"@stealthscale","version":"0.3.0","bom-ref":"pkg:npm/%40stealthscale/theme@0.3.0","description":"Publishes the foundation every recipe is written against, the runtime every component binds its recipe with, and the vocabulary a theme is written in.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/theme@0.3.0","externalReferences":[{"url":"https://github.com/stealth-scale/config/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/config.git#foundations/theme","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/config/tree/main/foundations/theme#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config-react","group":"@stealthscale","version":"0.8.0","bom-ref":"pkg:npm/%40stealthscale/vite-config-react@0.8.0","description":"Adds the JSX transform, the React lint rules, a test document and an MDX compiler to a package that renders.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-react@0.8.0","externalReferences":[{"url":"https://github.com/stealth-scale/config/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/config.git#packages/vite-config-react","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/config/tree/main/packages/vite-config-react#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config-theme","group":"@stealthscale","version":"0.1.0","bom-ref":"pkg:npm/%40stealthscale/vite-config-theme@0.1.0","description":"Adds the runtime generator to a design-system package and the stylesheet compiler to an application.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-theme@0.1.0","externalReferences":[{"url":"https://github.com/stealth-scale/config/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/config.git#packages/vite-config-theme","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/config/tree/main/packages/vite-config-theme#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config-typescript","group":"@stealthscale","version":"0.3.0","bom-ref":"pkg:npm/%40stealthscale/vite-config-typescript@0.3.0","description":"Sets the TypeScript options every stealthscale package compiles with.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-typescript@0.3.0","externalReferences":[{"url":"https://github.com/stealth-scale/config/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/config.git#packages/vite-config-typescript","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/config/tree/main/packages/vite-config-typescript#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config","group":"@stealthscale","version":"0.6.0","bom-ref":"pkg:npm/%40stealthscale/vite-config@0.6.0","description":"Configures a package from five Vite+ tiers and a named layer for every block.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config@0.6.0","externalReferences":[{"url":"https://github.com/stealth-scale/config/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/config.git#packages/vite-config","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/config/tree/main/packages/vite-config#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"react","group":"@testing-library","version":"16.3.3","bom-ref":"pkg:npm/%40testing-library/react@16.3.3","author":"Kent C. Dodds <me@kentcdodds.com> (https://kentcdodds.com)","description":"Simple and complete React DOM testing utilities that encourage good testing practices.","hashes":[{"alg":"SHA-512","content":"528d7ddcd8106cf333ea5aeb86d45040570c0ba45efc42cb15b6ee54bdf4583959c65a597fdfe53074c05713d12f0d6ad62bbd389991d5cd812e210d46cb5d06"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40testing-library/react@16.3.3","externalReferences":[{"url":"https://github.com/testing-library/react-testing-library/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"https://github.com/testing-library/react-testing-library","type":"vcs","comment":"as detected from PackageJson property \"repository.url\""},{"url":"https://github.com/testing-library/react-testing-library#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=18"}]},{"type":"library","name":"react-dom","group":"@types","version":"19.3.0","bom-ref":"pkg:npm/%40types/react-dom@19.3.0","description":"TypeScript definitions for react-dom","hashes":[{"alg":"SHA-512","content":"648edb538da66575ca1e7fea34b130d88adb888354ed7e7ebdf81d8b10479023696165e32a07d0fcffaec866f90a338b07d51c9d37a0debca542d5768729b8e1"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40types/react-dom@19.3.0","externalReferences":[{"url":"https://github.com/DefinitelyTyped/DefinitelyTyped.git#types/react-dom","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react-dom","type":"website","comment":"as detected from PackageJson property \"homepage\""}]},{"type":"library","name":"react","group":"@types","version":"19.3.0","bom-ref":"pkg:npm/%40types/react@19.3.0","description":"TypeScript definitions for react","hashes":[{"alg":"SHA-512","content":"374ac50ae1fd628c46f7f9bad65f4c7e924a7e62ce554d1e9bb8a9233e9346049292f45e2c1f6f2fce4607ecabf01b3995eaa9be0f7a252c05e194b5b38be242"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40types/react@19.3.0","externalReferences":[{"url":"https://github.com/DefinitelyTyped/DefinitelyTyped.git#types/react","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react","type":"website","comment":"as detected from PackageJson property \"homepage\""}]},{"type":"library","name":"babel-plugin-react-compiler","version":"1.0.0","bom-ref":"pkg:npm/babel-plugin-react-compiler@1.0.0","description":"Babel plugin for React Compiler.","hashes":[{"alg":"SHA-512","content":"2319bcb457e828a20f61d0822984ecaaff85778209d0342a3321229a8fa9c5438c511f5c54f9704eb16df40beefb771be99a77980ce5fadd4cac6d9fc712acc7"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/babel-plugin-react-compiler@1.0.0","externalReferences":[{"url":"git+https://github.com/facebook/react.git#compiler/packages/babel-plugin-react-compiler","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""}]},{"type":"library","name":"happy-dom","version":"20.14.5","bom-ref":"pkg:npm/happy-dom@20.14.5","author":"David Ortner","description":"Happy DOM is a JavaScript implementation of a web browser without its graphical user interface. It includes many web standards from WHATWG DOM and HTML.","hashes":[{"alg":"SHA-512","content":"c7f47392958ee346d38c8a13df4890b6deb814b2e61ff89171408dd97fff6cbc7b1f789f91d7cf5f2aacae8fce62dab32008622cc300ee69a2391f42dcd38a8d"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/happy-dom@20.14.5","externalReferences":[{"url":"https://github.com/capricorn86/happy-dom","type":"vcs","comment":"as detected from PackageJson property \"repository\""},{"url":"https://github.com/capricorn86/happy-dom","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=20.0.0"}]},{"type":"library","name":"oxc-transform-react","version":"0.149.0","bom-ref":"pkg:npm/oxc-transform-react@0.149.0","author":"Boshen and oxc contributors","description":"Oxc React Compiler Node API","hashes":[{"alg":"SHA-512","content":"69bdddc5c3ed90349f211f6d35dc4752d9a974bd258479ddb010fd214014e41c6d26dc061bff39367473b367f62b0a2e3641e5edc692b3030b41e52fc3714447"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/oxc-transform-react@0.149.0","externalReferences":[{"url":"https://github.com/oxc-project/oxc/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/oxc-project/oxc.git#napi/transform-react","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://oxc.rs","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":"^20.19.0 || >=22.12.0"}]},{"type":"library","name":"react-dom","version":"19.3.0","bom-ref":"pkg:npm/react-dom@19.3.0","description":"React package for working with the DOM.","hashes":[{"alg":"SHA-512","content":"24393c76089fe753a31680c4ef4f8e4fd202c98afeebd1e59a284dc29d7e36c7db9dadede6c22209af59264b43990e3fd5bfeb9f6ea1200476b985c332be6bd1"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/react-dom@19.3.0","externalReferences":[{"url":"https://github.com/react/react/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"https://github.com/react/react.git#packages/react-dom","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://react.dev/","type":"website","comment":"as detected from PackageJson property \"homepage\""}]},{"type":"library","name":"react","version":"19.3.0","bom-ref":"pkg:npm/react@19.3.0","description":"React is a JavaScript library for building user interfaces.","hashes":[{"alg":"SHA-512","content":"13c2d471bb415addb46db9766281dfc7864305dc554df38ab42667f5c0d227897afe7ba8029729201723e3bb76c19a155fc836647b8c1db892860091d53e52a2"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/react@19.3.0","externalReferences":[{"url":"https://github.com/react/react/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"https://github.com/react/react.git#packages/react","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://react.dev/","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=0.10.0"}]},{"type":"library","name":"typescript","version":"7.0.2","bom-ref":"pkg:npm/typescript@7.0.2","author":"Microsoft Corp.","description":"TypeScript is a language for application scale JavaScript development","hashes":[{"alg":"SHA-512","content":"f0561abbdea8dcd28e85b8ca8bfa8dbc6fd6e63873c646dd9b9b23f406d9ff94f9b16aa7de12602df1b1dbbb11299593bf2cc23fc74b4414dfe6d05349155434"}],"licenses":[{"license":{"id":"Apache-2.0"}}],"purl":"pkg:npm/typescript@7.0.2","externalReferences":[{"url":"https://github.com/microsoft/TypeScript/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"https://github.com/microsoft/TypeScript.git","type":"vcs","comment":"as detected from PackageJson property \"repository.url\""},{"url":"https://www.typescriptlang.org/","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=16.20.0"}]},{"type":"library","name":"vitest","version":"4.1.11","bom-ref":"pkg:npm/vitest@4.1.11","author":"Anthony Fu <anthonyfu117@hotmail.com>","description":"Next generation testing framework powered by Vite","hashes":[{"alg":"SHA-512","content":"7e1002acd5d489d21b19206be4595bb8190eed5582d59c8b9740cee025360eb42800fc57f3862cc6cf877864298a2e656565754388016534eee3d985f80e8477"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/vitest@4.1.11","externalReferences":[{"url":"https://github.com/vitest-dev/vitest/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"git+https://github.com/vitest-dev/vitest.git#packages/vitest","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://vitest.dev","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":"^20.0.0 || ^22.0.0 || >=24.0.0"}]}]},"component":{"type":"library","name":"component-actions","group":"@stealthscale","version":"0.1.0","bom-ref":"pkg:npm/%40stealthscale/component-actions@0.1.0","description":"Draws what a person presses: a button, a toggle, and the triggers that carry an action.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/component-actions@0.1.0","externalReferences":[{"url":"https://github.com/stealth-scale/config/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/config.git#components/actions","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/config/tree/main/components/actions#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}],"evidence":{"licenses":[{"license":{"name":"file: LICENSE","text":{"content":"TUlUIExpY2Vuc2UKCkNvcHlyaWdodCAoYykgMjAyNiBTdGVhbHRoIFNjYWxlIEIuVi4KClBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHkKb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksIHRvIGRlYWwKaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cwp0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsCmNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcwpmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgoKVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsCmNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuCgpUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgpJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFCkFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwKT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUKU09GVFdBUkUuCg==","contentType":"text/plain","encoding":"base64"}}}]}},"supplier":{"name":"Stealth Scale B.V.","url":["https://stealthscale.io"]}},"components":[],"dependencies":[{"ref":"pkg:npm/%40stealthscale/component-actions@0.1.0"}]}
1
+ {"$schema":"http://cyclonedx.org/schema/bom-1.7.schema.json","bomFormat":"CycloneDX","specVersion":"1.7","version":1,"metadata":{"lifecycles":[{"phase":"build"}],"tools":{"components":[{"type":"application","name":"rolldown","version":"1.2.12"},{"type":"application","name":"vite","version":"8.3.3"},{"type":"library","name":"core","group":"@arethetypeswrong","version":"0.18.5","bom-ref":"pkg:npm/%40arethetypeswrong/core@0.18.5","author":"Andrew Branch","description":"The API behind arethetypeswrong.github.io","hashes":[{"alg":"SHA-512","content":"f72b63cc6c318e6f54cfb23d6af7dbb79be542deae93db914444b3263aabce797a58abc8e9dc184e8faf277534d96aeafe64778aa97f3f386f1e129d2480230d"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40arethetypeswrong/core@0.18.5","externalReferences":[{"url":"https://github.com/arethetypeswrong/arethetypeswrong.github.io.git#packages/core","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=20"}]},{"type":"library","name":"hooks","group":"@stealthscale","version":"0.3.0","bom-ref":"pkg:npm/%40stealthscale/hooks@0.3.0","description":"The React hooks a component uses to read the page it draws into: how the page is read, what it measures, and what a value was on the previous render.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/hooks@0.3.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#foundations/hooks","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/foundations/hooks#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"provider-color-mode","group":"@stealthscale","version":"0.2.2","bom-ref":"pkg:npm/%40stealthscale/provider-color-mode@0.2.2","description":"Puts a colour mode in scope, remembers what a person chose, and settles the first paint before the page draws.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/provider-color-mode@0.2.2","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#foundations/providers/color-mode","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/foundations/providers/color-mode#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"settings","group":"@stealthscale","version":"0.2.0","bom-ref":"pkg:npm/%40stealthscale/settings@0.2.0","description":"Remembers one named setting a person made, per application, held to the values it is allowed to take and kept where the reader chooses.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/settings@0.2.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#foundations/settings","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/foundations/settings#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"theme","group":"@stealthscale","version":"0.5.0","bom-ref":"pkg:npm/%40stealthscale/theme@0.5.0","description":"Publishes the foundation every recipe is written against, the runtime every component binds its recipe with, and the vocabulary a theme is written in.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/theme@0.5.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#foundations/theme","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/foundations/theme#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config-i18n","group":"@stealthscale","version":"0.2.1","bom-ref":"pkg:npm/%40stealthscale/vite-config-i18n@0.2.1","description":"Configures a package or an application with words: the catalogue plugin, and the words in scope for its specifications.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-i18n@0.2.1","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/vite-config-i18n","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/vite-config-i18n#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config-react","group":"@stealthscale","version":"0.9.1","bom-ref":"pkg:npm/%40stealthscale/vite-config-react@0.9.1","description":"Adds the JSX transform, the React lint rules, a test document and an MDX compiler to a package that renders.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-react@0.9.1","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/vite-config-react","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/vite-config-react#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config-specimen","group":"@stealthscale","version":"0.2.1","bom-ref":"pkg:npm/%40stealthscale/vite-config-specimen@0.2.1","description":"Configures an application that shows a catalogue, and the workspace root the specimens sit under.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-specimen@0.2.1","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/vite-config-specimen","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/vite-config-specimen#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config-theme","group":"@stealthscale","version":"0.3.0","bom-ref":"pkg:npm/%40stealthscale/vite-config-theme@0.3.0","description":"Adds the runtime generator to a design-system package and the stylesheet compiler to an application.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-theme@0.3.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/vite-config-theme","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/vite-config-theme#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config-typescript","group":"@stealthscale","version":"0.3.0","bom-ref":"pkg:npm/%40stealthscale/vite-config-typescript@0.3.0","description":"Sets the TypeScript options every stealthscale package compiles with.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-typescript@0.3.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/vite-config-typescript","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/vite-config-typescript#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config","group":"@stealthscale","version":"0.8.0","bom-ref":"pkg:npm/%40stealthscale/vite-config@0.8.0","description":"Configures a package from five Vite+ tiers and a named layer for every block.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config@0.8.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/vite-config","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/vite-config#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"react","group":"@testing-library","version":"16.3.3","bom-ref":"pkg:npm/%40testing-library/react@16.3.3","author":"Kent C. Dodds <me@kentcdodds.com> (https://kentcdodds.com)","description":"Simple and complete React DOM testing utilities that encourage good testing practices.","hashes":[{"alg":"SHA-512","content":"528d7ddcd8106cf333ea5aeb86d45040570c0ba45efc42cb15b6ee54bdf4583959c65a597fdfe53074c05713d12f0d6ad62bbd389991d5cd812e210d46cb5d06"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40testing-library/react@16.3.3","externalReferences":[{"url":"https://github.com/testing-library/react-testing-library/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"https://github.com/testing-library/react-testing-library","type":"vcs","comment":"as detected from PackageJson property \"repository.url\""},{"url":"https://github.com/testing-library/react-testing-library#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=18"}]},{"type":"library","name":"react-dom","group":"@types","version":"19.3.0","bom-ref":"pkg:npm/%40types/react-dom@19.3.0","description":"TypeScript definitions for react-dom","hashes":[{"alg":"SHA-512","content":"648edb538da66575ca1e7fea34b130d88adb888354ed7e7ebdf81d8b10479023696165e32a07d0fcffaec866f90a338b07d51c9d37a0debca542d5768729b8e1"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40types/react-dom@19.3.0","externalReferences":[{"url":"https://github.com/DefinitelyTyped/DefinitelyTyped.git#types/react-dom","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react-dom","type":"website","comment":"as detected from PackageJson property \"homepage\""}]},{"type":"library","name":"react","group":"@types","version":"19.3.0","bom-ref":"pkg:npm/%40types/react@19.3.0","description":"TypeScript definitions for react","hashes":[{"alg":"SHA-512","content":"374ac50ae1fd628c46f7f9bad65f4c7e924a7e62ce554d1e9bb8a9233e9346049292f45e2c1f6f2fce4607ecabf01b3995eaa9be0f7a252c05e194b5b38be242"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40types/react@19.3.0","externalReferences":[{"url":"https://github.com/DefinitelyTyped/DefinitelyTyped.git#types/react","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react","type":"website","comment":"as detected from PackageJson property \"homepage\""}]},{"type":"library","name":"happy-dom","version":"20.14.5","bom-ref":"pkg:npm/happy-dom@20.14.5","author":"David Ortner","description":"Happy DOM is a JavaScript implementation of a web browser without its graphical user interface. It includes many web standards from WHATWG DOM and HTML.","hashes":[{"alg":"SHA-512","content":"c7f47392958ee346d38c8a13df4890b6deb814b2e61ff89171408dd97fff6cbc7b1f789f91d7cf5f2aacae8fce62dab32008622cc300ee69a2391f42dcd38a8d"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/happy-dom@20.14.5","externalReferences":[{"url":"https://github.com/capricorn86/happy-dom","type":"vcs","comment":"as detected from PackageJson property \"repository\""},{"url":"https://github.com/capricorn86/happy-dom","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=20.0.0"}]},{"type":"library","name":"lucide-react","version":"1.52.0","bom-ref":"pkg:npm/lucide-react@1.52.0","author":"Eric Fennis","description":"A Lucide icon library package for React applications.","hashes":[{"alg":"SHA-512","content":"4d480fb65e5923d5a0c4e71bbb8724682e41de5d6ac4f42b08c81be8e7d407da30c7f3af4897dc7fddd2320516031470e7fd570df87db88e45e623465c27060d"}],"licenses":[{"license":{"id":"ISC"}}],"purl":"pkg:npm/lucide-react@1.52.0","externalReferences":[{"url":"https://github.com/lucide-icons/lucide/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"https://github.com/lucide-icons/lucide.git#packages/lucide-react","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://lucide.dev","type":"website","comment":"as detected from PackageJson property \"homepage\""}]},{"type":"library","name":"oxc-transform-react","version":"0.153.0","bom-ref":"pkg:npm/oxc-transform-react@0.153.0","author":"Boshen and oxc contributors","description":"Oxc React Compiler Node API","hashes":[{"alg":"SHA-512","content":"f69fc1088423d76cbc51b95edd6594c55799cbcf118ea394edc569d7c70b57b3d36cd6156963b2c42dbe27d83e11d0bdfc038a5f35ffcf597dd8d67daefbe055"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/oxc-transform-react@0.153.0","externalReferences":[{"url":"https://github.com/oxc-project/oxc/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/oxc-project/oxc.git#napi/transform-react","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://oxc.rs","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":"^20.19.0 || >=22.12.0"}]},{"type":"library","name":"react-dom","version":"19.3.0","bom-ref":"pkg:npm/react-dom@19.3.0","description":"React package for working with the DOM.","hashes":[{"alg":"SHA-512","content":"24393c76089fe753a31680c4ef4f8e4fd202c98afeebd1e59a284dc29d7e36c7db9dadede6c22209af59264b43990e3fd5bfeb9f6ea1200476b985c332be6bd1"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/react-dom@19.3.0","externalReferences":[{"url":"https://github.com/react/react/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"https://github.com/react/react.git#packages/react-dom","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://react.dev/","type":"website","comment":"as detected from PackageJson property \"homepage\""}]},{"type":"library","name":"react","version":"19.3.0","bom-ref":"pkg:npm/react@19.3.0","description":"React is a JavaScript library for building user interfaces.","hashes":[{"alg":"SHA-512","content":"13c2d471bb415addb46db9766281dfc7864305dc554df38ab42667f5c0d227897afe7ba8029729201723e3bb76c19a155fc836647b8c1db892860091d53e52a2"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/react@19.3.0","externalReferences":[{"url":"https://github.com/react/react/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"https://github.com/react/react.git#packages/react","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://react.dev/","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=0.10.0"}]},{"type":"library","name":"typescript","version":"7.0.2","bom-ref":"pkg:npm/typescript@7.0.2","author":"Microsoft Corp.","description":"TypeScript is a language for application scale JavaScript development","hashes":[{"alg":"SHA-512","content":"f0561abbdea8dcd28e85b8ca8bfa8dbc6fd6e63873c646dd9b9b23f406d9ff94f9b16aa7de12602df1b1dbbb11299593bf2cc23fc74b4414dfe6d05349155434"}],"licenses":[{"license":{"id":"Apache-2.0"}}],"purl":"pkg:npm/typescript@7.0.2","externalReferences":[{"url":"https://github.com/microsoft/TypeScript/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"https://github.com/microsoft/TypeScript.git","type":"vcs","comment":"as detected from PackageJson property \"repository.url\""},{"url":"https://www.typescriptlang.org/","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=16.20.0"}]},{"type":"library","name":"vitest","version":"5.0.3","bom-ref":"pkg:npm/vitest@5.0.3","author":"Anthony Fu <anthonyfu117@hotmail.com>","description":"Next generation testing framework powered by Vite","hashes":[{"alg":"SHA-512","content":"c4cc3ded2deb8ddb63e5d9156adee30aca96069bdc86cdd196941cb54ab0243d0a904464e34bf3d9f27bee50f05bf57387fa64d7c788b5803392876149eb378d"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/vitest@5.0.3","externalReferences":[{"url":"https://github.com/vitest-dev/vitest/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"git+https://github.com/vitest-dev/vitest.git#packages/vitest","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://vitest.dev","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":"^22.12.0 || ^24.0.0 || >=26.0.0"}]}]},"component":{"type":"library","name":"component-actions","group":"@stealthscale","version":"0.2.2","bom-ref":"pkg:npm/%40stealthscale/component-actions@0.2.2","description":"Renders what a person presses: a button, a toggle group, a swap, a color mode toggle, a clipboard and a download trigger.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/component-actions@0.2.2","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#components/actions","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/components/actions#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}],"evidence":{"licenses":[{"license":{"name":"file: LICENSE","text":{"content":"TUlUIExpY2Vuc2UKCkNvcHlyaWdodCAoYykgMjAyNiBTdGVhbHRoIFNjYWxlIEIuVi4KClBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHkKb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksIHRvIGRlYWwKaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cwp0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsCmNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcwpmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgoKVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsCmNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuCgpUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgpJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFCkFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwKT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUKU09GVFdBUkUuCg==","contentType":"text/plain","encoding":"base64"}}}]}},"supplier":{"name":"Stealth Scale B.V.","url":["https://stealthscale.io"]}},"components":[],"dependencies":[{"ref":"pkg:npm/%40stealthscale/component-actions@0.2.2"}]}