@astryxdesign/core 0.7.6 → 0.7.7-canary.36f8ea1

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 (101) hide show
  1. package/dist/AppShell/AppShell.d.ts.map +1 -1
  2. package/dist/AppShell/AppShell.js +23 -3
  3. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  4. package/dist/BottomSheet/BottomSheetPanel.js +16 -9
  5. package/dist/Chat/ChatComposerInput.d.ts +9 -0
  6. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  7. package/dist/Chat/ChatComposerInput.js +2 -0
  8. package/dist/Chat/ChatMessage.js +2 -2
  9. package/dist/Chat/chatMessage.vars.stylex.d.ts +8 -8
  10. package/dist/Chat/chatMessage.vars.stylex.js +8 -8
  11. package/dist/Drawer/Drawer.d.ts.map +1 -1
  12. package/dist/Drawer/Drawer.js +6 -0
  13. package/dist/DropdownMenu/useMenuOverflow.d.ts +13 -3
  14. package/dist/DropdownMenu/useMenuOverflow.d.ts.map +1 -1
  15. package/dist/DropdownMenu/useMenuOverflow.js +31 -8
  16. package/dist/Link/Link.d.ts.map +1 -1
  17. package/dist/Link/Link.js +1 -0
  18. package/dist/Selector/Selector.d.ts.map +1 -1
  19. package/dist/Selector/Selector.js +25 -13
  20. package/dist/Slider/Slider.d.ts.map +1 -1
  21. package/dist/Slider/Slider.js +404 -131
  22. package/dist/Slider/sliderTouchController.d.ts +189 -0
  23. package/dist/Slider/sliderTouchController.d.ts.map +1 -0
  24. package/dist/Slider/sliderTouchController.js +1017 -0
  25. package/dist/Slider/useSliderTouch.d.ts +22 -0
  26. package/dist/Slider/useSliderTouch.d.ts.map +1 -0
  27. package/dist/Slider/useSliderTouch.js +56 -0
  28. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  29. package/dist/Typeahead/BaseTypeahead.js +10 -8
  30. package/dist/astryx.css +33 -6
  31. package/dist/gestures/GestureArena.d.ts.map +1 -1
  32. package/dist/gestures/GestureArena.js +4 -1
  33. package/dist/gestures/GestureHost.d.ts +72 -2
  34. package/dist/gestures/GestureHost.d.ts.map +1 -1
  35. package/dist/gestures/GestureHost.js +643 -5
  36. package/dist/gestures/GestureRecognizer.d.ts +15 -1
  37. package/dist/gestures/GestureRecognizer.d.ts.map +1 -1
  38. package/dist/gestures/GestureRecognizer.js +12 -0
  39. package/dist/gestures/PanGestureRecognizer.d.ts +8 -0
  40. package/dist/gestures/PanGestureRecognizer.d.ts.map +1 -1
  41. package/dist/gestures/PinchGestureRecognizer.d.ts +5 -1
  42. package/dist/gestures/PinchGestureRecognizer.d.ts.map +1 -1
  43. package/dist/gestures/PinchGestureRecognizer.js +10 -0
  44. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts +3 -3
  45. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts.map +1 -1
  46. package/dist/gestures/ScreenEdgePanGestureRecognizer.js +7 -5
  47. package/dist/gestures/nativeScroll.d.ts +16 -2
  48. package/dist/gestures/nativeScroll.d.ts.map +1 -1
  49. package/dist/gestures/nativeScroll.js +39 -8
  50. package/dist/gestures/recognizerInternals.d.ts +4 -2
  51. package/dist/gestures/recognizerInternals.d.ts.map +1 -1
  52. package/dist/gestures/types.d.ts +11 -0
  53. package/dist/gestures/types.d.ts.map +1 -1
  54. package/dist/gestures/types.js +7 -0
  55. package/dist/gestures/wheelSegmenter.d.ts +45 -0
  56. package/dist/gestures/wheelSegmenter.d.ts.map +1 -0
  57. package/dist/gestures/wheelSegmenter.js +98 -0
  58. package/dist/motion/animator.d.ts.map +1 -1
  59. package/dist/motion/animator.js +77 -14
  60. package/dist/motion/uikit/index.d.ts +2 -1
  61. package/dist/motion/uikit/index.d.ts.map +1 -1
  62. package/dist/motion/uikit/index.js +2 -1
  63. package/dist/motion/uikit/slider.d.ts +97 -0
  64. package/dist/motion/uikit/slider.d.ts.map +1 -0
  65. package/dist/motion/uikit/slider.js +111 -0
  66. package/dist/motion/uikit/springs.d.ts +46 -1
  67. package/dist/motion/uikit/springs.d.ts.map +1 -1
  68. package/dist/motion/uikit/springs.js +48 -4
  69. package/package.json +5 -5
  70. package/src/AppShell/AppShell.doc.mjs +10 -0
  71. package/src/AppShell/AppShell.tsx +48 -2
  72. package/src/BottomSheet/BottomSheetPanel.tsx +16 -9
  73. package/src/Chat/Chat.doc.mjs +1 -0
  74. package/src/Chat/ChatComposerInput.doc.mjs +11 -0
  75. package/src/Chat/ChatComposerInput.tsx +11 -0
  76. package/src/Chat/ChatMessage.tsx +2 -2
  77. package/src/Chat/chatMessage.vars.stylex.ts +8 -8
  78. package/src/Drawer/Drawer.tsx +6 -0
  79. package/src/DropdownMenu/useMenuOverflow.ts +44 -8
  80. package/src/Link/Link.tsx +3 -0
  81. package/src/Selector/Selector.tsx +29 -2
  82. package/src/Slider/Slider.doc.mjs +11 -7
  83. package/src/Slider/Slider.tsx +539 -132
  84. package/src/Slider/sliderTouchController.ts +1209 -0
  85. package/src/Slider/useSliderTouch.ts +78 -0
  86. package/src/Typeahead/BaseTypeahead.tsx +9 -8
  87. package/src/gestures/GestureArena.ts +1 -0
  88. package/src/gestures/GestureHost.ts +765 -5
  89. package/src/gestures/GestureRecognizer.ts +28 -0
  90. package/src/gestures/PanGestureRecognizer.ts +8 -0
  91. package/src/gestures/PinchGestureRecognizer.ts +16 -1
  92. package/src/gestures/README.md +63 -0
  93. package/src/gestures/ScreenEdgePanGestureRecognizer.ts +7 -5
  94. package/src/gestures/nativeScroll.ts +49 -9
  95. package/src/gestures/recognizerInternals.ts +9 -2
  96. package/src/gestures/types.ts +12 -0
  97. package/src/gestures/wheelSegmenter.ts +114 -0
  98. package/src/motion/animator.ts +115 -19
  99. package/src/motion/uikit/index.ts +2 -1
  100. package/src/motion/uikit/slider.ts +105 -0
  101. package/src/motion/uikit/springs.ts +37 -2
