@stealthscale/component-actions 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +306 -23
- package/dist/cyclonedx/bom.json +1 -1
- package/dist/index.d.ts +440 -53
- package/dist/index.js +983 -18
- package/dist/recipe-BhcK7PNL.js +317 -0
- package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
- package/dist/theme.d.ts +3 -4
- package/dist/theme.js +11 -6
- package/package.json +39 -24
- package/dist/recipe-19HSwhAG.js +0 -70
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { PALETTES, axis, below, controlSizes, defineRecipe, defineSlotRecipe, dense, interactive, liftVariants, lookVariants, motion, onSlot, onSlots, paletteVariants, sizeVariants, touchTarget } from "@stealthscale/theme/authoring";
|
|
2
|
+
//#region src/button/recipe.ts
|
|
3
|
+
/**
|
|
4
|
+
* Declares the button recipe: the base styles and the axes a caller sets.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Every value is a token, so a theme moves all of them. The border is transparent at the control
|
|
8
|
+
* width in every look, so the outline look is the same size as the others. A press changes the
|
|
9
|
+
* fill, spreads the ripple and lowers the elevation, and never moves the box, because a target
|
|
10
|
+
* that shifts under the pointer is easy to miss. `staticCss` lists `shape="square"` and every
|
|
11
|
+
* palette. The icon button sets the shape through a default prop, and callers set the palette
|
|
12
|
+
* through a provider or from data, so the compiler extracts neither from source.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Returns the fill of a button that is on under forced colors: `Highlight` behind `HighlightText`.
|
|
16
|
+
*
|
|
17
|
+
* @remarks
|
|
18
|
+
* Forced colors replace every background and remove every shadow, so without it a button that is
|
|
19
|
+
* on reads the same as one that is off.
|
|
20
|
+
*/
|
|
21
|
+
function forcedOn() {
|
|
22
|
+
return { _highContrast: {
|
|
23
|
+
background: "Highlight",
|
|
24
|
+
color: "HighlightText",
|
|
25
|
+
forcedColorAdjust: "none"
|
|
26
|
+
} };
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Returns the `_currentPage` and `_pressed` styles of a look with no fill of its own.
|
|
30
|
+
*
|
|
31
|
+
* @remarks
|
|
32
|
+
* A button is on when it has `aria-pressed="true"` or `aria-current="page"`, so the fill matches
|
|
33
|
+
* what a screen reader announces. The styles go in a compound variant, not the base, because the
|
|
34
|
+
* compiler emits a look's background in a later cascade layer than the base, and a later layer
|
|
35
|
+
* applies over an earlier one at any specificity. Pass `colorPalette.subtle` for a look with no
|
|
36
|
+
* resting fill and `colorPalette.muted` for a look that rests on the subtle fill, so the on state
|
|
37
|
+
* is one step deeper in both. A pressed button's edge is the palette's emphasized role, one step
|
|
38
|
+
* darker than the outline look's muted edge.
|
|
39
|
+
*/
|
|
40
|
+
function on(background) {
|
|
41
|
+
return {
|
|
42
|
+
_currentPage: {
|
|
43
|
+
background,
|
|
44
|
+
color: "colorPalette.fg",
|
|
45
|
+
fontWeight: "semibold",
|
|
46
|
+
...forcedOn()
|
|
47
|
+
},
|
|
48
|
+
_pressed: {
|
|
49
|
+
background,
|
|
50
|
+
borderColor: "colorPalette.emphasized",
|
|
51
|
+
color: "colorPalette.fg",
|
|
52
|
+
...forcedOn()
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Returns the `_currentPage` and `_pressed` styles of the solid look.
|
|
58
|
+
*
|
|
59
|
+
* @remarks
|
|
60
|
+
* The solid look has no deeper fill, and any other fill matches its hover fill. The on state is
|
|
61
|
+
* the theme's inset line and the semibold weight. `:active` is the momentary press.
|
|
62
|
+
*/
|
|
63
|
+
function marked() {
|
|
64
|
+
return {
|
|
65
|
+
_currentPage: {
|
|
66
|
+
boxShadow: "inset",
|
|
67
|
+
fontWeight: "semibold",
|
|
68
|
+
...forcedOn()
|
|
69
|
+
},
|
|
70
|
+
_pressed: {
|
|
71
|
+
boxShadow: "inset",
|
|
72
|
+
fontWeight: "semibold",
|
|
73
|
+
...forcedOn()
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Styles a button, defaulting to the solid look at the md size in the primary palette.
|
|
79
|
+
*/
|
|
80
|
+
const recipe$2 = defineRecipe({
|
|
81
|
+
base: {
|
|
82
|
+
...interactive(),
|
|
83
|
+
...touchTarget(),
|
|
84
|
+
layerStyle: "ripple",
|
|
85
|
+
alignItems: "center",
|
|
86
|
+
appearance: "none",
|
|
87
|
+
borderColor: "transparent",
|
|
88
|
+
borderRadius: "l2",
|
|
89
|
+
borderWidth: "control",
|
|
90
|
+
colorPalette: "primary",
|
|
91
|
+
display: "inline-flex",
|
|
92
|
+
flexShrink: "0",
|
|
93
|
+
fontWeight: "medium",
|
|
94
|
+
justifyContent: "center",
|
|
95
|
+
verticalAlign: "middle",
|
|
96
|
+
whiteSpace: "nowrap"
|
|
97
|
+
},
|
|
98
|
+
className: "button",
|
|
99
|
+
compoundVariants: [
|
|
100
|
+
(
|
|
101
|
+
/**
|
|
102
|
+
* Zeroes the inline padding of a square button.
|
|
103
|
+
*
|
|
104
|
+
* @remarks
|
|
105
|
+
* The compiler emits the size axis after the shape axis, and the size axis sets the padding,
|
|
106
|
+
* so the reset is a compound. `aspect-ratio` fixes the width, so padding only narrows the
|
|
107
|
+
* content box: at md, 16px each side leaves 6px for a 16px icon.
|
|
108
|
+
*/
|
|
109
|
+
{
|
|
110
|
+
css: { paddingInline: "0" },
|
|
111
|
+
name: "squared",
|
|
112
|
+
shape: "square"
|
|
113
|
+
}),
|
|
114
|
+
{
|
|
115
|
+
css: on("colorPalette.subtle"),
|
|
116
|
+
name: "on",
|
|
117
|
+
variant: [
|
|
118
|
+
"ghost",
|
|
119
|
+
"glass",
|
|
120
|
+
"outline",
|
|
121
|
+
"plain"
|
|
122
|
+
]
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
css: on("colorPalette.muted"),
|
|
126
|
+
name: "on-deeper",
|
|
127
|
+
variant: ["subtle", "surface"]
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
css: marked(),
|
|
131
|
+
name: "on-marked",
|
|
132
|
+
variant: ["solid"]
|
|
133
|
+
}
|
|
134
|
+
],
|
|
135
|
+
defaultVariants: {
|
|
136
|
+
size: "md",
|
|
137
|
+
variant: "solid"
|
|
138
|
+
},
|
|
139
|
+
jsx: [/Button$/u],
|
|
140
|
+
staticCss: [{ shape: ["square"] }, { palette: [...PALETTES] }],
|
|
141
|
+
variants: {
|
|
142
|
+
/**
|
|
143
|
+
* The halo around the button, in the palette's solid at half opacity.
|
|
144
|
+
*
|
|
145
|
+
* @remarks
|
|
146
|
+
* `pulse` sets `boxShadowColor` because its keyframe writes the whole `box-shadow`, which
|
|
147
|
+
* replaces a static glow. The axis offers no moving border. `border.moving` paints over the
|
|
148
|
+
* padding box and hides the look's fill, and a ring without it needs a pseudo-element, but
|
|
149
|
+
* `::after` renders the ripple and `::before` the touch target.
|
|
150
|
+
*/
|
|
151
|
+
effect: {
|
|
152
|
+
glow: { layerStyle: "glow.md" },
|
|
153
|
+
pulse: {
|
|
154
|
+
animationStyle: "pulse-glow",
|
|
155
|
+
boxShadowColor: "colorPalette.solid/50"
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
elevation: liftVariants(),
|
|
159
|
+
/**
|
|
160
|
+
* Palette of every look. The base sets `primary`.
|
|
161
|
+
*
|
|
162
|
+
* @remarks
|
|
163
|
+
* `neutral` renders the control in the surrounding text ink, for a button in a toolbar.
|
|
164
|
+
*/
|
|
165
|
+
palette: paletteVariants(),
|
|
166
|
+
shape: { square: { aspectRatio: "square" } },
|
|
167
|
+
size: controlSizes(),
|
|
168
|
+
variant: {
|
|
169
|
+
...lookVariants(),
|
|
170
|
+
glass: { layerStyle: "glass" }
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
//#endregion
|
|
175
|
+
//#region src/clipboard/recipe.ts
|
|
176
|
+
/**
|
|
177
|
+
* Declares the slot recipe of the clipboard: layout and spacing for its seven parts.
|
|
178
|
+
*
|
|
179
|
+
* @remarks
|
|
180
|
+
* The trigger has no control styles. A caller renders it as the library's `Button` or
|
|
181
|
+
* `IconButton` through `as`, so it matches every other button in a theme. The clipboard has no
|
|
182
|
+
* colour or surface of its own, so it offers no `palette` or `effect` axis. The button it renders
|
|
183
|
+
* through `as` carries both. The root aligns its children at the start, so a trigger on its own
|
|
184
|
+
* keeps its button width. The control row stretches to the width of the root, so a field inside
|
|
185
|
+
* it fills the row.
|
|
186
|
+
*/
|
|
187
|
+
/**
|
|
188
|
+
* Sizes the label text and the gaps step through.
|
|
189
|
+
*/
|
|
190
|
+
const STEPS = [
|
|
191
|
+
"sm",
|
|
192
|
+
"md",
|
|
193
|
+
"lg"
|
|
194
|
+
];
|
|
195
|
+
/**
|
|
196
|
+
* Slot styles and the size axis. Defaults to `md`.
|
|
197
|
+
*/
|
|
198
|
+
const recipe$1 = defineSlotRecipe({
|
|
199
|
+
base: {
|
|
200
|
+
control: {
|
|
201
|
+
alignItems: "center",
|
|
202
|
+
alignSelf: "stretch",
|
|
203
|
+
display: "flex"
|
|
204
|
+
},
|
|
205
|
+
indicator: {
|
|
206
|
+
alignItems: "center",
|
|
207
|
+
display: "inline-flex",
|
|
208
|
+
flexShrink: "0",
|
|
209
|
+
justifyContent: "center"
|
|
210
|
+
},
|
|
211
|
+
label: {
|
|
212
|
+
color: "fg",
|
|
213
|
+
display: "block"
|
|
214
|
+
},
|
|
215
|
+
root: {
|
|
216
|
+
alignItems: "start",
|
|
217
|
+
display: "flex",
|
|
218
|
+
flexDirection: "column"
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
className: "clipboard",
|
|
222
|
+
defaultVariants: { size: "md" },
|
|
223
|
+
jsx: [/^Clipboard(\.\w+)?$/u],
|
|
224
|
+
slots: [
|
|
225
|
+
"root",
|
|
226
|
+
"label",
|
|
227
|
+
"control",
|
|
228
|
+
"input",
|
|
229
|
+
"trigger",
|
|
230
|
+
"indicator",
|
|
231
|
+
"valueText"
|
|
232
|
+
],
|
|
233
|
+
variants: {
|
|
234
|
+
/**
|
|
235
|
+
* The label text style and the two gaps.
|
|
236
|
+
*
|
|
237
|
+
* @remarks
|
|
238
|
+
* The gap between the label and the row is one size smaller than the gap between the field
|
|
239
|
+
* and the trigger. The field and the trigger take their own size through their providers.
|
|
240
|
+
*/
|
|
241
|
+
size: onSlots({
|
|
242
|
+
control: sizeVariants((size) => ({ gap: dense(`{spacing.gap.${size}}`) }), STEPS),
|
|
243
|
+
label: sizeVariants((size) => ({ textStyle: `label.${size}` }), STEPS),
|
|
244
|
+
root: sizeVariants((size) => ({ gap: dense(`{spacing.gap.${below(size)}}`) }), STEPS)
|
|
245
|
+
}) }
|
|
246
|
+
});
|
|
247
|
+
//#endregion
|
|
248
|
+
//#region src/swap/recipe.ts
|
|
249
|
+
/**
|
|
250
|
+
* Recipe for a swap: two marks in one place, one of which shows, and the motion that replaces one
|
|
251
|
+
* with the other.
|
|
252
|
+
*
|
|
253
|
+
* @remarks
|
|
254
|
+
* The root is an inline grid and both indicators take its one cell, so the root is as large as
|
|
255
|
+
* the larger mark whichever shows, and nothing beside it moves. An indicator with `data-hidden`
|
|
256
|
+
* keeps its room with `visibility: hidden`, which also takes it out of the accessibility tree and
|
|
257
|
+
* the tab order. The `motion` axis
|
|
258
|
+
* picks the pair of animation styles an indicator enters and leaves with, and the leaving mark
|
|
259
|
+
* and the entering mark run at once. Under reduced motion the animation styles run nothing, so
|
|
260
|
+
* the marks change at once. The recipe has no `palette` and no `size` axis: the marks take their
|
|
261
|
+
* color and their size from the control around them.
|
|
262
|
+
*/
|
|
263
|
+
/**
|
|
264
|
+
* Class name of the recipe.
|
|
265
|
+
*/
|
|
266
|
+
const CLASS = "swap";
|
|
267
|
+
/**
|
|
268
|
+
* Lists the motions in reading order: the default first, then the others, then none.
|
|
269
|
+
*/
|
|
270
|
+
const MOTIONS = [
|
|
271
|
+
"scale",
|
|
272
|
+
"fade",
|
|
273
|
+
"slide",
|
|
274
|
+
"none"
|
|
275
|
+
];
|
|
276
|
+
/**
|
|
277
|
+
* Maps each motion to the animation styles an indicator enters and leaves with, or to no animation.
|
|
278
|
+
* The scale runs from half a mark's size, so a small icon visibly grows into place.
|
|
279
|
+
*/
|
|
280
|
+
const PAIRS = {
|
|
281
|
+
fade: motion("fade.in", "fade.out"),
|
|
282
|
+
none: { animation: "none" },
|
|
283
|
+
scale: {
|
|
284
|
+
...motion("scale-fade.in", "scale-fade.out"),
|
|
285
|
+
"--scale-distance": "0.5"
|
|
286
|
+
},
|
|
287
|
+
slide: motion("slide-up.in", "slide-up.out")
|
|
288
|
+
};
|
|
289
|
+
/**
|
|
290
|
+
* Defines the swap recipe, which scales the marks in and out by default.
|
|
291
|
+
*/
|
|
292
|
+
const recipe = defineSlotRecipe({
|
|
293
|
+
base: {
|
|
294
|
+
indicator: {
|
|
295
|
+
"&[data-hidden]": { visibility: "hidden" },
|
|
296
|
+
alignItems: "center",
|
|
297
|
+
display: "inline-flex",
|
|
298
|
+
gridArea: "1 / 1 / 2 / 2",
|
|
299
|
+
justifyContent: "center"
|
|
300
|
+
},
|
|
301
|
+
root: {
|
|
302
|
+
display: "inline-grid",
|
|
303
|
+
placeItems: "center"
|
|
304
|
+
}
|
|
305
|
+
},
|
|
306
|
+
className: CLASS,
|
|
307
|
+
defaultVariants: { motion: "scale" },
|
|
308
|
+
jsx: [/^Swap(\.\w+)?$/u],
|
|
309
|
+
slots: ["root", "indicator"],
|
|
310
|
+
variants: {
|
|
311
|
+
/**
|
|
312
|
+
* Motion the marks replace each other with.
|
|
313
|
+
*/
|
|
314
|
+
motion: onSlot("indicator", axis(MOTIONS, (name) => PAIRS[name])()) }
|
|
315
|
+
});
|
|
316
|
+
//#endregion
|
|
317
|
+
export { recipe$1 as n, recipe$2 as r, recipe as t };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __exportAll = (all, no_symbols) => {
|
|
4
|
+
let target = {};
|
|
5
|
+
for (var name in all) __defProp(target, name, {
|
|
6
|
+
get: all[name],
|
|
7
|
+
enumerable: true
|
|
8
|
+
});
|
|
9
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
10
|
+
return target;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { __exportAll as t };
|
package/dist/theme.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
//#region src/theme.d.ts
|
|
2
2
|
/**
|
|
3
|
-
* Publishes the preset
|
|
4
|
-
* to install.
|
|
3
|
+
* Publishes the preset an application's style compiler installs to pick up this package's recipes.
|
|
5
4
|
*
|
|
6
5
|
* @remarks
|
|
7
|
-
* The list is
|
|
8
|
-
*
|
|
6
|
+
* The list of recipes is maintained by hand. The package's own specification fails when a recipe
|
|
7
|
+
* file is missing from it, which is why nothing generates the list.
|
|
9
8
|
*/
|
|
10
9
|
declare const _default: import("@stealthscale/theme/authoring").Preset;
|
|
11
10
|
//#endregion
|
package/dist/theme.js
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
import { t as recipe } from "./recipe-
|
|
1
|
+
import { n as recipe$1, r as recipe, t as recipe$2 } from "./recipe-BhcK7PNL.js";
|
|
2
2
|
import { definePreset } from "@stealthscale/theme/authoring";
|
|
3
3
|
//#region src/theme.ts
|
|
4
4
|
/**
|
|
5
|
-
* Publishes the preset
|
|
6
|
-
* to install.
|
|
5
|
+
* Publishes the preset an application's style compiler installs to pick up this package's recipes.
|
|
7
6
|
*
|
|
8
7
|
* @remarks
|
|
9
|
-
* The list is
|
|
10
|
-
*
|
|
8
|
+
* The list of recipes is maintained by hand. The package's own specification fails when a recipe
|
|
9
|
+
* file is missing from it, which is why nothing generates the list.
|
|
11
10
|
*/
|
|
12
11
|
var theme_default = definePreset({
|
|
13
12
|
name: "@stealthscale/component-actions",
|
|
14
|
-
theme: { extend: {
|
|
13
|
+
theme: { extend: {
|
|
14
|
+
recipes: { button: recipe },
|
|
15
|
+
slotRecipes: {
|
|
16
|
+
clipboard: recipe$1,
|
|
17
|
+
swap: recipe$2
|
|
18
|
+
}
|
|
19
|
+
} }
|
|
15
20
|
});
|
|
16
21
|
//#endregion
|
|
17
22
|
export { theme_default as default };
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stealthscale/component-actions",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Renders what a person presses: a button, a toggle group, a swap, a color mode toggle, a clipboard and a download trigger.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"actions",
|
|
7
7
|
"button",
|
|
8
8
|
"components",
|
|
9
9
|
"react"
|
|
10
10
|
],
|
|
11
|
-
"homepage": "https://github.com/stealth-scale/
|
|
12
|
-
"bugs": "https://github.com/stealth-scale/
|
|
11
|
+
"homepage": "https://github.com/stealth-scale/scale/tree/main/components/actions#readme",
|
|
12
|
+
"bugs": "https://github.com/stealth-scale/scale/issues",
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"repository": {
|
|
15
15
|
"type": "git",
|
|
16
|
-
"url": "git+https://github.com/stealth-scale/
|
|
16
|
+
"url": "git+https://github.com/stealth-scale/scale.git",
|
|
17
17
|
"directory": "components/actions"
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
@@ -34,29 +34,44 @@
|
|
|
34
34
|
"publishConfig": {
|
|
35
35
|
"access": "public"
|
|
36
36
|
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@stealthscale/component-layout": "^0.2.1",
|
|
39
|
+
"@zag-js/clipboard": "1.45.0",
|
|
40
|
+
"@zag-js/file-utils": "1.45.0",
|
|
41
|
+
"@zag-js/react": "1.45.0",
|
|
42
|
+
"@zag-js/toggle-group": "1.45.0",
|
|
43
|
+
"@zag-js/types": "1.45.0",
|
|
44
|
+
"@zag-js/utils": "1.45.0"
|
|
45
|
+
},
|
|
37
46
|
"devDependencies": {
|
|
38
|
-
"@arethetypeswrong/core": "^0.18
|
|
39
|
-
"@
|
|
40
|
-
"@stealthscale/
|
|
41
|
-
"@stealthscale/
|
|
42
|
-
"@stealthscale/
|
|
43
|
-
"@stealthscale/vite-config
|
|
47
|
+
"@arethetypeswrong/core": "^0.18",
|
|
48
|
+
"@stealthscale/hooks": "^0.3.0",
|
|
49
|
+
"@stealthscale/provider-color-mode": "^0.2.2",
|
|
50
|
+
"@stealthscale/settings": "^0.2.0",
|
|
51
|
+
"@stealthscale/theme": "^0.5.0",
|
|
52
|
+
"@stealthscale/vite-config": "^0.8.0",
|
|
53
|
+
"@stealthscale/vite-config-i18n": "^0.2.1",
|
|
54
|
+
"@stealthscale/vite-config-react": "^0.9.1",
|
|
55
|
+
"@stealthscale/vite-config-specimen": "^0.2.1",
|
|
56
|
+
"@stealthscale/vite-config-theme": "^0.2.1",
|
|
44
57
|
"@stealthscale/vite-config-typescript": "^0.3.0",
|
|
45
|
-
"@testing-library/react": "^16.3
|
|
46
|
-
"@types/react": "^19.3
|
|
47
|
-
"@types/react-dom": "^19.3
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"oxc-transform-react": "^0.
|
|
51
|
-
"publint": "^0.3
|
|
52
|
-
"react": "^19.3
|
|
53
|
-
"react-dom": "^19.3
|
|
54
|
-
"typescript": "^7.0
|
|
55
|
-
"vitest": "
|
|
58
|
+
"@testing-library/react": "^16.3",
|
|
59
|
+
"@types/react": "^19.3",
|
|
60
|
+
"@types/react-dom": "^19.3",
|
|
61
|
+
"happy-dom": "^20.14",
|
|
62
|
+
"lucide-react": "^1.52",
|
|
63
|
+
"oxc-transform-react": "^0.153",
|
|
64
|
+
"publint": "^0.3",
|
|
65
|
+
"react": "^19.3",
|
|
66
|
+
"react-dom": "^19.3",
|
|
67
|
+
"typescript": "^7.0",
|
|
68
|
+
"vitest": "5.0.3"
|
|
56
69
|
},
|
|
57
70
|
"peerDependencies": {
|
|
58
|
-
"@stealthscale/
|
|
59
|
-
"
|
|
71
|
+
"@stealthscale/hooks": "^0.3.0",
|
|
72
|
+
"@stealthscale/provider-color-mode": "^0.2.2",
|
|
73
|
+
"@stealthscale/theme": "^0.5.0",
|
|
74
|
+
"react": "^19.3"
|
|
60
75
|
},
|
|
61
76
|
"engines": {
|
|
62
77
|
"node": ">=26.0.0"
|
package/dist/recipe-19HSwhAG.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { controlSizes, defineRecipe, interactive, liftVariants, lookVariants, statusVariants, touchTarget } from "@stealthscale/theme/authoring";
|
|
2
|
-
//#region src/button/recipe.ts
|
|
3
|
-
/**
|
|
4
|
-
* States what a button is: the element a person presses, drawn in a look and a size, in the
|
|
5
|
-
* palette of its status, square where it holds one glyph, and glowing where a page asks.
|
|
6
|
-
*
|
|
7
|
-
* @remarks
|
|
8
|
-
* Every value is a layer style, a semantic control height, a semantic inset, a label role or a
|
|
9
|
-
* palette, so a theme moves all of them. The interactive fragment gives the cursor, the focus
|
|
10
|
-
* ring, the disabled layer and the transitions every control shares, and the touch target widens
|
|
11
|
-
* the hit area on a coarse pointer without moving the box. The border is drawn transparent at the
|
|
12
|
-
* small width in every look, so the outline look changes its colour and not its size. A press is
|
|
13
|
-
* read from the look's own pressed fill and from the elevation dropping under the pointer. The
|
|
14
|
-
* box scales rather than shifting, because a control that shifts under a press is one a reader
|
|
15
|
-
* can miss. The square is listed under `staticCss`, because the icon button fixes it through a
|
|
16
|
-
* default prop and no JSX literal writes it for the compiler to extract.
|
|
17
|
-
*/
|
|
18
|
-
/**
|
|
19
|
-
* Draws a button on the primary palette in the solid look and the middle size until a caller says
|
|
20
|
-
* otherwise, set inline so it sits in a line of controls.
|
|
21
|
-
*/
|
|
22
|
-
const recipe = defineRecipe({
|
|
23
|
-
base: {
|
|
24
|
-
...interactive(),
|
|
25
|
-
...touchTarget(),
|
|
26
|
-
alignItems: "center",
|
|
27
|
-
appearance: "none",
|
|
28
|
-
borderColor: "transparent",
|
|
29
|
-
borderRadius: "l2",
|
|
30
|
-
borderWidth: "sm",
|
|
31
|
-
colorPalette: "primary",
|
|
32
|
-
display: "inline-flex",
|
|
33
|
-
flexShrink: "0",
|
|
34
|
-
fontWeight: "medium",
|
|
35
|
-
justifyContent: "center",
|
|
36
|
-
verticalAlign: "middle",
|
|
37
|
-
whiteSpace: "nowrap"
|
|
38
|
-
},
|
|
39
|
-
className: "button",
|
|
40
|
-
compoundVariants: [{
|
|
41
|
-
css: { "&:has(> svg:first-child)": { paddingInline: "0" } },
|
|
42
|
-
name: "squared",
|
|
43
|
-
shape: "square"
|
|
44
|
-
}],
|
|
45
|
-
defaultVariants: {
|
|
46
|
-
size: "md",
|
|
47
|
-
variant: "solid"
|
|
48
|
-
},
|
|
49
|
-
jsx: [/Button$/u],
|
|
50
|
-
staticCss: [{ shape: ["square"] }],
|
|
51
|
-
variants: {
|
|
52
|
-
effect: {
|
|
53
|
-
glow: { layerStyle: "glow.md" },
|
|
54
|
-
ripple: { layerStyle: "ripple" }
|
|
55
|
-
},
|
|
56
|
-
elevation: liftVariants(),
|
|
57
|
-
shape: { square: {
|
|
58
|
-
aspectRatio: "square",
|
|
59
|
-
paddingInline: "0"
|
|
60
|
-
} },
|
|
61
|
-
size: controlSizes(),
|
|
62
|
-
status: statusVariants(),
|
|
63
|
-
variant: {
|
|
64
|
-
...lookVariants(),
|
|
65
|
-
glass: { layerStyle: "glass" }
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
//#endregion
|
|
70
|
-
export { recipe as t };
|