@wtfalch/design 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +147 -0
- package/dist/components/Brand.d.ts +10 -0
- package/dist/components/Brand.js +212 -0
- package/dist/components/Button.d.ts +63 -0
- package/dist/components/Button.js +74 -0
- package/dist/components/Callout.d.ts +37 -0
- package/dist/components/Callout.js +71 -0
- package/dist/components/Card.d.ts +42 -0
- package/dist/components/Card.js +30 -0
- package/dist/components/Checkbox.d.ts +32 -0
- package/dist/components/Checkbox.js +31 -0
- package/dist/components/DangerZone.d.ts +59 -0
- package/dist/components/DangerZone.js +50 -0
- package/dist/components/Dialog.d.ts +28 -0
- package/dist/components/Dialog.js +29 -0
- package/dist/components/Empty.d.ts +45 -0
- package/dist/components/Empty.js +35 -0
- package/dist/components/Field.d.ts +58 -0
- package/dist/components/Field.js +46 -0
- package/dist/components/Icon.d.ts +64 -0
- package/dist/components/Icon.js +235 -0
- package/dist/components/Illustration.d.ts +36 -0
- package/dist/components/Illustration.js +48 -0
- package/dist/components/Input.d.ts +14 -0
- package/dist/components/Input.js +65 -0
- package/dist/components/Markdown.d.ts +21 -0
- package/dist/components/Markdown.js +29 -0
- package/dist/components/Modal.d.ts +59 -0
- package/dist/components/Modal.js +72 -0
- package/dist/components/Pill.d.ts +40 -0
- package/dist/components/Pill.js +41 -0
- package/dist/components/Progress.d.ts +35 -0
- package/dist/components/Progress.js +27 -0
- package/dist/components/Rows.d.ts +101 -0
- package/dist/components/Rows.js +55 -0
- package/dist/components/Select.d.ts +28 -0
- package/dist/components/Select.js +56 -0
- package/dist/components/SizeGrid.d.ts +34 -0
- package/dist/components/SizeGrid.js +41 -0
- package/dist/components/Skeleton.d.ts +45 -0
- package/dist/components/Skeleton.js +47 -0
- package/dist/components/Slider.d.ts +70 -0
- package/dist/components/Slider.js +100 -0
- package/dist/components/Table.d.ts +43 -0
- package/dist/components/Table.js +13 -0
- package/dist/components/Tabs.d.ts +72 -0
- package/dist/components/Tabs.js +82 -0
- package/dist/components/Textarea.d.ts +9 -0
- package/dist/components/Textarea.js +22 -0
- package/dist/components/Toast.d.ts +43 -0
- package/dist/components/Toast.js +78 -0
- package/dist/components/Toggle.d.ts +56 -0
- package/dist/components/Toggle.js +189 -0
- package/dist/components/Tooltip.d.ts +22 -0
- package/dist/components/Tooltip.js +62 -0
- package/dist/components/Tour.d.ts +33 -0
- package/dist/components/Tour.js +108 -0
- package/dist/components/iconNames.d.ts +18 -0
- package/dist/components/iconNames.js +60 -0
- package/dist/components/tourMarker.d.ts +29 -0
- package/dist/components/tourMarker.js +58 -0
- package/dist/contrast.d.ts +18 -0
- package/dist/contrast.js +27 -0
- package/dist/hooks/useTrapFocus.d.ts +24 -0
- package/dist/hooks/useTrapFocus.js +67 -0
- package/dist/illustrations.d.ts +11 -0
- package/dist/illustrations.js +55 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.js +65 -0
- package/dist/styles/index.css +3124 -0
- package/dist/themes.d.ts +210 -0
- package/dist/themes.js +300 -0
- package/dist/tokens.css +251 -0
- package/package.json +74 -0
package/dist/tokens.css
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The token vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* This file is the contract. `styles.css` may only consume these; a theme may
|
|
5
|
+
* only supply values for them. Nothing else is themeable, and that is the
|
|
6
|
+
* point: the moment a theme can ship a selector, every theme becomes a fork of
|
|
7
|
+
* the stylesheet and no change to the app is safe again.
|
|
8
|
+
*
|
|
9
|
+
* What makes a theme expressive is not permission to write rules — it is a
|
|
10
|
+
* vocabulary wide enough that the thing you want to vary is a value. So this
|
|
11
|
+
* covers seven axes, not just colour: a theme can change how the app *moves*
|
|
12
|
+
* and how dense it is without touching a selector.
|
|
13
|
+
*
|
|
14
|
+
* Base values here are today's, exactly. Adding this file changed nothing on
|
|
15
|
+
* screen, which is how a 200-literal refactor stays reviewable.
|
|
16
|
+
*
|
|
17
|
+
* Keys are mirrored in `themes.ts` as `ThemeTokens`. Add one here, add it
|
|
18
|
+
* there — a token a theme cannot name is a token no theme can use.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
:root {
|
|
22
|
+
/* ---- colour ------------------------------------------------------- */
|
|
23
|
+
/* Low-chroma slate, and a muted teal.
|
|
24
|
+
Neither warm nor cold on purpose: a beige-leaning neutral reads cosy and a
|
|
25
|
+
navy-leaning one reads cold, and this is a tool somebody keeps open all
|
|
26
|
+
day. Teal sits between the two, and unlike a saturated blue it does not
|
|
27
|
+
compete with the text for attention.
|
|
28
|
+
Every pair below is measured rather than chosen -- see the block comment
|
|
29
|
+
above `--border-strong`. */
|
|
30
|
+
--bg: #12151a;
|
|
31
|
+
--panel: #191d24;
|
|
32
|
+
--panel-2: #222831;
|
|
33
|
+
--border: #262c36;
|
|
34
|
+
--text: #e4e8ee;
|
|
35
|
+
--muted: #98a1b0;
|
|
36
|
+
--accent: #4fb3a8;
|
|
37
|
+
--accent-dim: #2f6b66;
|
|
38
|
+
/* Status colours that survive a light background too. The old set was
|
|
39
|
+
dark-mode neon -- `#4ade80` on white is 1.74:1 -- and the light theme never
|
|
40
|
+
overrode them, so a `running` pill was unreadable on Paper. */
|
|
41
|
+
--good: #68c48c;
|
|
42
|
+
--warn: #d9a65a;
|
|
43
|
+
--bad: #e28680;
|
|
44
|
+
/* Information, as a colour of its own. `Callout`'s info tone used to borrow
|
|
45
|
+
the accent for its edge and take no fill, so on the two teal themes an
|
|
46
|
+
"information" box was a teal-edged box and William read it as "isn't
|
|
47
|
+
information blue?" (2026-09-03). It is now: blue, and the fourth status
|
|
48
|
+
colour beside good, warn and bad. */
|
|
49
|
+
--info: #74b3ff;
|
|
50
|
+
/* Text that sits *on* the accent. Was hardcoded `#fff`, which made a primary
|
|
51
|
+
button vanish under any pale accent — white on near-white. */
|
|
52
|
+
/* Near-black, because the accent is light enough to need it. White on the old
|
|
53
|
+
`#5b9dff` was 2.72:1 -- the primary button, the single most important
|
|
54
|
+
control in the app, failed the body-text minimum by a wide margin. */
|
|
55
|
+
--on-accent: #06181a;
|
|
56
|
+
|
|
57
|
+
/* ---- surface ------------------------------------------------------ */
|
|
58
|
+
/* Consumed as `background:`, never `background-color:`, so a theme may hand
|
|
59
|
+
it a gradient or an image rather than only a colour. */
|
|
60
|
+
--app-bg: var(--bg);
|
|
61
|
+
/* A slot. Inert unless a theme fills it — see `body::before` in styles.css.
|
|
62
|
+
This is how a theme gets a grain, a vignette or a wash without shipping a
|
|
63
|
+
rule to create the layer. */
|
|
64
|
+
--app-overlay: none;
|
|
65
|
+
--app-overlay-opacity: 0;
|
|
66
|
+
/* Elevation as a scale rather than one shadow. Black is right on a dark UI
|
|
67
|
+
and muddy on a light one, so this has to be a theme's decision. */
|
|
68
|
+
--shadow-1: 0 6px 20px rgba(0, 0, 0, 0.22);
|
|
69
|
+
--shadow-2: 0 8px 28px rgba(0, 0, 0, 0.28);
|
|
70
|
+
--shadow-3: 0 10px 34px rgba(0, 0, 0, 0.3);
|
|
71
|
+
--scrim: rgba(0, 0, 0, 0.45);
|
|
72
|
+
|
|
73
|
+
/* ---- typography --------------------------------------------------- */
|
|
74
|
+
--font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
75
|
+
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
|
|
76
|
+
--font-size: 14px;
|
|
77
|
+
/* The scale, because there was not one.
|
|
78
|
+
`styles.css` carried eleven distinct sizes -- 10, 10.5, 11, 12, 13, 14, 15,
|
|
79
|
+
16, 17, 18, 19 -- and used `--font-size` exactly once. Eleven sizes is not a
|
|
80
|
+
hierarchy, it is eleven separate decisions, and it is most of why the app
|
|
81
|
+
felt uneven: two labels doing the same job would differ by a pixel for no
|
|
82
|
+
reason anybody could state.
|
|
83
|
+
Six steps, and every one of them earns its place: `xs` for the meter row and
|
|
84
|
+
mono chips, `sm` for hints, base for body, then three heading steps. A theme
|
|
85
|
+
can move the whole scale by moving `--font-size`, because they are all
|
|
86
|
+
relative to it.
|
|
87
|
+
|
|
88
|
+
`calc` off the token rather than `rem`, which is relative to the *root*
|
|
89
|
+
element and not to this -- `--font-size` is set on `body`, so a rem scale
|
|
90
|
+
would have silently resolved against the browser's 16px and every step
|
|
91
|
+
would have been wrong by a pixel and a half. */
|
|
92
|
+
/* `2xs` exists so the scale never has to round *up*. The first pass mapped
|
|
93
|
+
10px and 10.5px onto 11px and 15px onto 16px, and the app visibly grew --
|
|
94
|
+
a scale that inflates is not a scale, it is a resize. */
|
|
95
|
+
--text-2xs: calc(var(--font-size) * 0.714);
|
|
96
|
+
--text-xs: calc(var(--font-size) * 0.786);
|
|
97
|
+
--text-sm: calc(var(--font-size) * 0.857);
|
|
98
|
+
--text-base: var(--font-size);
|
|
99
|
+
--text-md: calc(var(--font-size) * 1.143);
|
|
100
|
+
--text-lg: calc(var(--font-size) * 1.286);
|
|
101
|
+
--text-xl: calc(var(--font-size) * 1.429);
|
|
102
|
+
--line-height: 1.5;
|
|
103
|
+
--tracking: 0;
|
|
104
|
+
--weight: 400;
|
|
105
|
+
--weight-strong: 600;
|
|
106
|
+
|
|
107
|
+
/* ---- shape -------------------------------------------------------- */
|
|
108
|
+
/* There were fifteen distinct radii and a `--radius` token used nine times
|
|
109
|
+
while literal `6px` appeared twelve. Four steps and a pill is the whole
|
|
110
|
+
range anything here actually needed. */
|
|
111
|
+
--radius-sm: 3px;
|
|
112
|
+
--radius: 6px;
|
|
113
|
+
--radius-md: 8px;
|
|
114
|
+
--radius-lg: 12px;
|
|
115
|
+
--radius-pill: 999px;
|
|
116
|
+
--border-width: 1px;
|
|
117
|
+
/* The surface a control sits on: an input, a select, a button that is not
|
|
118
|
+
the primary one. Derived from the two panel tones rather than stated, so a
|
|
119
|
+
theme that moves the panels moves the controls with them -- but themeable,
|
|
120
|
+
because a theme may want a control to read as inset or raised against a
|
|
121
|
+
panel it chose. Same bargain as `--app-bg`.
|
|
122
|
+
It lived on `:root` in `styles.css` and was used seven times, which made it
|
|
123
|
+
a token in every respect except being in the vocabulary a theme can name.
|
|
124
|
+
The audit that found it was looking for something else. */
|
|
125
|
+
--control: color-mix(in srgb, var(--panel-2) 62%, var(--panel));
|
|
126
|
+
|
|
127
|
+
/* Two jobs, two tokens.
|
|
128
|
+
`--border` was drawing both the hairline between two rows and the outline
|
|
129
|
+
of every input, select and button. Those have different requirements: a
|
|
130
|
+
divider is decoration and has no contrast minimum, while a control's
|
|
131
|
+
boundary is what tells you it is a control -- WCAG 1.4.11 wants 3:1 for
|
|
132
|
+
that. One token could satisfy either but not both, and it was set for the
|
|
133
|
+
divider, so every input in the app outlined itself at 1.26:1.
|
|
134
|
+
Solved for the threshold rather than picked: this is the first step on the
|
|
135
|
+
neutral ramp that clears 3:1 against `--panel`. */
|
|
136
|
+
--border-strong: #5f6a7a;
|
|
137
|
+
|
|
138
|
+
/* The paper an illustration is drawn on -- the white fill in an Open Peeps
|
|
139
|
+
figure, as opposed to the ink, which takes `currentColor`. Defaults to the
|
|
140
|
+
panel so a figure sits on its surface without being told.
|
|
141
|
+
It was a slot in every respect but the one that matters: used as
|
|
142
|
+
`var(--illo-paper, var(--panel))` and declared nowhere, so it rendered
|
|
143
|
+
correctly and no theme could fill it. A slot the vocabulary does not
|
|
144
|
+
contain is themeable only in appearance. */
|
|
145
|
+
--illo-paper: var(--panel);
|
|
146
|
+
|
|
147
|
+
/* The checkmark, once. Drawn as a mask so whatever wears it supplies its own
|
|
148
|
+
colour -- the choice row's tick and the select's are the same shape and
|
|
149
|
+
should not be two paths that drift. */
|
|
150
|
+
--tick-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m5 13 4 4 10-10' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
|
151
|
+
|
|
152
|
+
/* ---- density ------------------------------------------------------ */
|
|
153
|
+
/* One scale. `--density` multiplies the structural gaps — the grid, the
|
|
154
|
+
modals, the settings panes — so a theme can be roomy or tight without
|
|
155
|
+
restating every padding in the stylesheet. */
|
|
156
|
+
--density: 1;
|
|
157
|
+
|
|
158
|
+
/* One scale, in fours, for padding and margin and gap alike.
|
|
159
|
+
There were twenty-four distinct spacing values in `styles.css` -- every
|
|
160
|
+
integer from 1 to 16, then 18, 20, 22, 24, 26, 28, 40, 60 -- against
|
|
161
|
+
twenty-six uses of a token. That is not a rhythm, it is two hundred and
|
|
162
|
+
twenty-five separate decisions, and it is why two rows doing the same job
|
|
163
|
+
sat a pixel apart.
|
|
164
|
+
Fours because the app's smallest real gap is 4px and everything above it
|
|
165
|
+
was already trying to be a multiple of four and missing: 6 and 10 and 14
|
|
166
|
+
are what you write when there is no scale to reach for.
|
|
167
|
+
`--density` multiplies the structural steps, so a theme can be roomy or
|
|
168
|
+
tight without restating a single padding. */
|
|
169
|
+
--space-1: calc(4px * var(--density));
|
|
170
|
+
--space-2: calc(8px * var(--density));
|
|
171
|
+
--space-3: calc(12px * var(--density));
|
|
172
|
+
--space-4: calc(16px * var(--density));
|
|
173
|
+
--space-5: calc(20px * var(--density));
|
|
174
|
+
--space-6: calc(24px * var(--density));
|
|
175
|
+
--space-8: calc(32px * var(--density));
|
|
176
|
+
--space-10: calc(40px * var(--density));
|
|
177
|
+
--space-15: calc(60px * var(--density));
|
|
178
|
+
|
|
179
|
+
/* Below the scale, and deliberately outside it: a 1px or 2px offset is not
|
|
180
|
+
spacing, it is optical alignment -- nudging a glyph off a baseline, or a
|
|
181
|
+
mark off a cap height. Rounding those up to 4px would move things that were
|
|
182
|
+
placed by eye. */
|
|
183
|
+
--nudge: 2px;
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
/* ---- motion ------------------------------------------------------- */
|
|
187
|
+
/* Four durations existed, written four ways — `0.12s` and `120ms` were the
|
|
188
|
+
same value spelled differently. A theme sets the character here: calm at
|
|
189
|
+
320ms ease-out, or snappy at 90ms.
|
|
190
|
+
`--dur-drag` is read from JavaScript by the tile-reorder FLIP animation,
|
|
191
|
+
which is the one piece of motion CSS cannot reach. */
|
|
192
|
+
--dur-fast: 120ms;
|
|
193
|
+
--dur-md: 200ms;
|
|
194
|
+
--dur-slow: 300ms;
|
|
195
|
+
--dur-drag: 180ms;
|
|
196
|
+
--ease: cubic-bezier(0.2, 0, 0, 1);
|
|
197
|
+
--ease-out: ease-out;
|
|
198
|
+
/* A spring, sampled: stiffness 170, damping 26, no overshoot -- what a knob
|
|
199
|
+
does under a thumb rather than what a fade does. Written as `linear()` so
|
|
200
|
+
a consumer needs no animation engine, and the same curve `chef`'s design
|
|
201
|
+
system calls `spring/gentle`; it arrived here 2026-09-05 with the switch's
|
|
202
|
+
async state, so the knob's travel could be copied rather than approximated.
|
|
203
|
+
Played over `--dur-md`. A theme may replace it with any easing. */
|
|
204
|
+
--ease-spring: linear(0, 0.0315, 0.1058, 0.2003, 0.3012, 0.4, 0.4917, 0.5741, 0.6464, 0.7086, 0.7614, 0.8057, 0.8425, 0.8729, 0.8979, 0.9182, 0.9346, 0.9479, 0.9586, 0.9672, 0.9741, 0.9795, 0.9839, 0.9873, 1);
|
|
205
|
+
|
|
206
|
+
/* ---- interaction -------------------------------------------------- */
|
|
207
|
+
--hover-lift: 0px;
|
|
208
|
+
--hover-scale: 1;
|
|
209
|
+
/* Read by every `:active` rule in `styles.css` -- reserved since the
|
|
210
|
+
vocabulary was written, used since 2026-09-03. Small: a control that
|
|
211
|
+
visibly shrinks under the pointer reads as a toy. Reduced motion puts it
|
|
212
|
+
back to 1 below. */
|
|
213
|
+
--press-scale: 0.985;
|
|
214
|
+
/* How much darker a control goes while pressed: the share of `--text` mixed
|
|
215
|
+
into its hover colour. One number, so a button, a row and a tab press
|
|
216
|
+
the same amount. */
|
|
217
|
+
--press-ink: 9%;
|
|
218
|
+
/* The accent itself, not a pale tint of it. `--accent-dim` was 1.90:1 against
|
|
219
|
+
the panel, so the ring marking the focused control was fainter than the
|
|
220
|
+
control. */
|
|
221
|
+
--focus-ring: 0 0 0 2px var(--accent);
|
|
222
|
+
|
|
223
|
+
/* ---- fixed -------------------------------------------------------- */
|
|
224
|
+
/* Not themeable: geometry other things are measured against. The panel head
|
|
225
|
+
is pinned so a head without a cog — the studio's preview — is the same
|
|
226
|
+
height as one with, and the applet gets the same remainder in both. */
|
|
227
|
+
--tile-control: 34px;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/* Motion is an accessibility setting before it is a style, so this outranks
|
|
231
|
+
every theme. Declared here rather than in `styles.css` because it is part of
|
|
232
|
+
the vocabulary's contract: a theme may set the durations, it may not decide
|
|
233
|
+
whether they apply. */
|
|
234
|
+
/* `!important`, and it is the one place in the vocabulary that carries it.
|
|
235
|
+
A theme is applied as inline styles on the root, and an inline declaration
|
|
236
|
+
beats a stylesheet rule -- so a theme that set `--dur-md: 260ms` kept it
|
|
237
|
+
under `prefers-reduced-motion: reduce`, measured, and the three built-ins
|
|
238
|
+
only ever passed because none of them sets a duration. "Outranks every
|
|
239
|
+
theme" has to be true of a theme written by somebody who never read this
|
|
240
|
+
file, and the cascade is the only thing that can make it so. */
|
|
241
|
+
@media (prefers-reduced-motion: reduce) {
|
|
242
|
+
:root {
|
|
243
|
+
--dur-fast: 0s !important;
|
|
244
|
+
--dur-md: 0s !important;
|
|
245
|
+
--dur-slow: 0s !important;
|
|
246
|
+
--dur-drag: 0s !important;
|
|
247
|
+
--hover-lift: 0px !important;
|
|
248
|
+
--hover-scale: 1 !important;
|
|
249
|
+
--press-scale: 1 !important;
|
|
250
|
+
}
|
|
251
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wtfalch/design",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "The tf design system: themeable components on a fixed token vocabulary.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"design-system",
|
|
7
|
+
"react",
|
|
8
|
+
"react-aria",
|
|
9
|
+
"components",
|
|
10
|
+
"design-tokens",
|
|
11
|
+
"themes",
|
|
12
|
+
"css-variables",
|
|
13
|
+
"accessibility"
|
|
14
|
+
],
|
|
15
|
+
"author": "William Tallis Falch",
|
|
16
|
+
"homepage": "https://github.com/wtfalch/design#readme",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/wtfalch/design/issues"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/wtfalch/design",
|
|
23
|
+
"directory": "packages/design"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"type": "module",
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./dist/index.d.ts",
|
|
36
|
+
"default": "./dist/index.js"
|
|
37
|
+
},
|
|
38
|
+
"./themes": {
|
|
39
|
+
"types": "./dist/themes.d.ts",
|
|
40
|
+
"default": "./dist/themes.js"
|
|
41
|
+
},
|
|
42
|
+
"./tokens.css": "./dist/tokens.css",
|
|
43
|
+
"./styles.css": "./dist/styles/index.css"
|
|
44
|
+
},
|
|
45
|
+
"sideEffects": [
|
|
46
|
+
"*.css"
|
|
47
|
+
],
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=22.0.0"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"react": "^19.0.0",
|
|
53
|
+
"react-dom": "^19.0.0"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"dompurify": "^3.4.13",
|
|
57
|
+
"marked": "^18.0.9",
|
|
58
|
+
"react-aria-components": "^1.21.0"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@types/node": "^22",
|
|
62
|
+
"@types/react": "^19",
|
|
63
|
+
"@types/react-dom": "^19",
|
|
64
|
+
"react": "^19",
|
|
65
|
+
"react-dom": "^19",
|
|
66
|
+
"typescript": "^5.9.0",
|
|
67
|
+
"vitest": "^4.1.6"
|
|
68
|
+
},
|
|
69
|
+
"scripts": {
|
|
70
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json && node scripts/copy-css.mjs",
|
|
71
|
+
"typecheck": "tsc --noEmit",
|
|
72
|
+
"test": "vitest run"
|
|
73
|
+
}
|
|
74
|
+
}
|