@@ -668,26 +668,49 @@ export function createAnimator(element, options = {}) {
668
668
  };
669
669
 
670
670
  /**
671
- * The value on screen at `time`. A curve the browser has not started is at
672
- * its start up to now; a later time reads the curve from its provisional
673
- * start, the model's best guess until the browser's start moves it (a
674
- * companion that samples a curve ahead follows its shape).
671
+ * A held curve's start once a frame dated its call, as the browser's start
672
+ * moves it: by that frame's lead over the call's own time.
673
+ */
674
+ const datedFromLatest = (segment, latest) => latest == null || segment.group == null ? null : {
675
+ latest,
676
+ start: segment.start + latest - segment.group.provisional
677
+ };
678
+
679
+ /**
680
+ * The value on screen at `time`. Until the browser reports its start, a
681
+ * held curve shows its first value. A frame that ran without that start
682
+ * dates the curve. Without that frame, a later time reads from the
683
+ * provisional start, so a companion that samples ahead follows the curve's
684
+ * shape.
675
685
  */
676
686
  const valueAt = (property, time) => {
677
687
  const segment = segments.get(property);
678
- if (segment != null && isHeld(segment) && time <= now()) {
688
+ if (segment != null && isHeld(segment)) {
689
+ // The compositor starts the call near its first frame. The curve is
690
+ // dated as the browser's start would date it. A curve that joined by an
691
+ // older clock keeps its lead over the call's own time.
692
+ const latest = segment.group?.latest?.get(CHANNEL_OF[property]);
693
+ const dated = datedFromLatest(segment, latest);
694
+ if (dated != null) {
695
+ const elapsed = Math.max(time, dated.latest) - dated.start;
696
+ return elapsed >= segment.duration ? segment.target : segment.at(elapsed);
697
+ }
679
698
  // Nothing has moved on screen until the browser starts the call.
680
- return segment.at(0);
699
+ if (time <= now()) {
700
+ return segment.at(0);
701
+ }
681
702
  }
682
703
  return curveAt(property, time);
683
704
  };
684
705
  const velocityAt = (property, time) => {
685
706
  const held = segments.get(property);
686
707
  if (held != null && isHeld(held)) {
687
- // Still at its start on screen, but moving in the model: a retarget
688
- // carries the velocity the curve has reached by now, so a flick whose
689
- // moves all land before the browser starts any keeps its speed.
690
- return held.speed(Math.max(0, time - held.start));
708
+ // Still at its start on screen, but moving in the model. A retarget
709
+ // carries the velocity the curve has reached by now. So a flick whose
710
+ // moves all land before the browser starts any keeps its speed. Past
711
+ // its first frame, it reads from that frame, as its value does.
712
+ const dated = datedFromLatest(held, held.group?.latest?.get(CHANNEL_OF[property]));
713
+ return held.speed(Math.max(0, dated != null && time > dated.latest ? time - dated.start : time - held.start));
691
714
  }
692
715
  const segment = segmentAt(property, time);
693
716
  if (segment == null || time < segment.start) {
@@ -860,6 +883,30 @@ export function createAnimator(element, options = {}) {
860
883
  }
861
884
  }
862
885
  const moving = properties.filter(p => segments.has(p));
886
+ // An explicit call can rebuild a channel while one of its curves still
887
+ // waits for the browser's start. The animation then joins the current
888
+ // call, or else that waiting call, with no start of its own.
889
+ const waiting = callGroup ?? moving.map(p => segments.get(p).group).find(group => group != null && !group.resolved) ?? null;
890
+ const rebuiltAfterFirstFrame = waiting?.framed === true;
891
+ // The new animation starts at the frame that commits it, from its first
892
+ // keyframe. That holds for a waiting call it joins after that call's
893
+ // first frame, and for every waiting call it takes a curve from. So this
894
+ // channel's reads below, and until that frame, take that first value.
895
+ const restarted = new Set();
896
+ if (rebuiltAfterFirstFrame) {
897
+ restarted.add(waiting);
898
+ }
899
+ if (callGroup != null) {
900
+ for (const property of moving) {
901
+ const group = segments.get(property).group;
902
+ if (group != null && group !== callGroup && !group.resolved) {
903
+ restarted.add(group);
904
+ }
905
+ }
906
+ }
907
+ for (const group of restarted) {
908
+ group.latest?.delete(channel);
909
+ }
863
910
  if (channel === 'translate') {
864
911
  // The animation built below starts from the value at `time` (its first
865
912
  // keyframe); a rebase or a retarget builds a new one, so a new start.
@@ -887,10 +934,6 @@ export function createAnimator(element, options = {}) {
887
934
  previous?.cancel();
888
935
  return;
889
936
  }
890
- // A channel rebuilt by an explicit call (set, rebase, a retarget of
891
- // another axis) while one of its curves still waits for the browser's
892
- // start keeps that start: no explicit start for this animation.
893
- const waiting = callGroup ?? moving.map(p => segments.get(p).group).find(group => group != null && !group.resolved) ?? null;
894
937
  // The keyframes start where the animation will: at the waiting call's
895
938
  // own time, which its start moves to the browser's (resolveGroup), so a
896
939
  // write later in the task keeps the screen on the model's clock.
@@ -996,6 +1039,15 @@ export function createAnimator(element, options = {}) {
996
1039
  waiting.channels.add(channel);
997
1040
  // A cancel before the first frame rejects its ready promise.
998
1041
  animation.ready?.catch(() => {});
1042
+ if (rebuiltAfterFirstFrame) {
1043
+ // The frame that commits it dates this channel's start again. The
1044
+ // call's other channels keep their own.
1045
+ requestFrame?.(() => {
1046
+ if (!waiting.resolved && running.get(channel) === animation && animation.startTime == null && animation.playState === 'running') {
1047
+ (waiting.latest ??= new Map()).set(channel, now());
1048
+ }
1049
+ });
1050
+ }
999
1051
  } else {
1000
1052
  // One clock: the keyframes were sampled from `time`.
1001
1053
  animation.startTime = time;
@@ -1614,6 +1666,17 @@ export function createAnimator(element, options = {}) {
1614
1666
  if (!group.resolved && group.madeInFrame !== true && now() - (group.task?.first ?? group.provisional) <= LATE_START_MS && group.animations.some(animation => animation.startTime == null && animation.playState === 'running')) {
1615
1667
  resolveGroup(group, now());
1616
1668
  }
1669
+ // The browser's start is still unread. The compositor starts the call
1670
+ // near this frame, so each moving channel's reads take the curve from
1671
+ // now until the browser tells its start.
1672
+ if (!group.resolved) {
1673
+ for (const channel of group.channels) {
1674
+ const animation = running.get(channel);
1675
+ if (animation != null && group.animations.includes(animation) && animation.startTime == null && animation.playState === 'running') {
1676
+ (group.latest ??= new Map()).set(channel, now());
1677
+ }
1678
+ }
1679
+ }
1617
1680
  });
1618
1681
  ready.then(() => syncGroup(group), () => settleCancelled(group));
1619
1682
  };
@@ -2,7 +2,7 @@
2
2
  * @file index.ts
3
3
  * @input The domain files of the UIKit constants table
4
4
  * @output Re-exports `springs` and one constant per spring (`SHEET_PRESENT_SPRING`,
5
- * …), `scroll`, `timing`, `navigation` and the
5
+ * …), `scroll`, `timing`, `navigation`, the `slider` domain and the
6
6
  * gesture thresholds (one `UIKIT_*` group per recognizer, their union
7
7
  * `UIKIT_GESTURES`, and the haptic tables)
8
8
  * @position Entry of the UIKit constants table (motion/uikit). Internal to
@@ -19,6 +19,7 @@
19
19
  export { HAPTIC_FEEDBACK_KINDS, HAPTIC_VIBRATION_PATTERNS, UIKIT_CLICK, UIKIT_CONTROL, UIKIT_GESTURES, UIKIT_LONG_PRESS, UIKIT_PAN, UIKIT_PINCH, UIKIT_PRESS, UIKIT_ROTATION, UIKIT_SCREEN_EDGE_PAN, UIKIT_SWIPE, UIKIT_TAP, UIKIT_VELOCITY, type GestureConstant, type GestureConstantUnit, type HapticFeedbackKind, } from './gestures.js';
20
20
  export { navigation, registerNavigationTable } from './navigation.js';
21
21
  export { registerScrollTable, scroll } from './scroll.js';
22
+ export { slider } from './slider.js';
22
23
  export { ACTION_SHEET_DISMISS_SPRING, ACTION_SHEET_PRESENT_SPRING, ALERT_DISMISS_SPRING, ALERT_PRESENT_SPRING, BANNER_SPRING, CONTEXT_MENU_DISMISS_SPRING, CONTEXT_MENU_LIFT_SPRING, CONTEXT_MENU_MORPH_SPRING, DIRECT_CHANGE_SPRING, EMPHASIS_SPRING, FINGER_TRACKING_SPRING, KEYBOARD_SPRING, MENU_CLOSE_SPRING, MENU_OPEN_SPRING, MENU_REDUCED_MOTION_SPRING, NAVIGATION_BAR_ELEMENTS_SPRING, NAVIGATION_INTERACTIVE_POP_FINISH_SPRING, NAVIGATION_POP_SPRING, NAVIGATION_PUSH_SPRING, QUICK_CHANGE_SPRING, SEGMENTED_THUMB_SPRING, SETTLE_SPRING, SHEET_DETENT_SPRING, SHEET_DISMISS_SPRING, SHEET_DISMISS_SWIPE_SPRING, SHEET_PRESENT_SPRING, SHEET_RELEASE_FAST_SPRING, STATE_CHANGE_SPRING, SUB_MENU_BACK_SPRING, SUB_MENU_OPEN_SPRING, SWITCH_THUMB_MOVE_SPRING, SWITCH_THUMB_STRETCH_SPRING, TIMED_CHANGE_SPRING, VIEW_CHANGE_SPRING, registerSpringsTable, springs, } from './springs.js';
23
24
  export { registerTimingTable, timing } from './timing.js';
24
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/motion/uikit/index.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,WAAW,EACX,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,WAAW,EACX,WAAW,EACX,cAAc,EACd,qBAAqB,EACrB,WAAW,EACX,SAAS,EACT,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,GACxB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAC,UAAU,EAAE,uBAAuB,EAAC,MAAM,cAAc,CAAC;AACjE,OAAO,EAAC,mBAAmB,EAAE,MAAM,EAAC,MAAM,UAAU,CAAC;AACrD,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,2BAA2B,EAC3B,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,EACpB,eAAe,EACf,sBAAsB,EACtB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,0BAA0B,EAC1B,8BAA8B,EAC9B,wCAAwC,EACxC,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,0BAA0B,EAC1B,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,OAAO,GACR,MAAM,WAAW,CAAC;AACnB,OAAO,EAAC,mBAAmB,EAAE,MAAM,EAAC,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/motion/uikit/index.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,WAAW,EACX,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,WAAW,EACX,WAAW,EACX,cAAc,EACd,qBAAqB,EACrB,WAAW,EACX,SAAS,EACT,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,GACxB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAC,UAAU,EAAE,uBAAuB,EAAC,MAAM,cAAc,CAAC;AACjE,OAAO,EAAC,mBAAmB,EAAE,MAAM,EAAC,MAAM,UAAU,CAAC;AACrD,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAC;AAChC,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,2BAA2B,EAC3B,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,EACpB,eAAe,EACf,sBAAsB,EACtB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,0BAA0B,EAC1B,8BAA8B,EAC9B,wCAAwC,EACxC,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,0BAA0B,EAC1B,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,OAAO,GACR,MAAM,WAAW,CAAC;AACnB,OAAO,EAAC,mBAAmB,EAAE,MAAM,EAAC,MAAM,UAAU,CAAC"}
@@ -4,7 +4,7 @@
4
4
  * @file index.ts
5
5
  * @input The domain files of the UIKit constants table
6
6
  * @output Re-exports `springs` and one constant per spring (`SHEET_PRESENT_SPRING`,
7
- * …), `scroll`, `timing`, `navigation` and the
7
+ * …), `scroll`, `timing`, `navigation`, the `slider` domain and the
8
8
  * gesture thresholds (one `UIKIT_*` group per recognizer, their union
9
9
  * `UIKIT_GESTURES`, and the haptic tables)
