@charcuterie/ui 3.33.0 → 3.34.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 +30 -0
- package/dist/Board/Board.d.ts.map +1 -1
- package/dist/Board/Board.js +2 -2
- package/dist/Board/Board.js.map +1 -1
- package/dist/RangeSlider/RangeSlider.d.ts +117 -0
- package/dist/RangeSlider/RangeSlider.d.ts.map +1 -0
- package/dist/RangeSlider/RangeSlider.js +242 -0
- package/dist/RangeSlider/RangeSlider.js.map +1 -0
- package/dist/RangeSlider/rangeSliderValue.d.ts +102 -0
- package/dist/RangeSlider/rangeSliderValue.d.ts.map +1 -0
- package/dist/RangeSlider/rangeSliderValue.js +116 -0
- package/dist/RangeSlider/rangeSliderValue.js.map +1 -0
- package/dist/SegmentedControl/SegmentedControl.d.ts +12 -1
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +3 -3
- package/dist/SegmentedControl/SegmentedControl.js.map +1 -1
- package/dist/SegmentedControl/SegmentedOption.d.ts +2 -1
- package/dist/SegmentedControl/SegmentedOption.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedOption.js +7 -2
- package/dist/SegmentedControl/SegmentedOption.js.map +1 -1
- package/dist/Slider/Slider.d.ts +6 -1
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +8 -22
- package/dist/Slider/Slider.js.map +1 -1
- package/dist/TimecodeInput/TimecodeInput.d.ts +88 -0
- package/dist/TimecodeInput/TimecodeInput.d.ts.map +1 -0
- package/dist/TimecodeInput/TimecodeInput.js +258 -0
- package/dist/TimecodeInput/TimecodeInput.js.map +1 -0
- package/dist/TimecodeInput/timecode.d.ts +132 -0
- package/dist/TimecodeInput/timecode.d.ts.map +1 -0
- package/dist/TimecodeInput/timecode.js +246 -0
- package/dist/TimecodeInput/timecode.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/sliderStyles.d.ts +39 -0
- package/dist/sliderStyles.d.ts.map +1 -0
- package/dist/sliderStyles.js +50 -0
- package/dist/sliderStyles.js.map +1 -0
- package/package.json +1 -1
- package/src/Board/Board.test.tsx +8 -0
- package/src/Board/Board.tsx +7 -1
- package/src/RangeSlider/RangeSlider.mdx +85 -0
- package/src/RangeSlider/RangeSlider.stories.tsx +346 -0
- package/src/RangeSlider/RangeSlider.test.tsx +452 -0
- package/src/RangeSlider/RangeSlider.tsx +595 -0
- package/src/RangeSlider/rangeSliderValue.test.ts +217 -0
- package/src/RangeSlider/rangeSliderValue.ts +185 -0
- package/src/SegmentedControl/SegmentedControl.stories.tsx +50 -0
- package/src/SegmentedControl/SegmentedControl.test.tsx +36 -1
- package/src/SegmentedControl/SegmentedControl.tsx +14 -0
- package/src/SegmentedControl/SegmentedOption.tsx +7 -0
- package/src/Slider/Slider.tsx +23 -29
- package/src/TimecodeInput/TimecodeInput.mdx +155 -0
- package/src/TimecodeInput/TimecodeInput.stories.tsx +304 -0
- package/src/TimecodeInput/TimecodeInput.test.tsx +279 -0
- package/src/TimecodeInput/TimecodeInput.tsx +493 -0
- package/src/TimecodeInput/timecode.test.ts +236 -0
- package/src/TimecodeInput/timecode.ts +391 -0
- package/src/index.ts +18 -0
- package/src/sliderStyles.ts +69 -0
- package/src/sourceRules.test.ts +25 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The paint `Slider` and `RangeSlider` share.
|
|
3
|
+
*
|
|
4
|
+
* The two are separate components because their **focus models** are
|
|
5
|
+
* different — one `role="slider"` on the track against two of them in
|
|
6
|
+
* a `role="group"`, one tab stop against two
|
|
7
|
+
* ([decision](../../../docs/decisions/2026-09-01-a-two-thumb-range-is-its-own-component-and-shares-the-bar.md)).
|
|
8
|
+
* What is identical is the bar: a sunken rounded track, an intent
|
|
9
|
+
* fill inside it, and a round thumb pulled back by half its own
|
|
10
|
+
* width.
|
|
11
|
+
*
|
|
12
|
+
* Held here rather than copied for the reason `tileStyles.ts` exists:
|
|
13
|
+
* "the two look the same" spelled as two class strings is a promise
|
|
14
|
+
* that survives exactly one edit. `RangeSlider.test.tsx` compares the
|
|
15
|
+
* two thumbs as **computed** styles, so a class-name refactor cannot
|
|
16
|
+
* quietly break it either.
|
|
17
|
+
*
|
|
18
|
+
* No focus ring here. It is the one part of the bar the two do not
|
|
19
|
+
* share — `Slider` rings the track, because the track is the widget;
|
|
20
|
+
* `RangeSlider` rings each thumb, because each thumb is.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
export type SliderSize = "lg" | "md" | "sm"
|
|
24
|
+
|
|
25
|
+
/** The bar itself. A `sm` bar is 2px; that is not a hit target. */
|
|
26
|
+
export const SLIDER_TRACK_SIZE_CLASS: Record<
|
|
27
|
+
SliderSize,
|
|
28
|
+
string
|
|
29
|
+
> = {
|
|
30
|
+
sm: "h-1",
|
|
31
|
+
md: "h-2",
|
|
32
|
+
lg: "h-3",
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const SLIDER_THUMB_SIZE_CLASS: Record<
|
|
36
|
+
SliderSize,
|
|
37
|
+
string
|
|
38
|
+
> = {
|
|
39
|
+
sm: "size-3",
|
|
40
|
+
md: "size-4",
|
|
41
|
+
lg: "size-5",
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Half of each `SLIDER_THUMB_SIZE_CLASS`, as the inline-start pull-back. */
|
|
45
|
+
export const SLIDER_THUMB_OFFSET: Record<
|
|
46
|
+
SliderSize,
|
|
47
|
+
string
|
|
48
|
+
> = {
|
|
49
|
+
sm: "-0.375rem",
|
|
50
|
+
md: "-0.5rem",
|
|
51
|
+
lg: "-0.625rem",
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The row the bar sits in, which is taller than the bar: a 2px track
|
|
56
|
+
* is not a pointer target, and a finger is 44px. The height comes
|
|
57
|
+
* from the shared control-size system, so `[data-density]` decides
|
|
58
|
+
* it — never `MIN_TOUCH_TARGET_CLASS`, which would make this control
|
|
59
|
+
* taller than the ones beside it at desktop density
|
|
60
|
+
* ([decision](../../../docs/decisions/2026-08-05-controls-share-one-height-no-per-component-touch-floor.md)).
|
|
61
|
+
*/
|
|
62
|
+
export const SLIDER_ROW_CLASS =
|
|
63
|
+
"relative flex w-full touch-none cursor-pointer items-center rounded-full min-h-(--control-height-sm)"
|
|
64
|
+
|
|
65
|
+
export const SLIDER_TRACK_CLASS =
|
|
66
|
+
"w-full overflow-hidden rounded-full bg-surface-sunken"
|
|
67
|
+
|
|
68
|
+
export const SLIDER_THUMB_CLASS =
|
|
69
|
+
"absolute rounded-full border-2 border-surface-raised shadow-sm"
|
package/src/sourceRules.test.ts
CHANGED
|
@@ -545,7 +545,31 @@ test("the barrel is the only place components are re-exported", async () => {
|
|
|
545
545
|
// what it deliberately does not cover — a tile that navigates is
|
|
546
546
|
// not a radio, and giving one `aria-checked` would be worse than
|
|
547
547
|
// the paint it replaced.
|
|
548
|
-
|
|
548
|
+
//
|
|
549
|
+
// `TimecodeInput` — a typed media position, with an `isRange` mode
|
|
550
|
+
// for a section of a file — is +1 -> 63. `timecode.ts` is its
|
|
551
|
+
// member and stays out of this count by the `<Name>/<Name>.tsx`
|
|
552
|
+
// rule, while still being exported from the barrel: the fleet
|
|
553
|
+
// spells the *printing* half five times over (queuepilot twice,
|
|
554
|
+
// castkit, mux-magic twice) and a read-only surface needs the
|
|
555
|
+
// formatter without the field.
|
|
556
|
+
//
|
|
557
|
+
// `RangeSlider` is +1 -> 64. `Slider`'s own record said a two-thumb
|
|
558
|
+
// range is *"a different widget with its own focus model"*, and the
|
|
559
|
+
// focus model is exactly what makes it a component rather than an
|
|
560
|
+
// `isRange` mode: one `role="slider"` on the track becomes two of
|
|
561
|
+
// them on the thumbs inside a `role="group"`, and one tab stop
|
|
562
|
+
// becomes two. So this shares the ARITHMETIC (`sliderValue.ts`,
|
|
563
|
+
// called rather than copied) and the BAR (`sliderStyles.ts`, the
|
|
564
|
+
// same extraction `tileStyles.ts` is), and nothing else.
|
|
565
|
+
// `rangeSliderValue.ts` is its member and stays out of this count
|
|
566
|
+
// by the `<Name>/<Name>.tsx` rule. It lands beside `TimecodeInput`
|
|
567
|
+
// rather than instead of it: the two halves of QueuePilot's clip
|
|
568
|
+
// editor are a typed field and a dragged bar over one value, and
|
|
569
|
+
// `isRange` is right there and wrong here for a reason that is
|
|
570
|
+
// written down — a second text field is still a text field, while a
|
|
571
|
+
// second thumb cannot share one `aria-valuenow`.
|
|
572
|
+
expect(componentNames.length).toBe(64)
|
|
549
573
|
|
|
550
574
|
for (const name of componentNames) {
|
|
551
575
|
expect(barrel).toContain(`export { ${name} }`)
|