@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.
Files changed (63) hide show
  1. package/README.md +30 -0
  2. package/dist/Board/Board.d.ts.map +1 -1
  3. package/dist/Board/Board.js +2 -2
  4. package/dist/Board/Board.js.map +1 -1
  5. package/dist/RangeSlider/RangeSlider.d.ts +117 -0
  6. package/dist/RangeSlider/RangeSlider.d.ts.map +1 -0
  7. package/dist/RangeSlider/RangeSlider.js +242 -0
  8. package/dist/RangeSlider/RangeSlider.js.map +1 -0
  9. package/dist/RangeSlider/rangeSliderValue.d.ts +102 -0
  10. package/dist/RangeSlider/rangeSliderValue.d.ts.map +1 -0
  11. package/dist/RangeSlider/rangeSliderValue.js +116 -0
  12. package/dist/RangeSlider/rangeSliderValue.js.map +1 -0
  13. package/dist/SegmentedControl/SegmentedControl.d.ts +12 -1
  14. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  15. package/dist/SegmentedControl/SegmentedControl.js +3 -3
  16. package/dist/SegmentedControl/SegmentedControl.js.map +1 -1
  17. package/dist/SegmentedControl/SegmentedOption.d.ts +2 -1
  18. package/dist/SegmentedControl/SegmentedOption.d.ts.map +1 -1
  19. package/dist/SegmentedControl/SegmentedOption.js +7 -2
  20. package/dist/SegmentedControl/SegmentedOption.js.map +1 -1
  21. package/dist/Slider/Slider.d.ts +6 -1
  22. package/dist/Slider/Slider.d.ts.map +1 -1
  23. package/dist/Slider/Slider.js +8 -22
  24. package/dist/Slider/Slider.js.map +1 -1
  25. package/dist/TimecodeInput/TimecodeInput.d.ts +88 -0
  26. package/dist/TimecodeInput/TimecodeInput.d.ts.map +1 -0
  27. package/dist/TimecodeInput/TimecodeInput.js +258 -0
  28. package/dist/TimecodeInput/TimecodeInput.js.map +1 -0
  29. package/dist/TimecodeInput/timecode.d.ts +132 -0
  30. package/dist/TimecodeInput/timecode.d.ts.map +1 -0
  31. package/dist/TimecodeInput/timecode.js +246 -0
  32. package/dist/TimecodeInput/timecode.js.map +1 -0
  33. package/dist/index.d.ts +7 -0
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +3 -0
  36. package/dist/index.js.map +1 -1
  37. package/dist/sliderStyles.d.ts +39 -0
  38. package/dist/sliderStyles.d.ts.map +1 -0
  39. package/dist/sliderStyles.js +50 -0
  40. package/dist/sliderStyles.js.map +1 -0
  41. package/package.json +1 -1
  42. package/src/Board/Board.test.tsx +8 -0
  43. package/src/Board/Board.tsx +7 -1
  44. package/src/RangeSlider/RangeSlider.mdx +85 -0
  45. package/src/RangeSlider/RangeSlider.stories.tsx +346 -0
  46. package/src/RangeSlider/RangeSlider.test.tsx +452 -0
  47. package/src/RangeSlider/RangeSlider.tsx +595 -0
  48. package/src/RangeSlider/rangeSliderValue.test.ts +217 -0
  49. package/src/RangeSlider/rangeSliderValue.ts +185 -0
  50. package/src/SegmentedControl/SegmentedControl.stories.tsx +50 -0
  51. package/src/SegmentedControl/SegmentedControl.test.tsx +36 -1
  52. package/src/SegmentedControl/SegmentedControl.tsx +14 -0
  53. package/src/SegmentedControl/SegmentedOption.tsx +7 -0
  54. package/src/Slider/Slider.tsx +23 -29
  55. package/src/TimecodeInput/TimecodeInput.mdx +155 -0
  56. package/src/TimecodeInput/TimecodeInput.stories.tsx +304 -0
  57. package/src/TimecodeInput/TimecodeInput.test.tsx +279 -0
  58. package/src/TimecodeInput/TimecodeInput.tsx +493 -0
  59. package/src/TimecodeInput/timecode.test.ts +236 -0
  60. package/src/TimecodeInput/timecode.ts +391 -0
  61. package/src/index.ts +18 -0
  62. package/src/sliderStyles.ts +69 -0
  63. 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"
@@ -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
- expect(componentNames.length).toBe(62)
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} }`)