10
10
  * @position Entry of the UIKit constants table (motion/uikit). Internal to
@@ -22,5 +22,6 @@
22
22
  export { HAPTIC_FEEDBACK_KINDS, HAPTIC_VIBRATION_PATTERNS, UIKIT_CLICK, UIKIT_CONTROL, UIKIT_GESTURES, UIKIT_LONG_PRESS, UIKIT_PAN, UIKIT_PINCH, UIKIT_PRESS, UIKIT_ROTATION, UIKIT_SCREEN_EDGE_PAN, UIKIT_SWIPE, UIKIT_TAP, UIKIT_VELOCITY } from "./gestures.js";
23
23
  export { navigation, registerNavigationTable } from "./navigation.js";
24
24
  export { registerScrollTable, scroll } from "./scroll.js";
25
+ export { slider } from "./slider.js";
25
26
  export { ACTION_SHEET_DISMISS_SPRING, ACTION_SHEET_PRESENT_SPRING, ALERT_DISMISS_SPRING, ALERT_PRESENT_SPRING, BANNER_SPRING, CONTEXT_MENU_DISMISS_SPRING, CONTEXT_MENU_LIFT_SPRING, CONTEXT_MENU_MORPH_SPRING, DIRECT_CHANGE_SPRING, EMPHASIS_SPRING, FINGER_TRACKING_SPRING, KEYBOARD_SPRING, MENU_CLOSE_SPRING, MENU_OPEN_SPRING, MENU_REDUCED_MOTION_SPRING, NAVIGATION_BAR_ELEMENTS_SPRING, NAVIGATION_INTERACTIVE_POP_FINISH_SPRING, NAVIGATION_POP_SPRING, NAVIGATION_PUSH_SPRING, QUICK_CHANGE_SPRING, SEGMENTED_THUMB_SPRING, SETTLE_SPRING, SHEET_DETENT_SPRING, SHEET_DISMISS_SPRING, SHEET_DISMISS_SWIPE_SPRING, SHEET_PRESENT_SPRING, SHEET_RELEASE_FAST_SPRING, STATE_CHANGE_SPRING, SUB_MENU_BACK_SPRING, SUB_MENU_OPEN_SPRING, SWITCH_THUMB_MOVE_SPRING, SWITCH_THUMB_STRETCH_SPRING, TIMED_CHANGE_SPRING, VIEW_CHANGE_SPRING, registerSpringsTable, springs } from "./springs.js";
