@ambientcss/components 2.0.1 → 3.0.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/README.md +35 -0
- package/dist/index.cjs +1563 -384
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +763 -48
- package/dist/index.d.ts +763 -48
- package/dist/index.js +1524 -385
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1102 -256
- package/package.json +2 -2
- package/src/components/AmbientButton.tsx +25 -25
- package/src/components/AmbientFader.tsx +33 -115
- package/src/components/AmbientKnob.tsx +64 -222
- package/src/components/AmbientPanel.tsx +8 -2
- package/src/components/AmbientProvider.tsx +3 -0
- package/src/components/AmbientRack.tsx +32 -0
- package/src/components/AmbientSelect.tsx +40 -0
- package/src/components/AmbientSlider.tsx +32 -113
- package/src/components/AmbientSwitch.tsx +58 -58
- package/src/controls/AmbientBank.tsx +138 -0
- package/src/controls/AmbientLatch.tsx +78 -0
- package/src/controls/AmbientPress.tsx +74 -0
- package/src/controls/AmbientRotary.tsx +94 -0
- package/src/controls/AmbientTravel.tsx +83 -0
- package/src/core/context.tsx +46 -0
- package/src/core/controllable.ts +33 -0
- package/src/core/dev.ts +15 -0
- package/src/core/frames.tsx +63 -0
- package/src/core/kit.tsx +107 -0
- package/src/core/material.ts +27 -0
- package/src/core/numeric.ts +88 -0
- package/src/core/types.ts +116 -0
- package/src/core/useBank.ts +163 -0
- package/src/core/useLatch.ts +54 -0
- package/src/core/usePress.ts +120 -0
- package/src/core/useRotary.ts +253 -0
- package/src/core/useTravel.ts +141 -0
- package/src/index.ts +127 -4
- package/src/kits/console.tsx +80 -0
- package/src/kits/grounded.tsx +113 -0
- package/src/parts/bank.tsx +32 -0
- package/src/parts/console.tsx +99 -0
- package/src/parts/knob.tsx +203 -0
- package/src/parts/latch.tsx +33 -0
- package/src/parts/press.tsx +56 -0
- package/src/parts/travel.tsx +70 -0
- package/src/styles.css +1102 -256
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { PropsWithChildren, CSSProperties, HTMLAttributes, ReactNode, PointerEvent, ButtonHTMLAttributes, KeyboardEvent } from 'react';
|
|
3
4
|
|
|
4
5
|
type AmbientTheme = {
|
|
5
6
|
lightX?: number;
|
|
@@ -18,63 +19,777 @@ type AmbientProviderProps = PropsWithChildren<{
|
|
|
18
19
|
}>;
|
|
19
20
|
declare function AmbientProvider({ children, className, style, theme }: AmbientProviderProps): react_jsx_runtime.JSX.Element;
|
|
20
21
|
|
|
22
|
+
/** The grounded surface finishes from @ambientcss/css.
|
|
23
|
+
*
|
|
24
|
+
* Lives on parts and presets, never on a mechanism: which element a
|
|
25
|
+
* material belongs on is a fact about a particular control's construction,
|
|
26
|
+
* and a mechanism cannot know that once the parts are yours.
|
|
27
|
+
*
|
|
28
|
+
* `brushed`, `brushed-round` and `blasted` are micro-relief materials: they
|
|
29
|
+
* paint their grain into BOTH of the host's pseudo-elements, so a part that
|
|
30
|
+
* already spends one of its own has to give them an inner layer rather than
|
|
31
|
+
* wear them directly. `ButtonCap` is the only part in this package that does.
|
|
32
|
+
*
|
|
33
|
+
* `brushed-round` is the same aluminium as `brushed` with the grain spun
|
|
34
|
+
* round the element's centre, so it belongs on round faces — a knob cap, a
|
|
35
|
+
* round button — where the centre it turns about is a real feature. */
|
|
36
|
+
type AmbientMaterial = "matte" | "shiny" | "glass" | "brushed" | "brushed-round" | "blasted";
|
|
37
|
+
|
|
21
38
|
interface AmbientPanelProps extends HTMLAttributes<HTMLDivElement> {
|
|
22
|
-
material?:
|
|
39
|
+
material?: AmbientMaterial;
|
|
23
40
|
}
|
|
41
|
+
/** A panel is a plain surface, so it can wear any finish directly: it spends
|
|
42
|
+
* neither pseudo-element of its own, which is what the two micro-relief
|
|
43
|
+
* materials need. Their grain paints below the panel's children, and their
|
|
44
|
+
* `overflow: hidden` clips whatever hangs outside it — a control's drop
|
|
45
|
+
* shadow at the very edge included. */
|
|
24
46
|
declare function AmbientPanel({ className, material, ...props }: AmbientPanelProps): react_jsx_runtime.JSX.Element;
|
|
25
47
|
|
|
26
|
-
type
|
|
27
|
-
interface
|
|
28
|
-
|
|
29
|
-
|
|
48
|
+
type AmbientRackGap = "tight" | "normal" | "loose";
|
|
49
|
+
interface AmbientRackProps extends HTMLAttributes<HTMLDivElement> {
|
|
50
|
+
/** Clearance between controls: tight for one functional unit/repeated
|
|
51
|
+
* row, normal (default) for a few related controls, loose for
|
|
52
|
+
* separating distinct zones. */
|
|
53
|
+
gap?: AmbientRackGap;
|
|
54
|
+
direction?: "row" | "column";
|
|
30
55
|
}
|
|
31
|
-
declare function
|
|
56
|
+
declare function AmbientRack({ className, gap, direction, ...props }: AmbientRackProps): react_jsx_runtime.JSX.Element;
|
|
32
57
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
58
|
+
/** The four frames every control renders, in paint order.
|
|
59
|
+
*
|
|
60
|
+
* - `panel` static, behind the control, allowed to overflow its box
|
|
61
|
+
* - `base` static, the control's own footprint
|
|
62
|
+
* - `actuator` the moving part: the frame the control transforms
|
|
63
|
+
* - `fixture` static, above the actuator
|
|
64
|
+
*
|
|
65
|
+
* A part dropped into a frame is ordinary markup. The control moves the
|
|
66
|
+
* frame; the part only has to look like something. */
|
|
67
|
+
type ControlParts = {
|
|
68
|
+
panel?: ReactNode | undefined;
|
|
69
|
+
base?: ReactNode | undefined;
|
|
70
|
+
actuator?: ReactNode | undefined;
|
|
71
|
+
fixture?: ReactNode | undefined;
|
|
72
|
+
};
|
|
73
|
+
type FrameName = keyof ControlParts;
|
|
74
|
+
/** `"sm" | "md" | "lg"` picks a size from the family's table; any other
|
|
75
|
+
* string is used as a CSS length for `--ambx-size`. */
|
|
76
|
+
type ControlSize = "sm" | "md" | "lg" | (string & {});
|
|
77
|
+
/** How the actuator moves to a new position.
|
|
78
|
+
*
|
|
79
|
+
* - `follow` 1:1 with the pointer, no transition — right while dragging
|
|
80
|
+
* - `ease` transitions, right for keyboard and click-to-set
|
|
81
|
+
* - `snap` instant, for a detented control that should read as clicking
|
|
82
|
+
*
|
|
83
|
+
* The default is contextual: follow while `data-dragging` is on the root,
|
|
84
|
+
* ease otherwise. That needs no JS — see `.ambx-control` in styles.css. */
|
|
85
|
+
type ControlAnimate = "auto" | "follow" | "ease" | "snap";
|
|
86
|
+
/** What a part can read, via `useControlState()`. The same values are on
|
|
87
|
+
* the control root as custom properties, which are canonical; this is a
|
|
88
|
+
* typed view of them for parts that genuinely need JS. */
|
|
89
|
+
type ControlState = {
|
|
90
|
+
/** The raw value. Booleans arrive as 0/1, selections as the index. */
|
|
47
91
|
value: number;
|
|
48
|
-
min
|
|
49
|
-
max
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
92
|
+
min: number;
|
|
93
|
+
max: number;
|
|
94
|
+
/** Normalised position, 0-1. */
|
|
95
|
+
percent: number;
|
|
96
|
+
/** Degrees clockwise from 12 o'clock. 0 for non-rotary controls. */
|
|
97
|
+
angle: number;
|
|
98
|
+
/** Sweep origin and extent in degrees. 0 for non-rotary controls. */
|
|
99
|
+
travelStart: number;
|
|
100
|
+
travelSweep: number;
|
|
101
|
+
/** Rest positions along the travel; 0 means continuous. */
|
|
102
|
+
detents: number;
|
|
103
|
+
dragging: boolean;
|
|
104
|
+
disabled: boolean;
|
|
105
|
+
atMin: boolean;
|
|
106
|
+
atMax: boolean;
|
|
55
107
|
};
|
|
56
|
-
declare function AmbientKnob({ value, min, max, step, label, material, variant, onChange, className, ...props }: AmbientKnobProps): react_jsx_runtime.JSX.Element;
|
|
57
108
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
109
|
+
/** A transport key, a latching mute and an auto-repeating nudge button are
|
|
110
|
+
* the same object with three state machines and identical paint. */
|
|
111
|
+
type PressMode = "momentary" | "toggle" | "repeat";
|
|
112
|
+
type UsePressOptions = {
|
|
113
|
+
mode?: PressMode | undefined;
|
|
114
|
+
/** `toggle` mode only: the pressed-in state. */
|
|
115
|
+
value?: boolean | undefined;
|
|
116
|
+
defaultValue?: boolean | undefined;
|
|
117
|
+
onChange?: ((next: boolean) => void) | undefined;
|
|
118
|
+
/** Fires once per activation, and repeatedly in `repeat` mode. */
|
|
119
|
+
onPress?: (() => void) | undefined;
|
|
120
|
+
/** `repeat` mode: delay before repeating starts, then its interval. */
|
|
121
|
+
repeatDelay?: number | undefined;
|
|
122
|
+
repeatInterval?: number | undefined;
|
|
123
|
+
disabled?: boolean | undefined;
|
|
124
|
+
};
|
|
125
|
+
declare function usePress(options: UsePressOptions): {
|
|
126
|
+
state: ControlState;
|
|
127
|
+
rootProps: {
|
|
128
|
+
onPointerDown: (event: PointerEvent<HTMLButtonElement>) => void;
|
|
129
|
+
onPointerUp: () => void;
|
|
130
|
+
onPointerCancel: () => void;
|
|
131
|
+
onPointerLeave: () => void;
|
|
132
|
+
onClick: () => void;
|
|
133
|
+
type: "button";
|
|
134
|
+
disabled: boolean;
|
|
135
|
+
"aria-pressed": boolean | undefined;
|
|
136
|
+
style: CSSProperties;
|
|
137
|
+
"data-pressed": string | undefined;
|
|
138
|
+
"data-mode": PressMode;
|
|
139
|
+
};
|
|
140
|
+
pressed: boolean;
|
|
141
|
+
on: boolean;
|
|
142
|
+
setOn: (next: boolean) => void;
|
|
66
143
|
};
|
|
67
|
-
declare function AmbientFader({ value, min, max, step, label, material, onChange, className, ...props }: AmbientFaderProps): react_jsx_runtime.JSX.Element;
|
|
68
144
|
|
|
69
|
-
type
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
145
|
+
type AmbientPressProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, "onChange" | "value" | "defaultValue" | "type"> & UsePressOptions & {
|
|
146
|
+
parts?: ControlParts | undefined;
|
|
147
|
+
size?: ControlSize | undefined;
|
|
148
|
+
};
|
|
149
|
+
/** A key that sinks under a finger, with no appearance of its own.
|
|
150
|
+
*
|
|
151
|
+
* Its frames are `display: contents` markers rather than boxes, because a
|
|
152
|
+
* button is sized by its cap: the width is `min-width` plus the legend.
|
|
153
|
+
* Wrapping the cap in a positioned frame would collapse the control. */
|
|
154
|
+
declare function AmbientPress({ parts, size, className, mode, value, defaultValue, onChange, onPress, repeatDelay, repeatInterval, disabled, children, ...rest }: AmbientPressProps): react_jsx_runtime.JSX.Element;
|
|
155
|
+
|
|
156
|
+
/** How pointer movement becomes value.
|
|
157
|
+
*
|
|
158
|
+
* These are three different mappings, not one with a parameter, and the
|
|
159
|
+
* library was ambiguous about which it implemented: the code did `angle`
|
|
160
|
+
* while knob.md documented `drag`. Naming it makes that drift impossible.
|
|
161
|
+
*
|
|
162
|
+
* - `drag` pointer DISTANCE -> value delta. The v3 default: it is what the
|
|
163
|
+
* docs always described, what most audio software does, and the
|
|
164
|
+
* only one that behaves on touch, where a finger covers the knob.
|
|
165
|
+
* - `angle` pointer POSITION -> absolute angle -> value. Needs a dead zone,
|
|
166
|
+
* and needs a sweep under a full turn to be unambiguous.
|
|
167
|
+
* - `delta` accumulated angular change. The endless-encoder mapping: no
|
|
168
|
+
* ends, no dead zone, and the value may wrap independently of
|
|
169
|
+
* where the pointer happens to be. */
|
|
170
|
+
type RotaryInput = "drag" | "angle" | "delta";
|
|
171
|
+
/** The pot's travel in degrees clockwise from 12 o'clock. A bare number is
|
|
172
|
+
* a sweep centred on 12 o'clock, so `270` is the default 8-to-4 pot. */
|
|
173
|
+
type RotaryTravel = number | {
|
|
174
|
+
start: number;
|
|
175
|
+
sweep: number;
|
|
176
|
+
};
|
|
177
|
+
type UseRotaryOptions = {
|
|
178
|
+
value?: number | undefined;
|
|
179
|
+
defaultValue?: number | undefined;
|
|
180
|
+
min?: number | undefined;
|
|
181
|
+
max?: number | undefined;
|
|
182
|
+
/** Quantises the VALUE. `0` leaves it continuous. */
|
|
183
|
+
step?: number | undefined;
|
|
184
|
+
/** Quantises the TRAVEL: rest positions along the arc. Defaults to the
|
|
185
|
+
* step grid, but the two are independent — an endless encoder can have
|
|
186
|
+
* 24 detents per turn while its value stays continuous. */
|
|
187
|
+
detents?: number | undefined;
|
|
188
|
+
travel?: RotaryTravel | undefined;
|
|
189
|
+
input?: RotaryInput | undefined;
|
|
190
|
+
/** Pixels of drag for one full range, in `drag` mode. */
|
|
191
|
+
dragDistance?: number | undefined;
|
|
192
|
+
/** `delta` mode only: run past the ends and come round again. */
|
|
193
|
+
wrap?: boolean | undefined;
|
|
194
|
+
disabled?: boolean | undefined;
|
|
195
|
+
onChange?: ((next: number) => void) | undefined;
|
|
196
|
+
};
|
|
197
|
+
declare function useRotary(options: UseRotaryOptions): {
|
|
198
|
+
state: ControlState;
|
|
199
|
+
rootProps: {
|
|
200
|
+
onPointerDown: (event: PointerEvent<HTMLDivElement>) => void;
|
|
201
|
+
onPointerMove: (event: PointerEvent<HTMLDivElement>) => void;
|
|
202
|
+
onPointerUp: () => void;
|
|
203
|
+
onPointerCancel: () => void;
|
|
204
|
+
onKeyDown: (event: KeyboardEvent<HTMLDivElement>) => void;
|
|
205
|
+
ref: react.RefObject<HTMLDivElement | null>;
|
|
206
|
+
role: "slider";
|
|
207
|
+
"aria-valuemin": number;
|
|
208
|
+
"aria-valuemax": number;
|
|
209
|
+
"aria-valuenow": number;
|
|
210
|
+
"aria-orientation": "vertical";
|
|
211
|
+
"aria-disabled": true | undefined;
|
|
212
|
+
tabIndex: number;
|
|
213
|
+
style: CSSProperties;
|
|
214
|
+
};
|
|
215
|
+
setValue: (next: number) => void;
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
/** The five control families a kit can dress. */
|
|
219
|
+
type ControlFamily = "rotary" | "travel" | "press" | "latch" | "bank";
|
|
220
|
+
/** What a preset hands its kit: the look options the caller asked for.
|
|
221
|
+
*
|
|
222
|
+
* Deliberately loose. Look props are *kit vocabulary* — `knurling` and
|
|
223
|
+
* `markers` are words the grounded kit made up — so a kit reads the keys it
|
|
224
|
+
* understands and ignores the rest, exactly as a stylesheet that never
|
|
225
|
+
* implemented a class simply does not react to it. See `looks` below for
|
|
226
|
+
* how that stays honest rather than silent. */
|
|
227
|
+
type KitLook = Record<string, unknown>;
|
|
228
|
+
/** A dressed control: what goes in the frames, and what the root wears.
|
|
229
|
+
*
|
|
230
|
+
* The class comes from the kit rather than the preset because it is part of
|
|
231
|
+
* the look — `.amb-knob` carries the grounded knob's own token table, and a
|
|
232
|
+
* kit that replaces the parts has no use for it. */
|
|
233
|
+
type KitDress = {
|
|
234
|
+
parts: ControlParts;
|
|
235
|
+
className?: string | undefined;
|
|
236
|
+
};
|
|
237
|
+
/** Presentation defaults a visual identity may legitimately set.
|
|
238
|
+
*
|
|
239
|
+
* Narrow on purpose: a kit says how its controls should *feel* to turn, not
|
|
240
|
+
* what they are worth. Anything touching value, range or handlers stays with
|
|
241
|
+
* the caller. */
|
|
242
|
+
type KitDefaults = {
|
|
243
|
+
rotary?: {
|
|
244
|
+
travel?: RotaryTravel;
|
|
245
|
+
input?: RotaryInput;
|
|
246
|
+
animate?: ControlAnimate;
|
|
247
|
+
} | undefined;
|
|
248
|
+
travel?: {
|
|
249
|
+
animate?: ControlAnimate;
|
|
250
|
+
} | undefined;
|
|
251
|
+
latch?: {
|
|
252
|
+
animate?: ControlAnimate;
|
|
253
|
+
} | undefined;
|
|
254
|
+
};
|
|
255
|
+
type ControlKit = {
|
|
256
|
+
name: string;
|
|
257
|
+
rotary?: ((look: KitLook) => KitDress) | undefined;
|
|
258
|
+
travel?: ((look: KitLook) => KitDress) | undefined;
|
|
259
|
+
press?: ((look: KitLook) => KitDress) | undefined;
|
|
260
|
+
latch?: ((look: KitLook) => KitDress) | undefined;
|
|
261
|
+
bank?: ((look: KitLook) => KitDress) | undefined;
|
|
262
|
+
defaults?: KitDefaults | undefined;
|
|
263
|
+
/** Look keys each family honours. Used only to warn in development when a
|
|
264
|
+
* caller passes a prop the active kit is going to drop on the floor —
|
|
265
|
+
* the one real cost of letting look props pass through untyped. */
|
|
266
|
+
looks?: Partial<Record<ControlFamily, readonly string[]>> | undefined;
|
|
267
|
+
};
|
|
268
|
+
/** Dress every control below this point in `kit`.
|
|
269
|
+
*
|
|
270
|
+
* A kit is a plain object, so shipping one is shipping a module: no
|
|
271
|
+
* registry, no lifecycle, nothing to initialise. A kit that leaves a family
|
|
272
|
+
* undefined falls through to the default, which is what a real third-party
|
|
273
|
+
* kit will do for most of them. */
|
|
274
|
+
declare function AmbientKitProvider({ kit, children }: PropsWithChildren<{
|
|
275
|
+
kit: ControlKit;
|
|
276
|
+
}>): react_jsx_runtime.JSX.Element;
|
|
277
|
+
declare function useKit(): ControlKit | null;
|
|
278
|
+
/** Resolve a family's dressing: the active kit if it dresses this family,
|
|
279
|
+
* otherwise the fallback the preset was built around. */
|
|
280
|
+
declare function useDress<F extends ControlFamily>(family: F, look: KitLook, fallback: (look: KitLook) => KitDress): {
|
|
281
|
+
dress: KitDress;
|
|
282
|
+
defaults: F extends keyof KitDefaults ? KitDefaults[F] : undefined;
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
type AmbientButtonShape = "pill" | "round" | "square";
|
|
286
|
+
type AmbientButtonSize = "sm" | "md" | "lg";
|
|
287
|
+
type AmbientButtonProps = Omit<AmbientPressProps, "parts" | "size"> & {
|
|
288
|
+
material?: AmbientMaterial | undefined;
|
|
289
|
+
shape?: AmbientButtonShape | undefined;
|
|
290
|
+
size?: AmbientButtonSize | undefined;
|
|
291
|
+
/** Look options in the active kit's vocabulary. */
|
|
292
|
+
look?: KitLook | undefined;
|
|
293
|
+
};
|
|
294
|
+
/** A key cap seated in a clearance well. */
|
|
295
|
+
declare function AmbientButton({ className, children, look, material, shape, size, ...rest }: AmbientButtonProps): react_jsx_runtime.JSX.Element;
|
|
296
|
+
|
|
297
|
+
type UseLatchOptions = {
|
|
298
|
+
value?: boolean | undefined;
|
|
299
|
+
defaultValue?: boolean | undefined;
|
|
300
|
+
onChange?: ((next: boolean) => void) | undefined;
|
|
301
|
+
disabled?: boolean | undefined;
|
|
302
|
+
};
|
|
303
|
+
/** A two-position travel. Kept distinct from Press because its actuator
|
|
304
|
+
* genuinely slides rather than sinking, and because its ARIA is
|
|
305
|
+
* `role="switch"` — a switch is a state, not an action. */
|
|
306
|
+
declare function useLatch(options: UseLatchOptions): {
|
|
307
|
+
state: ControlState;
|
|
308
|
+
rootProps: {
|
|
309
|
+
onClick: () => void;
|
|
310
|
+
type: "button";
|
|
311
|
+
role: "switch";
|
|
312
|
+
"aria-checked": boolean;
|
|
313
|
+
disabled: boolean;
|
|
314
|
+
style: CSSProperties;
|
|
315
|
+
};
|
|
316
|
+
on: boolean;
|
|
317
|
+
setOn: (next: boolean) => void;
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
type AmbientLatchProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, "onChange" | "value" | "defaultValue" | "type"> & UseLatchOptions & {
|
|
321
|
+
parts?: ControlParts | undefined;
|
|
322
|
+
size?: ControlSize | undefined;
|
|
323
|
+
animate?: ControlAnimate | undefined;
|
|
324
|
+
label?: ReactNode | undefined;
|
|
325
|
+
};
|
|
326
|
+
/** A two-position slide, with no appearance of its own. The control IS the
|
|
327
|
+
* track: its actuator is a pill-sized frame that travels across it, which
|
|
328
|
+
* is why anything sitting beside a switch — a lamp, a legend — belongs to
|
|
329
|
+
* whatever composes it rather than to the switch. */
|
|
330
|
+
declare function AmbientLatch({ parts, size, animate, label, className, value, defaultValue, onChange, disabled, children, ...rest }: AmbientLatchProps): react_jsx_runtime.JSX.Element;
|
|
331
|
+
|
|
332
|
+
type AmbientSwitchSize = "sm" | "md" | "lg";
|
|
333
|
+
type AmbientSwitchProps = Omit<AmbientLatchProps, "parts" | "size"> & {
|
|
334
|
+
size?: AmbientSwitchSize | undefined;
|
|
335
|
+
/** A lamp above the switch. `true` for the scene's own colour, or any
|
|
336
|
+
* CSS colour string. */
|
|
337
|
+
led?: boolean | string | undefined;
|
|
338
|
+
/** Look options in the active kit's vocabulary. */
|
|
339
|
+
look?: KitLook | undefined;
|
|
340
|
+
};
|
|
341
|
+
/** A pill sliding in a dark stadium recess, with an optional lamp above.
|
|
342
|
+
*
|
|
343
|
+
* The lamp is mounted beside the switch rather than inside it: the latch
|
|
344
|
+
* control IS the track, so anything that is neither track nor pill belongs
|
|
345
|
+
* to whatever composes them. That means the preset has to hold the state —
|
|
346
|
+
* the lamp and the pill read the same boolean, and only their common
|
|
347
|
+
* parent can see both.
|
|
348
|
+
*/
|
|
349
|
+
declare function AmbientSwitch({ size, led, label, look, value, defaultValue, onChange, animate, className, ...rest }: AmbientSwitchProps): react_jsx_runtime.JSX.Element;
|
|
350
|
+
|
|
351
|
+
type BankOption = {
|
|
352
|
+
value: string;
|
|
353
|
+
/** Key legend — a numeral in the referent, but any node works. */
|
|
354
|
+
label?: ReactNode | undefined;
|
|
355
|
+
/** Accessible name, and the hover title. Needed whenever the legend is a
|
|
356
|
+
* glyph or an icon: a key reading "*" has no name otherwise. */
|
|
357
|
+
ariaLabel?: string | undefined;
|
|
358
|
+
/** Overrides the bank's lamp colour for this key only. */
|
|
359
|
+
color?: string | undefined;
|
|
360
|
+
disabled?: boolean | undefined;
|
|
361
|
+
};
|
|
362
|
+
type BankOrientation = "vertical" | "horizontal";
|
|
363
|
+
type UseBankOptions = {
|
|
364
|
+
options: BankOption[];
|
|
365
|
+
value?: string | string[] | undefined;
|
|
366
|
+
defaultValue?: string | string[] | undefined;
|
|
367
|
+
onChange?: ((value: string | string[]) => void) | undefined;
|
|
368
|
+
/** Let more than one lamp be lit at a time. */
|
|
369
|
+
multiple?: boolean | undefined;
|
|
370
|
+
orientation?: BankOrientation | undefined;
|
|
371
|
+
disabled?: boolean | undefined;
|
|
77
372
|
};
|
|
78
|
-
|
|
373
|
+
/** N presses sharing a selection model.
|
|
374
|
+
*
|
|
375
|
+
* The roving tabindex, the radiogroup-versus-checkbox-group keyboard
|
|
376
|
+
* difference and the selection-follows-focus rule are the reason this
|
|
377
|
+
* mechanism exists: they are the part nobody should have to re-derive in
|
|
378
|
+
* order to change what a key looks like. */
|
|
379
|
+
declare function useBank(options: UseBankOptions): {
|
|
380
|
+
selected: string[];
|
|
381
|
+
select: (option: BankOption | undefined) => void;
|
|
382
|
+
rootProps: {
|
|
383
|
+
role: "group" | "radiogroup";
|
|
384
|
+
"aria-orientation": BankOrientation | undefined;
|
|
385
|
+
"aria-disabled": true | undefined;
|
|
386
|
+
"data-orientation": BankOrientation;
|
|
387
|
+
"data-disabled": string | undefined;
|
|
388
|
+
};
|
|
389
|
+
keyProps: (option: BankOption, index: number) => {
|
|
390
|
+
key: string;
|
|
391
|
+
type: "button";
|
|
392
|
+
ref: (node: HTMLButtonElement | null) => void;
|
|
393
|
+
role: "checkbox" | "radio";
|
|
394
|
+
"aria-checked": boolean;
|
|
395
|
+
"aria-label": string | undefined;
|
|
396
|
+
title: string | undefined;
|
|
397
|
+
disabled: boolean;
|
|
398
|
+
tabIndex: number;
|
|
399
|
+
"data-on": string | undefined;
|
|
400
|
+
onClick: () => void;
|
|
401
|
+
onKeyDown: (event: KeyboardEvent<HTMLButtonElement>) => void;
|
|
402
|
+
};
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
type AmbientBankProps = Omit<HTMLAttributes<HTMLDivElement>, "onChange" | "defaultValue"> & UseBankOptions & {
|
|
406
|
+
/** Parts applied to every key. The bank's own frames go in `parts`. */
|
|
407
|
+
keyParts?: ControlParts | undefined;
|
|
408
|
+
parts?: ControlParts | undefined;
|
|
409
|
+
size?: ControlSize | undefined;
|
|
410
|
+
/** Lamp colour. Defaults to the scene's `--amb-highlight-color`. */
|
|
411
|
+
color?: string | undefined;
|
|
412
|
+
label?: ReactNode | undefined;
|
|
413
|
+
/** Per-key override, for a bank whose keys are not interchangeable. */
|
|
414
|
+
renderKey?: ((option: BankOption, on: boolean) => ReactNode) | undefined;
|
|
415
|
+
};
|
|
416
|
+
/** N keys sharing a selection model, with no appearance of its own.
|
|
417
|
+
*
|
|
418
|
+
* Parts apply per key rather than once, because that is what a bank is.
|
|
419
|
+
* The focusable element is the key `<button>`, which this mechanism
|
|
420
|
+
* renders — your parts go inside it, which is why the presentational-parts
|
|
421
|
+
* rule still holds here. */
|
|
422
|
+
declare function AmbientBank({ options, keyParts, parts, size, color, label, renderKey, className, style, value, defaultValue, onChange, multiple, orientation, disabled, ...rest }: AmbientBankProps): react_jsx_runtime.JSX.Element;
|
|
423
|
+
|
|
424
|
+
type AmbientSelectOption = BankOption;
|
|
425
|
+
type AmbientSelectOrientation = BankOrientation;
|
|
426
|
+
type AmbientSelectSize = "sm" | "md" | "lg";
|
|
427
|
+
type AmbientSelectProps = Omit<AmbientBankProps, "keyParts" | "parts" | "size"> & {
|
|
428
|
+
size?: AmbientSelectSize | undefined;
|
|
429
|
+
/** Look options in the active kit's vocabulary. */
|
|
430
|
+
look?: KitLook | undefined;
|
|
431
|
+
};
|
|
432
|
+
/**
|
|
433
|
+
* A bank of lamp-lit keys in a shared rail — the hardware idiom for a
|
|
434
|
+
* mode selector, where the state is a lamp rather than a mark.
|
|
435
|
+
*
|
|
436
|
+
* Three physical layers per key, and the ORDER is the whole trick: the key
|
|
437
|
+
* itself is the pocket floor, the lens is a disc lying on it, and the cap
|
|
438
|
+
* is a translucent diffuser over both. The cap is `.amb-mat-glass`, so its
|
|
439
|
+
* backdrop-filter blurs the lens behind it — which is why the lens goes in
|
|
440
|
+
* the `base` frame and the cap in `actuator`, and why swapping them would
|
|
441
|
+
* put out every lamp.
|
|
442
|
+
*/
|
|
443
|
+
declare function AmbientSelect({ size, look, className, ...rest }: AmbientSelectProps): react_jsx_runtime.JSX.Element;
|
|
444
|
+
|
|
445
|
+
type AmbientRotaryProps = Omit<HTMLAttributes<HTMLDivElement>, "onChange" | "defaultValue"> & UseRotaryOptions & {
|
|
446
|
+
parts?: ControlParts | undefined;
|
|
447
|
+
size?: ControlSize | undefined;
|
|
448
|
+
animate?: ControlAnimate | undefined;
|
|
449
|
+
label?: ReactNode | undefined;
|
|
450
|
+
};
|
|
451
|
+
/** A rotary mechanism with no appearance of its own.
|
|
452
|
+
*
|
|
453
|
+
* It owns the value, the three pointer mappings, the sweep, the keyboard
|
|
454
|
+
* contract and the ARIA; what it looks like is entirely the `parts` you
|
|
455
|
+
* give it. There is deliberately no `material` prop: which element a
|
|
456
|
+
* material belongs on is a fact about a particular knob's construction —
|
|
457
|
+
* on the clipped face when it is knurled, on the body when it is not —
|
|
458
|
+
* and a mechanism cannot know that once the body is yours. Presets carry
|
|
459
|
+
* `material`, because a preset knows its own parts. */
|
|
460
|
+
declare function AmbientRotary({ parts, size, animate, label, className, value, defaultValue, min, max, step, detents, travel, input, dragDistance, wrap, disabled, onChange, ...rest }: AmbientRotaryProps): react_jsx_runtime.JSX.Element;
|
|
461
|
+
|
|
462
|
+
/** Printed scale dots on the panel around the knob: the arc's two ends, the
|
|
463
|
+
* full graduated ring, or nothing. */
|
|
464
|
+
type AmbientKnobMarkers = "none" | "ends" | "full";
|
|
465
|
+
/** The pointer riding the rotating face: a radial bar or an offset dot. */
|
|
466
|
+
type AmbientKnobIndicator = "rectangle" | "circle";
|
|
467
|
+
type AmbientKnobSize = "sm" | "md" | "lg";
|
|
468
|
+
type AmbientKnobProps = Omit<AmbientRotaryProps, "parts" | "size"> & {
|
|
469
|
+
material?: AmbientMaterial | undefined;
|
|
470
|
+
/** Ribbed grip around the rotating body. Off gives a smooth turned body. */
|
|
471
|
+
knurling?: boolean | undefined;
|
|
472
|
+
/** The grip ring's own colour, for a two-tone knob — any CSS colour, read
|
|
473
|
+
* as an albedo, so it still takes the scene's light rather than being
|
|
474
|
+
* painted flat. Unset, the ring is the same material as the cap. */
|
|
475
|
+
knurlColor?: string | undefined;
|
|
476
|
+
markers?: AmbientKnobMarkers | undefined;
|
|
477
|
+
indicator?: AmbientKnobIndicator | undefined;
|
|
478
|
+
size?: AmbientKnobSize | undefined;
|
|
479
|
+
/** Look options in another kit's vocabulary.
|
|
480
|
+
*
|
|
481
|
+
* The five props above are the *grounded* kit's words. A kit that dresses
|
|
482
|
+
* knobs differently has its own, and they arrive here rather than as
|
|
483
|
+
* loose props so the common path stays typed and a misspelt `knurling`
|
|
484
|
+
* is still a compile error. Kits usually ship a preset of their own that
|
|
485
|
+
* types this properly — see `ConsoleKnob`. */
|
|
486
|
+
look?: KitLook | undefined;
|
|
487
|
+
};
|
|
488
|
+
/**
|
|
489
|
+
* The rotary preset: `AmbientRotary` wearing whatever the active kit says a
|
|
490
|
+
* knob looks like, and the grounded hardware knob when no kit is set.
|
|
491
|
+
*/
|
|
492
|
+
declare function AmbientKnob({ material, knurling, knurlColor, markers, indicator, look, size, className, travel, input, animate, ...rest }: AmbientKnobProps): react_jsx_runtime.JSX.Element;
|
|
493
|
+
|
|
494
|
+
type TravelOrientation = "horizontal" | "vertical";
|
|
495
|
+
type UseTravelOptions = {
|
|
496
|
+
value?: number | undefined;
|
|
497
|
+
defaultValue?: number | undefined;
|
|
498
|
+
min?: number | undefined;
|
|
499
|
+
max?: number | undefined;
|
|
500
|
+
step?: number | undefined;
|
|
501
|
+
detents?: number | undefined;
|
|
502
|
+
orientation?: TravelOrientation | undefined;
|
|
503
|
+
/** Flip which end of the axis is `min`. */
|
|
504
|
+
invert?: boolean | undefined;
|
|
505
|
+
disabled?: boolean | undefined;
|
|
506
|
+
onChange?: ((next: number) => void) | undefined;
|
|
507
|
+
};
|
|
508
|
+
/** A value riding a straight track.
|
|
509
|
+
*
|
|
510
|
+
* One mechanism behind both the slider and the fader, which before v3 were
|
|
511
|
+
* the same file twice with X and Y swapped. The only real difference is
|
|
512
|
+
* which axis the pointer reads — and which end is `min`, where the two
|
|
513
|
+
* disagree for a physical reason rather than a stylistic one: a horizontal
|
|
514
|
+
* track runs min-at-the-left, and an upright one runs min-at-the-bottom,
|
|
515
|
+
* because that is how a fader is built. Both are the default here, so
|
|
516
|
+
* neither preset has to ask. */
|
|
517
|
+
declare function useTravel(options: UseTravelOptions): {
|
|
518
|
+
state: ControlState;
|
|
519
|
+
rootProps: {
|
|
520
|
+
onPointerDown: (event: PointerEvent<HTMLDivElement>) => void;
|
|
521
|
+
onPointerMove: (event: PointerEvent<HTMLDivElement>) => void;
|
|
522
|
+
onPointerUp: () => void;
|
|
523
|
+
onPointerCancel: () => void;
|
|
524
|
+
onKeyDown: (event: KeyboardEvent<HTMLDivElement>) => void;
|
|
525
|
+
ref: react.RefObject<HTMLDivElement | null>;
|
|
526
|
+
role: "slider";
|
|
527
|
+
"aria-valuemin": number;
|
|
528
|
+
"aria-valuemax": number;
|
|
529
|
+
"aria-valuenow": number;
|
|
530
|
+
"aria-orientation": TravelOrientation;
|
|
531
|
+
"aria-disabled": true | undefined;
|
|
532
|
+
tabIndex: number;
|
|
533
|
+
style: CSSProperties;
|
|
534
|
+
"data-orientation": TravelOrientation;
|
|
535
|
+
};
|
|
536
|
+
setValue: (next: number) => void;
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
type AmbientTravelProps = Omit<HTMLAttributes<HTMLDivElement>, "onChange" | "defaultValue"> & UseTravelOptions & {
|
|
540
|
+
parts?: ControlParts | undefined;
|
|
541
|
+
size?: ControlSize | undefined;
|
|
542
|
+
animate?: ControlAnimate | undefined;
|
|
543
|
+
label?: ReactNode | undefined;
|
|
544
|
+
};
|
|
545
|
+
/** A value on a straight track, with no appearance of its own. */
|
|
546
|
+
declare function AmbientTravel({ parts, size, animate, label, className, value, defaultValue, min, max, step, detents, orientation, invert, disabled, onChange, ...rest }: AmbientTravelProps): react_jsx_runtime.JSX.Element;
|
|
547
|
+
|
|
548
|
+
type AmbientFaderSize = "sm" | "md" | "lg";
|
|
549
|
+
type AmbientFaderProps = Omit<AmbientTravelProps, "parts" | "size" | "orientation"> & {
|
|
550
|
+
material?: AmbientMaterial | undefined;
|
|
551
|
+
size?: AmbientFaderSize | undefined;
|
|
552
|
+
/** Look options in the active kit's vocabulary. */
|
|
553
|
+
look?: KitLook | undefined;
|
|
554
|
+
};
|
|
555
|
+
/** A pill cap on a stem, riding an upright slot. Min is at the bottom,
|
|
556
|
+
* which `AmbientTravel` already does for a vertical track. */
|
|
557
|
+
declare function AmbientFader({ material, look, size, animate, className, ...rest }: AmbientFaderProps): react_jsx_runtime.JSX.Element;
|
|
558
|
+
|
|
559
|
+
type AmbientSliderSize = "sm" | "md" | "lg";
|
|
560
|
+
type AmbientSliderProps = Omit<AmbientTravelProps, "parts" | "size" | "orientation"> & {
|
|
561
|
+
material?: AmbientMaterial | undefined;
|
|
562
|
+
size?: AmbientSliderSize | undefined;
|
|
563
|
+
/** Look options in the active kit's vocabulary. */
|
|
564
|
+
look?: KitLook | undefined;
|
|
565
|
+
};
|
|
566
|
+
/** A domed disc gliding over a shallow concave channel. */
|
|
567
|
+
declare function AmbientSlider({ material, look, size, animate, className, ...rest }: AmbientSliderProps): react_jsx_runtime.JSX.Element;
|
|
568
|
+
|
|
569
|
+
/** The Blender-grounded hardware look: the default every preset falls back to. */
|
|
570
|
+
declare const groundedKit: ControlKit;
|
|
571
|
+
|
|
572
|
+
declare const consoleKit: ControlKit;
|
|
573
|
+
type ConsoleKnobProps = Omit<AmbientKnobProps, "look" | "material" | "knurling" | "knurlColor" | "markers" | "indicator"> & {
|
|
574
|
+
/** The accent centre mark printed above the knob. */
|
|
575
|
+
mark?: boolean | undefined;
|
|
576
|
+
/** The −/+ legends at the ends of the travel. */
|
|
577
|
+
legend?: boolean | undefined;
|
|
578
|
+
};
|
|
579
|
+
declare function ConsoleKnob({ mark, legend, ...rest }: ConsoleKnobProps): react_jsx_runtime.JSX.Element;
|
|
580
|
+
type ConsoleToggleProps = Omit<AmbientSwitchProps, "look">;
|
|
581
|
+
declare function ConsoleToggle(props: ConsoleToggleProps): react_jsx_runtime.JSX.Element;
|
|
582
|
+
|
|
583
|
+
/** The knob's base: a flat face housed in a circular groove.
|
|
584
|
+
*
|
|
585
|
+
* Two elements, because they are two pieces of the panel: the groove is the
|
|
586
|
+
* cut, and the face is the flat disc sitting in it, showing the ring of the
|
|
587
|
+
* cut around itself. Neither carries `.ambient` — the face has no body, so
|
|
588
|
+
* there is no edge to cut and nothing to cast, and every cue that reads as
|
|
589
|
+
* depth here belongs either to the walls of the housing or to the bar
|
|
590
|
+
* standing on the face.
|
|
591
|
+
*
|
|
592
|
+
* It sits in the `base` frame, so it does not turn. A plain disc looks the
|
|
593
|
+
* same at every angle, and leaving it still keeps the scene's light on it
|
|
594
|
+
* untouched — only the bar has to do the work below. */
|
|
595
|
+
declare function ConsoleWell({ className }: {
|
|
596
|
+
className?: string | undefined;
|
|
597
|
+
}): react_jsx_runtime.JSX.Element;
|
|
598
|
+
/** The actuator: a cuboid bar lying across the disc on its diameter.
|
|
599
|
+
*
|
|
600
|
+
* Two spans, and the nesting is load-bearing. The bar rides the rotating
|
|
601
|
+
* actuator frame, so a chamfer highlight painted from the inherited light
|
|
602
|
+
* would turn with it and put the lit edge on the wrong side of the screen
|
|
603
|
+
* at half the angles. The fix is to rotate the LIGHT the other way: the
|
|
604
|
+
* outer span captures the scene's light vector, the inner one re-states it
|
|
605
|
+
* in the frame's own turned coordinates, so the bright edge and the drop
|
|
606
|
+
* shadow both stay put on screen while the bar sweeps under them.
|
|
607
|
+
*
|
|
608
|
+
* It has to be two elements because a custom property cannot read itself —
|
|
609
|
+
* `--amb-light-x: calc(var(--amb-light-x) ...)` is a cycle, which resolves
|
|
610
|
+
* to invalid at computed-value time and takes the whole `box-shadow`
|
|
611
|
+
* composite down with it, silently. */
|
|
612
|
+
declare function ConsoleBar({ className }: {
|
|
613
|
+
className?: string | undefined;
|
|
614
|
+
}): react_jsx_runtime.JSX.Element;
|
|
615
|
+
/** Panel graphics around the knob: the accent centre mark above it, and the
|
|
616
|
+
* −/+ legends at the ends of the travel. Both sit outside the knob's own
|
|
617
|
+
* box, which is what the `panel` frame is for. */
|
|
618
|
+
declare function ConsoleMarks({ mark, legend, className }: {
|
|
619
|
+
mark?: boolean | undefined;
|
|
620
|
+
legend?: boolean | undefined;
|
|
621
|
+
className?: string | undefined;
|
|
622
|
+
}): react_jsx_runtime.JSX.Element;
|
|
623
|
+
/** The toggle's track: a pill groove that fills with the accent as the
|
|
624
|
+
* switch travels.
|
|
625
|
+
*
|
|
626
|
+
* A pure-CSS part — it reads `--ambx-percent` off the control root and
|
|
627
|
+
* mixes its own colour from it, so the mechanism does not know this element
|
|
628
|
+
* exists and no React state reaches it. */
|
|
629
|
+
declare function ToggleTrack({ className }: {
|
|
630
|
+
className?: string | undefined;
|
|
631
|
+
}): react_jsx_runtime.JSX.Element;
|
|
632
|
+
/** The travelling thumb: an accent disc inside a white ring.
|
|
633
|
+
*
|
|
634
|
+
* Flat on top and deliberately so — no chamfer, no fillet — but still a
|
|
635
|
+
* knob-scale body, so it casts. That pairing is why the classes are spelt
|
|
636
|
+
* out rather than reached through `.amb-fillet-2`: the edge treatments set
|
|
637
|
+
* a thickness of their own, and here the thickness is wanted without the
|
|
638
|
+
* cut that usually comes with it. */
|
|
639
|
+
declare function ToggleThumb({ className }: {
|
|
640
|
+
className?: string | undefined;
|
|
641
|
+
}): react_jsx_runtime.JSX.Element;
|
|
642
|
+
|
|
643
|
+
/** Read the enclosing control's state from inside a part.
|
|
644
|
+
*
|
|
645
|
+
* This is the third outlet of the state channel, and the one to reach for
|
|
646
|
+
* last: the custom properties on the control root are canonical, and a
|
|
647
|
+
* part that can be styled from CSS should be. Use this when a part needs
|
|
648
|
+
* the value as a JS number — a readout, a tick ring that has to emit N
|
|
649
|
+
* children, an SVG whose path data depends on the value. */
|
|
650
|
+
declare function useControlState(): ControlState;
|
|
651
|
+
/** A bank key carries more than a number: its legend, its accessible name
|
|
652
|
+
* and its own lamp colour all belong to the option, not to the state. So a
|
|
653
|
+
* key's parts get this alongside `useControlState()`. */
|
|
654
|
+
type BankKeyState = {
|
|
655
|
+
option: BankOption;
|
|
656
|
+
on: boolean;
|
|
657
|
+
index: number;
|
|
658
|
+
};
|
|
659
|
+
declare function useBankKey(): BankKeyState;
|
|
660
|
+
|
|
661
|
+
/** The knob's cap: the smooth chamfered disc that is most of what you see,
|
|
662
|
+
* and the element that carries the drop shadow.
|
|
663
|
+
*
|
|
664
|
+
* `flush` takes the full width, which is what a smooth turned knob wants.
|
|
665
|
+
* The default sits back by the knurl band so a `KnurledFace` can ring it —
|
|
666
|
+
* the same cap either way, and the chamfer the referent cuts on every knob
|
|
667
|
+
* (knob.py's `chamfer=0.35`, regardless of rib count) either way too. */
|
|
668
|
+
declare function KnobBody({ material, flush, className }: {
|
|
669
|
+
material?: AmbientMaterial | undefined;
|
|
670
|
+
flush?: boolean | undefined;
|
|
671
|
+
className?: string | undefined;
|
|
672
|
+
}): react_jsx_runtime.JSX.Element;
|
|
673
|
+
/** The rotating knurl: a rim ring of ribs around the cap, clipped to the
|
|
674
|
+
* toothed annulus so the ribs break the outline instead of being painted
|
|
675
|
+
* inside a circle, and shaded per tooth — a lit flank climbing to each
|
|
676
|
+
* ridge, a shaded one falling away — with a contact-occlusion band along
|
|
677
|
+
* its inner edge where the cap overhangs it.
|
|
678
|
+
*
|
|
679
|
+
* The clip is the part's own business — it generates the path, emits its
|
|
680
|
+
* own `<defs>` and references it by a local id. A rotary mechanism has no
|
|
681
|
+
* idea any of this is happening, which is exactly the point: if this part
|
|
682
|
+
* needed help from the control to exist, the split would not be clean. */
|
|
683
|
+
declare function KnurledFace({ material, color, className }: {
|
|
684
|
+
material?: AmbientMaterial | undefined;
|
|
685
|
+
/** The ribs' own colour, as an albedo. */
|
|
686
|
+
color?: string | undefined;
|
|
687
|
+
className?: string | undefined;
|
|
688
|
+
}): react_jsx_runtime.JSX.Element;
|
|
689
|
+
/** The grounded referent's offset indicator dot (knob() dot_frac 0.12,
|
|
690
|
+
* dot_offset 0.68). Put it in the `actuator` frame and it sweeps; put it
|
|
691
|
+
* in `base` and it stays put while everything else turns. */
|
|
692
|
+
declare function IndicatorDot({ className }: {
|
|
693
|
+
className?: string | undefined;
|
|
694
|
+
}): react_jsx_runtime.JSX.Element;
|
|
695
|
+
/** A short radial bar out near the rim, running 0.50R to 0.84R. */
|
|
696
|
+
declare function IndicatorBar({ className }: {
|
|
697
|
+
className?: string | undefined;
|
|
698
|
+
}): react_jsx_runtime.JSX.Element;
|
|
699
|
+
type ScaleRingProps = {
|
|
700
|
+
/** Dots to print. `2` is the pair the travel starts and stops at. */
|
|
701
|
+
count?: number | undefined;
|
|
702
|
+
className?: string | undefined;
|
|
703
|
+
children?: ReactNode | undefined;
|
|
704
|
+
};
|
|
705
|
+
/** Printed scale dots on the panel around a rotary, on the same arc the
|
|
706
|
+
* value sweeps.
|
|
707
|
+
*
|
|
708
|
+
* This is the part that has to read state as JS rather than CSS: the
|
|
709
|
+
* angles come from the control's own travel, and there is no way to emit
|
|
710
|
+
* N children from a stylesheet. It is also the proof that the context
|
|
711
|
+
* outlet works — the dots land on the sweep whatever `travel` is set to,
|
|
712
|
+
* without the ring being told. */
|
|
713
|
+
declare function ScaleRing({ count, className, children }: ScaleRingProps): react_jsx_runtime.JSX.Element;
|
|
714
|
+
|
|
715
|
+
/** The track a thumb rides in.
|
|
716
|
+
*
|
|
717
|
+
* Both grounded referents are grooves with a lume interior — dark in
|
|
718
|
+
* bright light, glowing in low light — but they are cut to different
|
|
719
|
+
* depths: a fader runs in a through-slot, a slider in a shallow concave
|
|
720
|
+
* channel (slider.py, 1mm deep = thickness 0.22). */
|
|
721
|
+
declare function TravelTrack({ depth, className }: {
|
|
722
|
+
depth?: "slot" | "channel" | undefined;
|
|
723
|
+
className?: string | undefined;
|
|
724
|
+
}): react_jsx_runtime.JSX.Element;
|
|
725
|
+
/** Fader cap: the referent (fader.py) is a pill on a stem — 7mm tall
|
|
726
|
+
* (thickness 1.5) riding 2.2mm above the plate (elevation 0.28) — with a
|
|
727
|
+
* single grip line across the top. */
|
|
728
|
+
declare function FaderCap({ material, className }: {
|
|
729
|
+
material?: AmbientMaterial | undefined;
|
|
730
|
+
className?: string | undefined;
|
|
731
|
+
}): react_jsx_runtime.JSX.Element;
|
|
732
|
+
/** Slider thumb: a domed disc gliding over the channel. */
|
|
733
|
+
declare function SliderThumb({ material, className }: {
|
|
734
|
+
material?: AmbientMaterial | undefined;
|
|
735
|
+
className?: string | undefined;
|
|
736
|
+
}): react_jsx_runtime.JSX.Element;
|
|
737
|
+
|
|
738
|
+
/** The key cap: a chamfered, subtly dished top that sinks on `:active`.
|
|
739
|
+
*
|
|
740
|
+
* The cap is what sizes a press control — its legend sets the width above
|
|
741
|
+
* the well's `min-width` — which is why a press control's frames are
|
|
742
|
+
* `display: contents` markers rather than boxes.
|
|
743
|
+
*
|
|
744
|
+
* The cap spends its own `::after` on the dish, so the two micro-relief
|
|
745
|
+
* materials cannot ride on it: their grain wants both pseudo-elements, and
|
|
746
|
+
* the dish's `background` shorthand and the grain's tile would each silently
|
|
747
|
+
* win half of the other's declarations. They get `.ambx-cap-face` instead —
|
|
748
|
+
* an inner layer under the dish and under the legend, which is the inner
|
|
749
|
+
* layer @ambientcss/css's own note prescribes. The cap itself stays a plain
|
|
750
|
+
* `amb-surface` when relief is down there: the dish's overlay alphas are
|
|
751
|
+
* derived from `--amb-shade` the ordinary way, and since the relief
|
|
752
|
+
* materials carry no `--amb-albedo` of their own any more, that derivation
|
|
753
|
+
* is already correct for them too — no per-material tone correction to
|
|
754
|
+
* apply. */
|
|
755
|
+
declare function ButtonCap({ material, className, children }: {
|
|
756
|
+
material?: AmbientMaterial | undefined;
|
|
757
|
+
className?: string | undefined;
|
|
758
|
+
children?: ReactNode | undefined;
|
|
759
|
+
}): react_jsx_runtime.JSX.Element;
|
|
760
|
+
|
|
761
|
+
/** The recess the pill slides in (switch.py: a 1.5mm well, thickness 0.33). */
|
|
762
|
+
declare function SwitchTrack({ className }: {
|
|
763
|
+
className?: string | undefined;
|
|
764
|
+
}): react_jsx_runtime.JSX.Element;
|
|
765
|
+
/** The sliding pill, standing 2.6mm above the recess floor. */
|
|
766
|
+
declare function SwitchPill({ className }: {
|
|
767
|
+
className?: string | undefined;
|
|
768
|
+
}): react_jsx_runtime.JSX.Element;
|
|
769
|
+
/** A pinprick indicator lamp. `color` is any CSS colour; unset it takes the
|
|
770
|
+
* scene's own lamp colour, the same `--amb-led-color` a bank reads. */
|
|
771
|
+
declare function Led({ on, color, className }: {
|
|
772
|
+
on?: boolean | undefined;
|
|
773
|
+
color?: string | undefined;
|
|
774
|
+
className?: string | undefined;
|
|
775
|
+
}): react_jsx_runtime.JSX.Element;
|
|
776
|
+
|
|
777
|
+
/** The lamp under a key: a big disc lying on the pocket floor.
|
|
778
|
+
*
|
|
779
|
+
* It has to paint BEFORE the cap, because the cap's `backdrop-filter` is
|
|
780
|
+
* what diffuses it — which is the whole trick, and the reason the lens
|
|
781
|
+
* belongs in the `base` frame and the cap in `actuator`. */
|
|
782
|
+
declare function KeyLens({ className }: {
|
|
783
|
+
className?: string | undefined;
|
|
784
|
+
}): react_jsx_runtime.JSX.Element;
|
|
785
|
+
/** The translucent diffuser over the lamp, carrying the key's legend.
|
|
786
|
+
*
|
|
787
|
+
* With no children it prints the option's own label, which is why a bank
|
|
788
|
+
* of numerals needs no `renderKey`: the part reads the option it belongs
|
|
789
|
+
* to out of the key context. */
|
|
790
|
+
declare function KeyCap({ className, children }: {
|
|
791
|
+
className?: string | undefined;
|
|
792
|
+
children?: ReactNode | undefined;
|
|
793
|
+
}): react_jsx_runtime.JSX.Element;
|
|
79
794
|
|
|
80
|
-
export { AmbientButton, type AmbientButtonProps, type AmbientButtonShape, AmbientFader, type AmbientFaderProps, AmbientKnob, type AmbientKnobProps, type
|
|
795
|
+
export { AmbientBank, type AmbientBankProps, AmbientButton, type AmbientButtonProps, type AmbientButtonShape, type AmbientButtonSize, AmbientFader, type AmbientFaderProps, type AmbientFaderSize, AmbientKitProvider, AmbientKnob, type AmbientKnobIndicator, type AmbientKnobMarkers, type AmbientKnobProps, type AmbientKnobSize, AmbientLatch, type AmbientLatchProps, type AmbientMaterial, AmbientPanel, type AmbientPanelProps, AmbientPress, type AmbientPressProps, AmbientProvider, type AmbientProviderProps, AmbientRack, type AmbientRackGap, type AmbientRackProps, AmbientRotary, type AmbientRotaryProps, AmbientSelect, type AmbientSelectOption, type AmbientSelectOrientation, type AmbientSelectProps, type AmbientSelectSize, AmbientSlider, type AmbientSliderProps, type AmbientSliderSize, AmbientSwitch, type AmbientSwitchProps, type AmbientSwitchSize, type AmbientTheme, AmbientTravel, type AmbientTravelProps, type BankKeyState, type BankOption, type BankOrientation, ButtonCap, ConsoleBar, ConsoleKnob, type ConsoleKnobProps, ConsoleMarks, ConsoleToggle, type ConsoleToggleProps, ConsoleWell, type ControlAnimate, type ControlFamily, type ControlKit, type ControlParts, type ControlSize, type ControlState, FaderCap, type FrameName, IndicatorBar, IndicatorDot, KeyCap, KeyLens, type KitDefaults, type KitDress, type KitLook, KnobBody, KnurledFace, Led, type PressMode, type RotaryInput, type RotaryTravel, ScaleRing, type ScaleRingProps, SliderThumb, SwitchPill, SwitchTrack, ToggleThumb, ToggleTrack, type TravelOrientation, TravelTrack, type UseBankOptions, type UseLatchOptions, type UsePressOptions, type UseRotaryOptions, type UseTravelOptions, consoleKit, groundedKit, useBank, useBankKey, useControlState, useDress, useKit, useLatch, usePress, useRotary, useTravel };
|