26
27
  export { registerTimingTable, timing } from "./timing.js";
@@ -0,0 +1,97 @@
1
+ /**
2
+ * UISlider's touch values: hit target, tracking, release coast, lift, drop
3
+ * and the end-of-track haptic.
4
+ */
5
+ export declare const slider: {
6
+ /**
7
+ * The thumb's touch target, a square in pt centered on the thumb. It is
8
+ * the 37 × 24 pt thumb grown by its hit edge insets: 12 pt above and
9
+ * below, 5.5 pt left and right. UIKit hit-tests inside the control's frame
10
+ * first, so the lab's 40 pt frame clipped it to 48 × 40.
11
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro.
12
+ * `_thumbHitEdgeInsets` reads {−12, −5.5, −12, −5.5}. Touch-downs on a
13
+ * 4 pt grid take the thumb from −24 to +20 pt in x. A track tap away
14
+ * from the thumb moves nothing. Oct 23 2026
15
+ */
16
+ readonly thumbHitTarget: 48;
17
+ /**
18
+ * Value range per track length of finger travel. The value moves by
19
+ * (max − min) × translation ÷ the track's full length. The translation
20
+ * counts from the pan's threshold: the touch-down point plus 10 pt along
21
+ * the track. 1 means one full range per track length.
22
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. In
23
+ * drags at 120 to 2000 pt/s, each event's value is v0 plus the
24
+ * translation past 10 pt ÷ 300. Past the max end, the value leaves 1
25
+ * only once the finger comes back past where it reached 1. Oct 23 2026
26
+ */
27
+ readonly trackingGain: 1;
28
+ /**
29
+ * The coast after the lift. The thumb and the value spring from where the
30
+ * finger left them to the projected target, with the release velocity.
31
+ * Critically damped, it never overshoots a target ahead of it.
32
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The
33
+ * `UIViewSpringAnimationBehavior` at the lift reads response 0.4 and
34
+ * damping ratio 1. Four releases fit it per frame, at rms 0.11 pt or
35
+ * less. Oct 23 2026
36
+ */
37
+ readonly releaseSpring: {
38
+ readonly response: 0.4;
39
+ readonly dampingRatio: 1;
40
+ };
41
+ /**
42
+ * The deceleration rate of the coast's momentum projection, per ms
43
+ * (WWDC18's `project`). It is not UIScrollView's normal rate (0.998), so
44
+ * pass it to the projection explicitly.
45
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The
46
+ * release behavior's projection deceleration reads 0.996. Oct 23 2026
47
+ */
48
+ readonly releaseProjectionRate: 0.996;
49
+ /**
50
+ * How much of the projection the coast travels. The target is the lift
51
+ * value plus this share of the projected distance. A finger lifted outside
52
+ * the control's tracking bounds coasts back to the lift value instead.
53
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The
54
+ * release behavior's target smoothing reads 0.4. A 126.9 pt/s release
55
+ * travels 12.56 pt, against 12.64 predicted. Oct 23 2026
56
+ */
57
+ readonly releaseProjectionShare: 0.4;
58
+ /**
59
+ * The thumb's growth under a finger, uniform about its center (37 × 24 to
60
+ * 57.35 × 37.2 pt).
61
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The lens
62
+ * frame settled during an 800 ms hold. Oct 23 2026
63
+ */
64
+ readonly liftScale: 1.55;
65
+ /**
66
+ * The lift: the thumb grows to `liftScale` when the finger lands.
67
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The lens
68
+ * width per frame in an 800 ms hold fits one spring at rms 0.31 pt.
69
+ * Oct 23 2026
70
+ */
71
+ readonly liftSpring: {
72
+ readonly response: 0.215;
73
+ readonly dampingRatio: 0.6;
74
+ };
75
+ /**
76
+ * The drop: the thumb shrinks back to its rest size when the finger lifts,
77
+ * while the coast runs.
78
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The
79
+ * lens's spring at the lift of an 800 ms hold reads response 0.5 s and
80
+ * damping ratio 0.7. The width per frame fits it at rms 0.10 pt.
81
+ * Oct 23 2026
82
+ */
83
+ readonly dropSpring: {
84
+ readonly response: 0.5;
85
+ readonly dampingRatio: 0.7;
86
+ };
87
+ /**
88
+ * The feedback each time the value reaches an end, once per entry. It
89
+ * re-arms when the value leaves the end, in the drag and the coast. UIKit
90
+ * plays "Micro Tap Medium", and the web stand-in is the closest kind.
91
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The
92
+ * haptics log of drags into both ends shows the fluid slider generator's
93
+ * "Micro Tap Medium" once per entry. Oct 23 2026
94
+ */
95
+ readonly endHaptic: "impactMedium";
96
+ };
97
+ //# sourceMappingURL=slider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slider.d.ts","sourceRoot":"","sources":["../../../src/motion/uikit/slider.ts"],"names":[],"mappings":"AAkBA;;;GAGG;AACH,eAAO,MAAM,MAAM;IACjB;;;;;;;;;OASG;;IAEH;;;;;;;;;OASG;;IAEH;;;;;;;;OAQG;;;;;IAEH;;;;;;OAMG;;IAEH;;;;;;;OAOG;;IAEH;;;;;OAKG;;IAEH;;;;;OAKG;;;;;IAEH;;;;;;;OAOG;;;;;IAEH;;;;;;;OAOG;;CAEK,CAAC"}
@@ -0,0 +1,111 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file slider.ts
5
+ * @input Nothing: data only
6
+ * @output Exports `slider`: UISlider's hit target, tracking rule, release
7
+ * coast, lift, drop and end haptic, measured on the iOS 26.2 simulator
8
+ * @position The slider domain of the UIKit constants table (motion/uikit).
9
+ * Lengths are in pt (CSS px). Tests check each leaf's `@source`.
10
+ *
11
+ * SYNC: When modified, update:
12
+ * - /packages/core/src/Slider/sliderTouchController.ts
13
+ * - /packages/core/src/Slider/Slider.tsx
14
+ * - /packages/core/src/motion/uikit/slider.test.ts
15
+ */
16
+
17
+ import { SLIDER_RELEASE_SPRING } from "./springs.js";
18
+
19
+ /**
20
+ * UISlider's touch values: hit target, tracking, release coast, lift, drop
21
+ * and the end-of-track haptic.
22
+ */
23
+ export const slider = {
24
+ /**
25
+ * The thumb's touch target, a square in pt centered on the thumb. It is
26
+ * the 37 × 24 pt thumb grown by its hit edge insets: 12 pt above and
27
+ * below, 5.5 pt left and right. UIKit hit-tests inside the control's frame
28
+ * first, so the lab's 40 pt frame clipped it to 48 × 40.
29
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro.
30
+ * `_thumbHitEdgeInsets` reads {−12, −5.5, −12, −5.5}. Touch-downs on a
31
+ * 4 pt grid take the thumb from −24 to +20 pt in x. A track tap away
32
+ * from the thumb moves nothing. Oct 23 2026
33
+ */
34
+ thumbHitTarget: 48,
35
+ /**
36
+ * Value range per track length of finger travel. The value moves by
37
+ * (max − min) × translation ÷ the track's full length. The translation
38
+ * counts from the pan's threshold: the touch-down point plus 10 pt along
39
+ * the track. 1 means one full range per track length.
40
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. In
41
+ * drags at 120 to 2000 pt/s, each event's value is v0 plus the
42
+ * translation past 10 pt ÷ 300. Past the max end, the value leaves 1
43
+ * only once the finger comes back past where it reached 1. Oct 23 2026
44
+ */
45
+ trackingGain: 1,
46
+ /**
47
+ * The coast after the lift. The thumb and the value spring from where the
48
+ * finger left them to the projected target, with the release velocity.
49
+ * Critically damped, it never overshoots a target ahead of it.
50
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The
51
+ * `UIViewSpringAnimationBehavior` at the lift reads response 0.4 and
52
+ * damping ratio 1. Four releases fit it per frame, at rms 0.11 pt or
53
+ * less. Oct 23 2026
54
+ */
55
+ releaseSpring: SLIDER_RELEASE_SPRING,
56
+ /**
57
+ * The deceleration rate of the coast's momentum projection, per ms
58
+ * (WWDC18's `project`). It is not UIScrollView's normal rate (0.998), so
59
+ * pass it to the projection explicitly.
60
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The
61
+ * release behavior's projection deceleration reads 0.996. Oct 23 2026
62
+ */
63
+ releaseProjectionRate: 0.996,
64
+ /**
65
+ * How much of the projection the coast travels. The target is the lift
66
+ * value plus this share of the projected distance. A finger lifted outside
67
+ * the control's tracking bounds coasts back to the lift value instead.
68
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The
69
+ * release behavior's target smoothing reads 0.4. A 126.9 pt/s release
70
+ * travels 12.56 pt, against 12.64 predicted. Oct 23 2026
71
+ */
72
+ releaseProjectionShare: 0.4,
73
+ /**
74
+ * The thumb's growth under a finger, uniform about its center (37 × 24 to
75
+ * 57.35 × 37.2 pt).
76
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The lens
77
+ * frame settled during an 800 ms hold. Oct 23 2026
78
+ */
79
+ liftScale: 1.55,
80
+ /**
81
+ * The lift: the thumb grows to `liftScale` when the finger lands.
82
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The lens
83
+ * width per frame in an 800 ms hold fits one spring at rms 0.31 pt.
84
+ * Oct 23 2026
85
+ */
86
+ liftSpring: {
87
+ response: 0.215,
88
+ dampingRatio: 0.6
89
+ },
90
+ /**
91
+ * The drop: the thumb shrinks back to its rest size when the finger lifts,
92
+ * while the coast runs.
93
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The
94
+ * lens's spring at the lift of an 800 ms hold reads response 0.5 s and
95
+ * damping ratio 0.7. The width per frame fits it at rms 0.10 pt.
96
+ * Oct 23 2026
97
+ */
98
+ dropSpring: {
99
+ response: 0.5,
100
+ dampingRatio: 0.7
101
+ },
102
+ /**
103
+ * The feedback each time the value reaches an end, once per entry. It
104
+ * re-arms when the value leaves the end, in the drag and the coast. UIKit
105
+ * plays "Micro Tap Medium", and the web stand-in is the closest kind.
106
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The
107
+ * haptics log of drags into both ends shows the fluid slider generator's
108
+ * "Micro Tap Medium" once per entry. Oct 23 2026
109
+ */
110
+ endHaptic: 'impactMedium'
111
+ };
@@ -399,6 +399,39 @@ export declare const BANNER_SPRING: {
399
399
  readonly stiffness: 1000;
400
400
  readonly damping: 500;
401
401
  };
402
+ /**
403
+ * UISlider's release: after a finger lifts, the thumb settles on this spring
404
+ * toward 0.4 of the release's momentum projection. It is critically damped,
405
+ * so it never overshoots a target ahead of it.
406
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The
407
+ * `UIViewSpringAnimationBehavior` at the lift reads response 0.4 and
408
+ * damping ratio 1. Four releases fit it per frame (the UIKit slider
409
+ * table). Oct 23 2026
410
+ */
411
+ export declare const SLIDER_RELEASE_SPRING: {
412
+ readonly response: 0.4;
413
+ readonly dampingRatio: 1;
414
+ };
415
+ /**
416
+ * UISlider's lift: a finger's touch-down scales the thumb up on this spring.
417
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The
418
+ * thumb's scale per frame after touch-down (the UIKit slider table).
419
+ * Oct 23 2026
420
+ */
421
+ export declare const SLIDER_LIFT_SPRING: {
422
+ readonly response: 0.215;
423
+ readonly dampingRatio: 0.6;
424
+ };
425
+ /**
426
+ * UISlider's drop: the lift's end scales the thumb back down on this spring.
427
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The
428
+ * thumb's scale per frame after the lift (the UIKit slider table).
429
+ * Oct 23 2026
430
+ */
431
+ export declare const SLIDER_DROP_SPRING: {
432
+ readonly response: 0.5;
433
+ readonly dampingRatio: 0.7;
434
+ };
402
435
  /**
403
436
  * Every spring above, by row name: the table the existing readers use. A
404
437
  * component imports only the rows it plays (`architecture:component-style-authoring`
@@ -550,9 +583,21 @@ export declare const springs: {
550
583
  readonly stiffness: 1000;
551
584
  readonly damping: 500;
552
585
  };
586
+ readonly sliderRelease: {
587
+ readonly response: 0.4;
588
+ readonly dampingRatio: 1;
589
+ };
590
+ readonly sliderLift: {
591
+ readonly response: 0.215;
592
+ readonly dampingRatio: 0.6;
593
+ };
594
+ readonly sliderDrop: {
595
+ readonly response: 0.5;
596
+ readonly dampingRatio: 0.7;
597
+ };
553
598
  };
554
599
  /**
555
- * Registers the springs spec:AST-094 FR4 names as internal motion roles
600
+ * Registers the role springs (`SPRING_ROLES`) as internal motion roles
556
601
  * (motion/roles.ts), by their row names (`springs.settle`). Every other
557
602
  * spring, UIKit's menu spring under Reduce Motion and the keyboard's
558
603
  * included, is not a role. Nothing registers on import: the touch code that
@@ -1 +1 @@
1
- {"version":3,"file":"springs.d.ts","sourceRoot":"","sources":["../../../src/motion/uikit/springs.ts"],"names":[],"mappings":"AAmCA;;;;GAIG;AACH,eAAO,MAAM,aAAa;;;CAAsC,CAAC;AAEjE;;;GAGG;AACH,eAAO,MAAM,mBAAmB;;;CAAyC,CAAC;AAE1E;;;GAGG;AACH,eAAO,MAAM,eAAe;;;CAAwC,CAAC;AAErE;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;CAGzB,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,mBAAmB;;;CAA6C,CAAC;AAE9E;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;CAGvB,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,mBAAmB;;;CAAsC,CAAC;AAEvE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,kBAAkB;;;;CAIrB,CAAC;AAMX;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB;;;CAA4C,CAAC;AAEhF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;;CAA4C,CAAC;AAE/E;;;;;;GAMG;AACH,eAAO,MAAM,wCAAwC;;;CAG3C,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B;;;CAGjC,CAAC;AAMX;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB;;;;CAIvB,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;CAIvB,CAAC;AAEX;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB;;;CAGtB,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB;;;CAG5B,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B;;;CAG7B,CAAC;AAMX;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB;;;;CAIvB,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;CAIvB,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B;;;;CAI9B,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,2BAA2B;;;;CAI9B,CAAC;AAEX;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB;;;CAA+C,CAAC;AAE7E;;;;GAIG;AACH,eAAO,MAAM,iBAAiB;;;CAAgD,CAAC;AAE/E;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,oBAAoB;;;CAGvB,CAAC;AAEX;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,oBAAoB;;;CAA4C,CAAC;AAE9E;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB;;;CAG3B,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,2BAA2B;;;CAG9B,CAAC;AAEX;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB;;;CAG5B,CAAC;AAEX;;;;;;;;;GASG;AACH,eAAO,MAAM,0BAA0B;;;CAG7B,CAAC;AAMX;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB;;;CAG3B,CAAC;AAEX;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B;;;CAG9B,CAAC;AAEX;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB;;;CAGzB,CAAC;AAMX;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe;;;;CAIlB,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,aAAa;;;;CAAoD,CAAC;AAE/E;;;;GAIG;AACH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCV,CAAC;AAwBX;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAI3C"}
1
+ {"version":3,"file":"springs.d.ts","sourceRoot":"","sources":["../../../src/motion/uikit/springs.ts"],"names":[],"mappings":"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"}
@@ -488,6 +488,42 @@ export const BANNER_SPRING = {
488
488
  damping: 500
489
489
  };
490
490
 
491
+ /**
492
+ * UISlider's release: after a finger lifts, the thumb settles on this spring
493
+ * toward 0.4 of the release's momentum projection. It is critically damped,
494
+ * so it never overshoots a target ahead of it.
495
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The
496
+ * `UIViewSpringAnimationBehavior` at the lift reads response 0.4 and
497
+ * damping ratio 1. Four releases fit it per frame (the UIKit slider
498
+ * table). Oct 23 2026
499
+ */
500
+ export const SLIDER_RELEASE_SPRING = {
501
+ response: 0.4,
502
+ dampingRatio: 1
503
+ };
504
+
505
+ /**
506
+ * UISlider's lift: a finger's touch-down scales the thumb up on this spring.
507
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The
508
+ * thumb's scale per frame after touch-down (the UIKit slider table).
509
+ * Oct 23 2026
510
+ */
511
+ export const SLIDER_LIFT_SPRING = {
512
+ response: 0.215,
513
+ dampingRatio: 0.6
514
+ };
515
+
516
+ /**
517
+ * UISlider's drop: the lift's end scales the thumb back down on this spring.
518
+ * @source measured: UIKit lab, iOS 26.2 simulator, iPhone 17 Pro. The
519
+ * thumb's scale per frame after the lift (the UIKit slider table).
520
+ * Oct 23 2026
521
+ */
522
+ export const SLIDER_DROP_SPRING = {
523
+ response: 0.5,
524
+ dampingRatio: 0.7
525
+ };
526
+
491
527
  /**
492
528
  * Every spring above, by row name: the table the existing readers use. A
493
529
  * component imports only the rows it plays (`architecture:component-style-authoring`
@@ -527,11 +563,16 @@ export const springs = {
527
563
  switchThumbStretch: SWITCH_THUMB_STRETCH_SPRING,
528
564
  segmentedThumb: SEGMENTED_THUMB_SPRING,
529
565
  keyboard: KEYBOARD_SPRING,
530
- banner: BANNER_SPRING
566
+ banner: BANNER_SPRING,
567
+ sliderRelease: SLIDER_RELEASE_SPRING,
568
+ sliderLift: SLIDER_LIFT_SPRING,
569
+ sliderDrop: SLIDER_DROP_SPRING
531
570
  };
532
571
 
533
572
  /**
534
- * The springs spec:AST-094 FR4 names: the only ones that are motion roles.
573
+ * The only springs that are motion roles. The touch presentations' record
574
+ * names some, and a component's own record names others, such as Slider's
575
+ * three. The generated motion role table lists each with its record.
535
576
  * The registry takes these rows alone, so registering ships no other spring.
536
577
  */
537
578
  const SPRING_ROLES = {
@@ -549,11 +590,14 @@ const SPRING_ROLES = {
549
590
  subMenuBack: SUB_MENU_BACK_SPRING,
550
591
  contextMenuLift: CONTEXT_MENU_LIFT_SPRING,
551
592
  contextMenuDismiss: CONTEXT_MENU_DISMISS_SPRING,
552
- contextMenuMorph: CONTEXT_MENU_MORPH_SPRING
593
+ contextMenuMorph: CONTEXT_MENU_MORPH_SPRING,
594
+ sliderRelease: SLIDER_RELEASE_SPRING,
595
+ sliderLift: SLIDER_LIFT_SPRING,
596
+ sliderDrop: SLIDER_DROP_SPRING
553
597
  };
554
598
 
555
599
  /**
556
- * Registers the springs spec:AST-094 FR4 names as internal motion roles
600
+ * Registers the role springs (`SPRING_ROLES`) as internal motion roles
557
601
  * (motion/roles.ts), by their row names (`springs.settle`). Every other
558
602
  * spring, UIKit's menu spring under Reduce Motion and the keyboard's
559
603
  * included, is not a role. Nothing registers on import: the touch code that
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/core",
3
- "version": "0.7.6",
3
+ "version": "0.7.7-canary.36f8ea1",
4
4
  "displayName": "Astryx Core",
5
5
  "description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
6
6
  "author": "Meta Open Source",
@@ -860,6 +860,9 @@
860
860
  "react-dom": ">=19.0.0"
861
861
  },
862
862
  "devDependencies": {
863
+ "@astryxdesign/a11y-spec": "0.7.7-canary.36f8ea1",
864
+ "@astryxdesign/cli": "0.7.7-canary.36f8ea1",
865
+ "@astryxdesign/interaction-harness": "0.7.7-canary.36f8ea1",
863
866
  "@babel/cli": "^7.29.7",
864
867
  "@babel/core": "^7.29.7",
865
868
  "@babel/preset-react": "^7.29.7",
@@ -870,10 +873,7 @@
870
873
  "@testing-library/jest-dom": "^6.6.0",
871
874
  "@testing-library/react": "^16.3.2",
872
875
  "@types/babel__core": "^7.20.5",
873
- "tailwindcss": "^4.3.2",
874
- "@astryxdesign/cli": "0.7.6",
875
- "@astryxdesign/a11y-spec": "0.0.0",
876
- "@astryxdesign/interaction-harness": "0.0.0"
876
+ "tailwindcss": "^4.3.2"
877
877
  },
878
878
  "dependencies": {
879
879
  "intl-messageformat": "^11.2.9"
@@ -45,6 +45,11 @@ export const docs = {
45
45
  description:
46
46
  'Start the page heading inside `children`. AppShell owns the skip link, the banner landmark and the main landmark, but it renders no heading, so the first heading in the content area is the page h1.',
47
47
  },
48
+ {
49
+ guidance: true,
50
+ description:
51
+ 'On phones, opt the page into the full screen with `viewport-fit=cover` in the viewport meta tag (`width=device-width, initial-scale=1, viewport-fit=cover`). AppShell then extends its header under the status bar and out to the screen sides, and keeps the header\'s items and the end of the content inside the device\'s safe area. An installed web app can also draw under the status bar with `<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">`. In landscape only the header is inset: an inline SideNav and the content\'s sides still reach under a notch, so keep content padding there. A shell with no header region or phone top bar keeps no top inset; keep top padding there.',
52
+ },
48
53
  {
49
54
  guidance: false,
50
55
  description:
@@ -343,6 +348,11 @@ export const docsDense = {
343
348
  description:
344
349
  'Give every nav slot an accessible name: TopNav and SideNav are separate navigation landmarks, so pass `label` to each.',
345
350
  },
351
+ {
352
+ guidance: true,
353
+ description:
354
+ 'Phones: add `viewport-fit=cover` to the viewport meta; the header then reaches under the status bar while its items and the content end stay in the safe area. Landscape: only the header is inset (not an inline SideNav or the content sides). No header region or phone top bar: no top inset, so keep top padding. Installed web apps: `apple-mobile-web-app-status-bar-style` `black-translucent`.',
355
+ },
346
356
  {
347
357
  guidance: true,
348
358
  description: