@astryxdesign/lab 0.7.5-canary.bc40b80 → 0.7.5-canary.c26ae3f

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 (36) hide show
  1. package/blocks/CommentPinShowcase.doc.mjs +1 -1
  2. package/blocks/CommentPinShowcase.tsx +2 -3
  3. package/dist/CommentPin/CommentPin.d.ts +22 -7
  4. package/dist/CommentPin/CommentPin.d.ts.map +1 -1
  5. package/dist/CommentPin/CommentPin.js +115 -38
  6. package/dist/ListInput/ListInput.d.ts.map +1 -1
  7. package/dist/ListInput/ListInput.js +19 -0
  8. package/dist/MobilePowerSearch/MobilePowerSearch.d.ts +5 -0
  9. package/dist/MobilePowerSearch/MobilePowerSearch.d.ts.map +1 -1
  10. package/dist/MobilePowerSearch/MobilePowerSearch.js +100 -7
  11. package/dist/TransferList/TransferList.d.ts.map +1 -1
  12. package/dist/TransferList/TransferList.js +20 -0
  13. package/dist/lab.css +20 -14
  14. package/dist/reorderStyles.d.ts +2 -2
  15. package/dist/reorderStyles.d.ts.map +1 -1
  16. package/dist/reorderStyles.js +2 -2
  17. package/package.json +7 -7
  18. package/src/Chat/__tests__/ChatTypingIndicator.a11y.chromium.spec.ts +1 -0
  19. package/src/CircularProgress/__tests__/CircularProgress.a11y.chromium.spec.ts +1 -0
  20. package/src/CommentPin/CommentPin.doc.mjs +82 -34
  21. package/src/CommentPin/CommentPin.spec.md +92 -81
  22. package/src/CommentPin/CommentPin.test.tsx +98 -19
  23. package/src/CommentPin/CommentPin.tsx +146 -82
  24. package/src/Comments/Comments.test.tsx +10 -4
  25. package/src/InfoTip/InfoTip.test.tsx +9 -4
  26. package/src/ListInput/ListInput.test.tsx +43 -3
  27. package/src/ListInput/ListInput.tsx +23 -0
  28. package/src/MobilePowerSearch/MobilePowerSearch.test.tsx +165 -5
  29. package/src/MobilePowerSearch/MobilePowerSearch.tsx +113 -5
  30. package/src/MobileTokenizer/MobileTokenizer.test.tsx +12 -3
  31. package/src/TransferList/TransferList.composition.test.tsx +4 -4
  32. package/src/TransferList/TransferList.test.tsx +36 -0
  33. package/src/TransferList/TransferList.tsx +24 -0
  34. package/src/TransferList/TransferListSelector.test.tsx +4 -4
  35. package/src/__tests__/ReorderGripPinchZoom.a11y.chromium.spec.ts +178 -0
  36. package/src/reorderStyles.ts +7 -2
@@ -6,7 +6,7 @@ export default {
6
6
  name: 'Avatar-first annotations',
7
7
  displayName: 'Avatar-first annotations',
8
8
  description:
9
- 'Caller-positioned comment pins over media and in a content margin. Every coordinate maps to the pin’s logical bottom-start corner. The selected group caps its participants at three circles (two Avatars plus +3) and shows its unread count in an accent badge instead of the total; the unread margin pin shows the badge too. Other pins dim without becoming disabled, activating the selected pin again clears the selection, and no pin dims while nothing is selected.',
9
+ 'Caller-positioned comment pins over media and in a content margin. Every coordinate maps to the pin’s logical bottom-start corner. The selected group caps its participants at three circles (two Avatars plus an ellipsis) and ends with its total and an accent unread dot; the unread margin pin shows the dot too. Other pins dim without becoming disabled, activating the selected pin again clears the selection, and no pin dims while nothing is selected.',
10
10
  exampleFor: 'CommentPin',
11
11
  isReady: true,
12
12
  isShowcase: true,
@@ -7,7 +7,7 @@
7
7
  * participant/thread/unread counts, and controlled selected/dimmed state
8
8
  * that may be empty
9
9
  * @output A grouped pin with a three-circle participant cap and an unread
10
- * badge, a resolved pin, and an unread margin pin; activating the selected
10
+ * dot, a single pin, and an unread margin pin; activating the selected
11
11
  * pin clears the selection, and non-selected pins dim only while another pin
12
12
  * is selected
13
13
  * @position CommentPin docsite showcase and copyable Lab block
@@ -160,9 +160,8 @@ export default function CommentPinShowcase() {
160
160
  xstyle={styles.groupedMarker}
161
161
  />
162
162
  <CommentPin
163
- label="Open resolved annotation from Mira"
163
+ label="Open annotation from Mira"
164
164
  participants={[PEOPLE.mira]}
165
- isResolved
166
165
  isSelected={selected === 'resolved'}
167
166
  isDimmed={selected != null && selected !== 'resolved'}
168
167
  onClick={() => toggle('resolved')}
@@ -1,4 +1,6 @@
1
1
  import type { BaseProps } from '@astryxdesign/core';
2
+ /** Pin heights on the shared element-size scale: 28, 32, or 36px. */
3
+ export type CommentPinSize = 'sm' | 'md' | 'lg';
2
4
  /** Identity data for one representative shown inside a CommentPin. */
3
5
  export interface CommentPinParticipant {
4
6
  /** Stable identity used to remove duplicate representatives. */
@@ -21,10 +23,17 @@ export interface CommentPinProps extends Omit<BaseProps<HTMLButtonElement>, 'chi
21
23
  * Ordered participants, lead first. A single marker shows the first. A
22
24
  * grouped marker shows distinct IDs as an AvatarGroup of at most three
23
25
  * circles: every participant when three or fewer are distinct, otherwise the
24
- * first two plus a `+N` overflow circle. Pass every distinct participant so
25
- * the overflow count is accurate.
26
+ * first two plus an ellipsis overflow circle. Pass every distinct
27
+ * participant so the overflow appears only when more than three people
28
+ * participate.
26
29
  */
27
30
  participants: readonly [CommentPinParticipant, ...CommentPinParticipant[]];
31
+ /**
32
+ * Pin height on the element-size scale: `sm` 28px, `md` 32px, `lg` 36px,
33
+ * with 22px, 24px, and 28px participant circles.
34
+ * @default 'sm'
35
+ */
36
+ size?: CommentPinSize;
28
37
  /**
29
38
  * Total number of threads represented by this marker. Values above one use
30
39
  * the grouped presentation and show the exact total.
@@ -33,8 +42,9 @@ export interface CommentPinProps extends Omit<BaseProps<HTMLButtonElement>, 'chi
33
42
  threadCount?: number;
34
43
  /**
35
44
  * Number of represented threads with unread activity. When above zero, an
36
- * accent badge shows this number in place of the thread total, on single
37
- * and grouped pins alike. Values above `threadCount` are capped.
45
+ * accent status dot appears at the end of the pin: after the thread total,
46
+ * or after the participant on a single pin. Values above `threadCount` are
47
+ * capped.
38
48
  * @default 0
39
49
  */
40
50
  unreadCount?: number;
@@ -45,7 +55,11 @@ export interface CommentPinProps extends Omit<BaseProps<HTMLButtonElement>, 'chi
45
55
  * disabling it, so it remains available to switch selection.
46
56
  */
47
57
  isDimmed?: boolean;
48
- /** Whether every thread represented by this pin is resolved. */
58
+ /**
59
+ * Whether every thread represented by this pin is resolved. A resolved pin
60
+ * renders nothing unless it is selected, so resolved discussion leaves the
61
+ * content while a thread the reader opened keeps its anchor.
62
+ */
49
63
  isResolved?: boolean;
50
64
  /** Whether activation is unavailable. */
51
65
  isDisabled?: boolean;
@@ -56,7 +70,8 @@ export interface CommentPinProps extends Omit<BaseProps<HTMLButtonElement>, 'chi
56
70
  * The caller owns grouping, representative selection, coordinates, collision
57
71
  * handling, and the content opened by activation. Absolute placement maps the
58
72
  * host anchor to the pin's logical bottom-start corner. The pin only owns its
59
- * compact button surface and controlled visual states.
73
+ * compact button surface and controlled visual states. `size` sets its height
74
+ * on the element-size scale.
60
75
  *
61
76
  * @example
62
77
  * ```
@@ -79,7 +94,7 @@ export interface CommentPinProps extends Omit<BaseProps<HTMLButtonElement>, 'chi
79
94
  * />
80
95
  * ```
81
96
  */
82
- export declare function CommentPin({ label, participants, threadCount, unreadCount, isSelected, isDimmed, isResolved, isDisabled, ref, xstyle, className, style, ...rest }: CommentPinProps): React.ReactNode;
97
+ export declare function CommentPin({ label, participants, size, threadCount, unreadCount, isSelected, isDimmed, isResolved, isDisabled, ref, xstyle, className, style, ...rest }: CommentPinProps): React.ReactNode;
83
98
  export declare namespace CommentPin {
84
99
  var displayName: string;
85
100
  }
@@ -1 +1 @@
1
- {"version":3,"file":"CommentPin.d.ts","sourceRoot":"","sources":["../../src/CommentPin/CommentPin.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AA2BlD,sEAAsE;AACtE,MAAM,WAAW,qBAAqB;IACpC,gEAAgE;IAChE,EAAE,EAAE,MAAM,CAAC;IACX,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAC3C,SAAS,CAAC,iBAAiB,CAAC,EAC5B,UAAU,CACX;IACC,0CAA0C;IAC1C,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,YAAY,EAAE,SAAS,CAAC,qBAAqB,EAAE,GAAG,qBAAqB,EAAE,CAAC,CAAC;IAC3E;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gEAAgE;IAChE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yCAAyC;IACzC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAqMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,YAAY,EACZ,WAAe,EACf,WAAe,EACf,UAAkB,EAClB,QAAgB,EAChB,UAAkB,EAClB,UAAkB,EAClB,GAAG,EACH,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,eAAe,GAAG,KAAK,CAAC,SAAS,CAyInC;yBAvJe,UAAU"}
1
+ {"version":3,"file":"CommentPin.d.ts","sourceRoot":"","sources":["../../src/CommentPin/CommentPin.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AA4BlD,qEAAqE;AACrE,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEhD,sEAAsE;AACtE,MAAM,WAAW,qBAAqB;IACpC,gEAAgE;IAChE,EAAE,EAAE,MAAM,CAAC;IACX,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAC3C,SAAS,CAAC,iBAAiB,CAAC,EAC5B,UAAU,CACX;IACC,0CAA0C;IAC1C,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;OAOG;IACH,YAAY,EAAE,SAAS,CAAC,qBAAqB,EAAE,GAAG,qBAAqB,EAAE,CAAC,CAAC;IAC3E;;;;OAIG;IACH,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yCAAyC;IACzC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA8ND;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,YAAY,EACZ,IAAW,EACX,WAAe,EACf,WAAe,EACf,UAAkB,EAClB,QAAgB,EAChB,UAAkB,EAClB,UAAkB,EAClB,GAAG,EACH,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,eAAe,GAAG,KAAK,CAAC,SAAS,CA4JnC;yBA3Ke,UAAU"}
@@ -5,8 +5,10 @@
5
5
  /**
6
6
  * @file CommentPin.tsx
7
7
  * @input Ordered participants (grouped pins show at most three circles),
8
- * total and unread represented thread counts, controlled
9
- * selected/dimmed/resolved/disabled state, and button DOM props
8
+ * total and unread represented thread counts (unread shows as a dot), a
9
+ * size on the element-size
10
+ * scale, controlled selected/dimmed/resolved/disabled state, and button DOM
11
+ * props
10
12
  * @output Exports the avatar-first CommentPin button and its public types
11
13
  * @position Lab collaboration primitive for annotation anchors over content or
12
14
  * in content margins; callers own grouping, coordinates, and opened content
@@ -23,11 +25,15 @@ import * as stylex from '@stylexjs/stylex';
23
25
  import { Avatar } from '@astryxdesign/core/Avatar';
24
26
  import { AvatarGroup, AvatarGroupOverflow } from '@astryxdesign/core/AvatarGroup';
25
27
  import { useDevWarning, useMergedRefs, usePressFeedback } from '@astryxdesign/core/hooks';
28
+ import { Icon } from '@astryxdesign/core/Icon';
29
+ import { StatusDot } from '@astryxdesign/core/StatusDot';
26
30
  import '@astryxdesign/core/theme/tokens.stylex';
27
- import { borderVars, colorVars, fontWeightVars, radiusVars, shadowVars, sizeVars, spacingVars, typeScaleVars, typographyVars } from '@astryxdesign/core/theme/tokens.stylex';
31
+ import { borderVars, colorVars, fontWeightVars, shadowVars, sizeVars, spacingVars, typeScaleVars, typographyVars } from '@astryxdesign/core/theme/tokens.stylex';
28
32
  import { useTooltip } from '@astryxdesign/core/Tooltip';
29
33
  import { focusOutlineProps, interactionOverlayStyles, mergeProps, themeProps } from '@astryxdesign/core/utils';
30
34
 
35
+ /** Pin heights on the shared element-size scale: 28, 32, or 36px. */
36
+
31
37
  /** Identity data for one representative shown inside a CommentPin. */
32
38
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
33
39
  const styles = {
@@ -41,17 +47,11 @@ const styles = {
41
47
  kmuXW: "x2lah0s",
42
48
  kXLuUW: "xxymvpz",
43
49
  k3nNDw: "x1bd091l x173emx3",
44
- k7Eaqz: "x1nkkqge",
45
- kZKoxP: "x6k0iem",
46
50
  kogj98: "x1ghz6dp",
47
- kmVPX3: "x12nba7r",
48
51
  kMzoRj: "x1litavf",
49
52
  ksu8eU: "x1y0btm7",
50
53
  kVAM5u: "x9r1u3d",
51
- krdFHd: "x19415el",
52
- kfmiAY: "x8agd5o",
53
- kT0f0o: "x1dgc8on",
54
- kVL7Gh: "x1pczhz8",
54
+ kVL7Gh: "x6en5u8",
55
55
  kWkggS: "x1prclbq",
56
56
  kKwaWg: "x18o3ruo",
57
57
  kGVxlE: "x14hfi27",
@@ -68,8 +68,6 @@ const styles = {
68
68
  withCount: {
69
69
  kjj79g: "x1nhvcw1",
70
70
  kOIVth: "xzye2dw",
71
- kZCmMZ: "x138rykx",
72
- kwRFfy: "x1djylfy",
73
71
  $$css: true
74
72
  },
75
73
  selected: {
@@ -81,15 +79,6 @@ const styles = {
81
79
  kMwMTN: "xv1l7n4 x1k5gbb1",
82
80
  $$css: true
83
81
  },
84
- resolved: {
85
- kAXs8y: "x1kzknox",
86
- kVAM5u: "x9r1u3d x1w1tqly",
87
- kWkggS: "xwmxj5m x9yvj25",
88
- kGVxlE: "x1gnnqk1",
89
- kMwMTN: "xv1l7n4 xs5hli",
90
- kSiTet: "xf9vgkq x1tbh5bv",
91
- $$css: true
92
- },
93
82
  dimmed: {
94
83
  kSiTet: "xti2d7y x1tbh5bv",
95
84
  $$css: true
@@ -102,8 +91,69 @@ const styles = {
102
91
  overflowCircle: {
103
92
  kg3NbH: "xnjsko4",
104
93
  $$css: true
94
+ },
95
+ unreadDot: {
96
+ kAXs8y: "x1kzknox",
97
+ kMwMTN: "x17wrial x1q73b31",
98
+ kWkggS: "x1ewilqj x438xzl",
99
+ $$css: true
105
100
  }
106
101
  };
102
+
103
+ // Each size pairs an element-size height with a participant circle diameter
104
+ // (see AVATAR_SIZE). The padding is the inset that centers that circle in the
105
+ // height, applied on every side: the avatars and overflow sit the same
106
+ // distance from all four edges. The three round corners are half the height,
107
+ // which is fully round: the 9999px full-radius token would make the browser
108
+ // scale every corner down to fit the box (the CSS corner-overlap rule) and
109
+ // shrink the 2px anchor corner to nothing.
110
+ const sizeStyles = {
111
+ sm: {
112
+ k7Eaqz: "x1nkkqge",
113
+ kZKoxP: "x6k0iem",
114
+ kmVPX3: "x5pt662",
115
+ krdFHd: "x404ayl",
116
+ kfmiAY: "x1096wwc",
117
+ kT0f0o: "xjc3rfe",
118
+ $$css: true
119
+ },
120
+ md: {
121
+ k7Eaqz: "x17ydmr0",
122
+ kZKoxP: "x1ueg155",
123
+ kmVPX3: "xnvfkzk",
124
+ krdFHd: "x17mafka",
125
+ kfmiAY: "x1fefpn5",
126
+ kT0f0o: "x11o29ay",
127
+ $$css: true
128
+ },
129
+ lg: {
130
+ k7Eaqz: "x1je4dsv",
131
+ kZKoxP: "xssyfek",
132
+ kmVPX3: "x1fx55se",
133
+ krdFHd: "xgwm7ou",
134
+ kfmiAY: "x7b04l7",
135
+ kT0f0o: "x9hxrvx",
136
+ $$css: true
137
+ }
138
+ };
139
+
140
+ /**
141
+ * Participant circle diameter per pin size, matching the literals in
142
+ * `sizeStyles`. Avatar renders any pixel size; its typed scale lists neither
143
+ * 22 nor 28, hence the cast.
144
+ */
145
+ const AVATAR_SIZE = {
146
+ sm: 22,
147
+ md: 24,
148
+ lg: 28
149
+ };
150
+
151
+ /** The overflow ellipsis per pin size. */
152
+ const OVERFLOW_ICON_SIZE = {
153
+ sm: 'xsm',
154
+ md: 'xsm',
155
+ lg: 'sm'
156
+ };
107
157
  function takeDistinctParticipants(participants, limit) {
108
158
  const result = [];
109
159
  const seen = new Set();
@@ -135,7 +185,8 @@ const MAX_GROUP_CIRCLES = 3;
135
185
  * The caller owns grouping, representative selection, coordinates, collision
136
186
  * handling, and the content opened by activation. Absolute placement maps the
137
187
  * host anchor to the pin's logical bottom-start corner. The pin only owns its
138
- * compact button surface and controlled visual states.
188
+ * compact button surface and controlled visual states. `size` sets its height
189
+ * on the element-size scale.
139
190
  *
140
191
  * @example
141
192
  * ```
@@ -161,6 +212,7 @@ const MAX_GROUP_CIRCLES = 3;
161
212
  export function CommentPin({
162
213
  label,
163
214
  participants,
215
+ size = 'sm',
164
216
  threadCount = 1,
165
217
  unreadCount = 0,
166
218
  isSelected = false,
@@ -173,6 +225,8 @@ export function CommentPin({
173
225
  style,
174
226
  ...rest
175
227
  }) {
228
+ const resolvedSize = size === 'md' || size === 'lg' ? size : 'sm';
229
+ const avatarSize = AVATAR_SIZE[resolvedSize];
176
230
  const validThreadCount = isValidThreadCount(threadCount);
177
231
  const resolvedThreadCount = validThreadCount ? threadCount : 1;
178
232
  const isGrouped = resolvedThreadCount > 1;
@@ -181,7 +235,7 @@ export function CommentPin({
181
235
  const hasUnread = resolvedUnreadCount > 0;
182
236
 
183
237
  // Grouped pins cap at MAX_GROUP_CIRCLES circles: every distinct participant
184
- // when they fit, otherwise one fewer Avatar plus a `+N` overflow circle.
238
+ // when they fit, otherwise one fewer Avatar plus an ellipsis overflow circle.
185
239
  const distinctParticipants = takeDistinctParticipants(participants, isGrouped ? Number.POSITIVE_INFINITY : 1);
186
240
  const hasOverflow = isGrouped && distinctParticipants.length > MAX_GROUP_CIRCLES;
187
241
  const visibleParticipants = hasOverflow ? distinctParticipants.slice(0, MAX_GROUP_CIRCLES - 1) : distinctParticipants;
@@ -197,6 +251,13 @@ export function CommentPin({
197
251
  isEnabled: hasTooltip
198
252
  });
199
253
  const mergedRef = useMergedRefs(ref, hasTooltip ? tooltip.ref : undefined);
254
+
255
+ // Resolved discussion leaves the content. A selected pin stays, so a thread
256
+ // the reader opened (or resolved from its popover) keeps its anchor until
257
+ // the host clears the selection.
258
+ if (isResolved && !isSelected) {
259
+ return null;
260
+ }
200
261
  const avatarParticipants = visibleParticipants.length > 0 ? visibleParticipants : [{
201
262
  id: '__anonymous__',
202
263
  name: '',
@@ -211,46 +272,62 @@ export function CommentPin({
211
272
  "aria-pressed": isSelected,
212
273
  disabled: isDisabled,
213
274
  ...mergeProps(themeProps('comment-pin', {
275
+ size: resolvedSize,
214
276
  grouped: isGrouped ? 'grouped' : null,
215
277
  unread: hasUnread ? 'unread' : null,
216
278
  selected: isSelected ? 'selected' : null,
217
279
  dimmed: isDimmed ? 'dimmed' : null,
218
280
  resolved: isResolved ? 'resolved' : null,
219
281
  disabled: isDisabled ? 'disabled' : null
220
- }), focusOutlineProps.focusVisible(styles.root, interactionOverlayStyles.backgroundImage, (isGrouped || hasUnread) && styles.withCount, isResolved && !isSelected && styles.resolved, isDimmed && !isSelected && styles.dimmed, isSelected && styles.selected, isDisabled && styles.disabled, xstyle), className, style),
282
+ }), focusOutlineProps.focusVisible(styles.root, sizeStyles[resolvedSize], interactionOverlayStyles.backgroundImage, (isGrouped || hasUnread) && styles.withCount, isDimmed && !isSelected && styles.dimmed, isSelected && styles.selected, isDisabled && styles.disabled, xstyle), className, style),
221
283
  children: [/*#__PURE__*/_jsx("span", {
222
284
  "aria-hidden": "true",
223
285
  ...{
224
- className: "x3nfvp2 x6s0dn4 x2lah0s"
225
- },
286
+ 0: {
287
+ className: "x3nfvp2 x6s0dn4 x2lah0s"
288
+ },
289
+ 1: {
290
+ className: "x3nfvp2 x6s0dn4 x2lah0s xe9ewy2"
291
+ }
292
+ }[!!isGrouped << 0],
226
293
  children: isGrouped ? /*#__PURE__*/_jsxs(AvatarGroup, {
227
- size: "xsm",
294
+ size: avatarSize,
228
295
  children: [avatarParticipants.map(participant => /*#__PURE__*/_jsx(Avatar, {
229
296
  name: participant.name,
230
297
  src: participant.avatarSrc,
231
298
  tooltip: false
232
299
  }, participant.id)), overflowCount > 0 ? /*#__PURE__*/_jsx(AvatarGroupOverflow, {
233
300
  count: overflowCount,
234
- xstyle: styles.overflowCircle
301
+ xstyle: styles.overflowCircle,
302
+ children: /*#__PURE__*/_jsx(Icon, {
303
+ icon: "moreHorizontal",
304
+ size: OVERFLOW_ICON_SIZE[resolvedSize]
305
+ })
235
306
  }) : null]
236
307
  }) : avatarParticipants.map(participant => /*#__PURE__*/_jsx(Avatar, {
237
308
  name: participant.name,
238
309
  src: participant.avatarSrc,
239
- size: "xsm",
310
+ size: avatarSize,
240
311
  tooltip: false
241
312
  }, participant.id))
242
- }), hasUnread ? /*#__PURE__*/_jsx("span", {
243
- "aria-hidden": "true",
244
- ...{
245
- className: "x1kzknox x3nfvp2 x6s0dn4 xl56j7k x9f619 x16asifk x1grt7ep x7a5moj xjspbzw x1ewilqj x1jzqe4 x17wrial x1k5gbb1 xss6m8b xo5v014"
246
- },
247
- children: resolvedUnreadCount
248
- }) : isGrouped ? /*#__PURE__*/_jsx("span", {
313
+ }), hasUnread || isGrouped ? /*#__PURE__*/_jsxs("span", {
249
314
  "aria-hidden": "true",
250
315
  ...{
251
- className: "x1rg5ohu x163how x1heor9g xss6m8b x2b8uid"
316
+ className: "x3nfvp2 x6s0dn4 xzye2dw x1nryj5t"
252
317
  },
253
- children: resolvedThreadCount
318
+ children: [isGrouped ? /*#__PURE__*/_jsx("span", {
319
+ ...{
320
+ className: "x1heor9g xss6m8b"
321
+ },
322
+ children: resolvedThreadCount
323
+ }) : null, hasUnread ?
324
+ /*#__PURE__*/
325
+ // Decorative: the button's label carries the unread context.
326
+ _jsx(StatusDot, {
327
+ variant: "accent",
328
+ label: "",
329
+ xstyle: styles.unreadDot
330
+ }) : null]
254
331
  }) : null]
255
332
  });
256
333
  return /*#__PURE__*/_jsxs(_Fragment, {
@@ -1 +1 @@
1
- {"version":3,"file":"ListInput.d.ts","sourceRoot":"","sources":["../../src/ListInput/ListInput.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ListInput.d.ts","sourceRoot":"","sources":["../../src/ListInput/ListInput.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,EAOL,KAAK,GAAG,EACR,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAGlD,OAAO,EAAQ,KAAK,WAAW,EAAC,MAAM,0BAA0B,CAAC;AAYjE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,0BAA0B,CAAC;AAiB1D,MAAM,MAAM,eAAe,CAAC,CAAC,IACzB;IAAC,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,GACrC;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,CAAC,CAAC;IACR,YAAY,EAAE,CAAC,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GACD;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,GACxC;IAAC,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAAC;AAEnE,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACtC,sBAAsB;IACtB,IAAI,EAAE,CAAC,CAAC;IACR,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,sBAAsB,CAAC,CAAC,CAAE,SAAQ,qBAAqB,CAAC,CAAC,CAAC;IACzE,uDAAuD;IACvD,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,gFAAgF;IAChF,aAAa,EAAE,SAAS,CAAC;IACzB,uDAAuD;IACvD,UAAU,EAAE,OAAO,CAAC;IACpB,6DAA6D;IAC7D,SAAS,EAAE,OAAO,CAAC;IACnB,kDAAkD;IAClD,UAAU,EAAE,CAAC,QAAQ,EAAE,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACvD;AAED,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAC;IACZ,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,iDAAiD;IACjD,WAAW,EAAE,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;CAChE;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,CAAE,SAAQ,IAAI,CAC7C,SAAS,CAAC,cAAc,CAAC,EACzB,UAAU,CACX;IACC,gDAAgD;IAChD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAA0B;IAC1B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,gFAAgF;IAChF,QAAQ,EAAE,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IAC/D,kEAAkE;IAClE,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,GAAG,CAAC;IAC7B,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC,CAAC;IACpB,6CAA6C;IAC7C,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9B,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,CAAC;IACpE,gEAAgE;IAChE,cAAc,CAAC,EAAE,CACf,IAAI,EAAE,CAAC,EACP,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,KACV,WAAW,GAAG,SAAS,CAAC;IAC7B,0EAA0E;IAC1E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iEAAiE;IACjE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,+BAA+B;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+BAA+B;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA6dD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,EAC3B,KAAK,EACL,WAAW,EACX,KAAK,EACL,QAAQ,EACR,UAAU,EACV,UAAU,EACV,OAAO,EACP,QAAiB,EACjB,MAAM,EACN,aAAa,EACb,cAAc,EACd,aAAqB,EACrB,UAAkB,EAClB,SAAiB,EACjB,QAAQ,EACR,aAAqB,EACrB,UAAkB,EAClB,UAAkB,EAClB,GAAG,EACH,GAAG,IAAI,EACR,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS,CAuuC/B;yBA5vCe,SAAS"}
@@ -476,6 +476,25 @@ export function ListInput({
476
476
  announce(t('@astryx.listInput.announceReorderCancelled'));
477
477
  }
478
478
  }, [isDisabled, isLoading, announce, t]);
479
+
480
+ // A second pointer that lands anywhere during a pointer reorder (the second
481
+ // finger of a pinch) cancels the reorder. A pinch whose first finger slid
482
+ // first zooms without a pointercancel, so the drag would otherwise commit on
483
+ // release and drop the row at the end of the list.
484
+ useEffect(() => {
485
+ if (!isPointerReorderActive) {
486
+ return;
487
+ }
488
+ const onPointerDown = event => {
489
+ const activeState = reorderStateRef.current;
490
+ if (activeState?.mode === 'pointer' && activeState.pointerId !== event.pointerId) {
491
+ setReorderState(null);
492
+ announce(t('@astryx.listInput.announceReorderCancelled'));
493
+ }
494
+ };
495
+ document.addEventListener('pointerdown', onPointerDown, true);
496
+ return () => document.removeEventListener('pointerdown', onPointerDown, true);
497
+ }, [isPointerReorderActive, announce, t]);
479
498
  useEffect(() => {
480
499
  const activeAnimations = activeMutationAnimationsRef.current;
481
500
  return () => {
@@ -24,6 +24,11 @@
24
24
  * and tokens wrap inside the trigger;
25
25
  * - strings are literals (no new i18n keys; existing Core keys are reused
26
26
  * only for the result count and the add announcement);
27
+ * - announcements made while a sheet is open go to a persistent polite
28
+ * region inside each sheet, created empty and kept mounted (spec AST-086
29
+ * FR3), because the shared page-body channel is not exposed while a
30
+ * native modal dialog is open (its Platform support section); the closed
31
+ * field still uses the shared channel;
27
32
  * - no theming contract: no `power-search` theme target or selectors;
28
33
  * - `components[type].Token` overrides receive Core's PowerSearchTokenProps,
29
34
  * which carry no `timezoneID`; the built-in token renders Core `Token`
@@ -1 +1 @@
1
- {"version":3,"file":"MobilePowerSearch.d.ts","sourceRoot":"","sources":["../../src/MobilePowerSearch/MobilePowerSearch.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MobilePowerSearch.d.ts","sourceRoot":"","sources":["../../src/MobilePowerSearch/MobilePowerSearch.tsx"],"names":[],"mappings":"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"}
@@ -28,6 +28,11 @@
28
28
  * and tokens wrap inside the trigger;
29
29
  * - strings are literals (no new i18n keys; existing Core keys are reused
30
30
  * only for the result count and the add announcement);
31
+ * - announcements made while a sheet is open go to a persistent polite
32
+ * region inside each sheet, created empty and kept mounted (spec AST-086
33
+ * FR3), because the shared page-body channel is not exposed while a
34
+ * native modal dialog is open (its Platform support section); the closed
35
+ * field still uses the shared channel;
31
36
  * - no theming contract: no `power-search` theme target or selectors;
32
37
  * - `components[type].Token` overrides receive Core's PowerSearchTokenProps,
33
38
  * which carry no `timezoneID`; the built-in token renders Core `Token`
@@ -67,6 +72,7 @@ import { Text } from '@astryxdesign/core/Text';
67
72
  import { TextInput } from '@astryxdesign/core/TextInput';
68
73
  import { Token } from '@astryxdesign/core/Token';
69
74
  import { useTooltip } from '@astryxdesign/core/Tooltip';
75
+ import { VisuallyHidden } from '@astryxdesign/core/VisuallyHidden';
70
76
  import { useAnnounce, useDevWarning, useMergedRefs } from '@astryxdesign/core/hooks';
71
77
  import { useLocale, useTranslator } from '@astryxdesign/core/i18n';
72
78
  import '@astryxdesign/core/theme/tokens.stylex';
@@ -146,6 +152,9 @@ function resolveDraftFilterIndex(filters, draft) {
146
152
  const SEARCHABLE_FIELD_COUNT = 8;
147
153
  const DEFAULT_MAX_SEARCH_RESULTS = 10;
148
154
  const MAX_BROWSE_MENU_ITEMS = 1000;
155
+ // How long a message stays in the sheets' live region; the shared channel
156
+ // clears on the same schedule.
157
+ const SHEET_ANNOUNCEMENT_CLEAR_MS = 2000;
149
158
 
150
159
  // =============================================================================
151
160
  // Token
@@ -235,7 +244,62 @@ export function MobilePowerSearch({
235
244
  const config = useMobilePowerSearchConfig(configProp);
236
245
  const t = useTranslator();
237
246
  const locale = useLocale();
238
- const announce = useAnnounce();
247
+ const announceOnPage = useAnnounce();
248
+ // While a sheet is open the page-body live region is not exposed (the
249
+ // sheets are native modal dialogs), so a message then goes to the polite
250
+ // region rendered inside the sheets; `step` is read through a ref because
251
+ // the add path changes the step in the same tick it announces.
252
+ const [sheetAnnouncement, setSheetAnnouncement] = useState('');
253
+ const sheetAnnouncementFrameRef = useRef(null);
254
+ const pendingSheetMessagesRef = useRef([]);
255
+ const sheetAnnouncementClearRef = useRef(null);
256
+ const stepRef = useRef(null);
257
+ const announce = useCallback(message => {
258
+ if (stepRef.current == null) {
259
+ announceOnPage(message);
260
+ return;
261
+ }
262
+ // Clear, then write on the next frame so the same words announce again
263
+ // (FR6: a new occasion), and clear shortly after so stale text does not
264
+ // linger in a sheet that opens later (FR3). Messages that arrive while
265
+ // the frame is pending are joined in order into that one write, the way
266
+ // the shared channel joins them (FR9), so an add and the result count
267
+ // it changes in the same commit are both heard.
268
+ pendingSheetMessagesRef.current.push(message);
269
+ if (sheetAnnouncementFrameRef.current != null) {
270
+ return;
271
+ }
272
+ if (sheetAnnouncementClearRef.current != null) {
273
+ clearTimeout(sheetAnnouncementClearRef.current);
274
+ sheetAnnouncementClearRef.current = null;
275
+ }
276
+ setSheetAnnouncement('');
277
+ sheetAnnouncementFrameRef.current = requestAnimationFrame(() => {
278
+ sheetAnnouncementFrameRef.current = null;
279
+ const joined = pendingSheetMessagesRef.current.join(' ');
280
+ pendingSheetMessagesRef.current = [];
281
+ setSheetAnnouncement(joined);
282
+ sheetAnnouncementClearRef.current = setTimeout(() => {
283
+ sheetAnnouncementClearRef.current = null;
284
+ setSheetAnnouncement('');
285
+ }, SHEET_ANNOUNCEMENT_CLEAR_MS);
286
+ });
287
+ }, [announceOnPage]);
288
+ // Owns the sheet announcer's frame and clear timer: released on teardown,
289
+ // with the refs and the pending queue reset, so an Effect teardown that is
290
+ // not an unmount (an <Activity> hide) leaves no cancelled id behind that
291
+ // would block later in-sheet announcements.
292
+ useEffect(() => () => {
293
+ if (sheetAnnouncementFrameRef.current != null) {
294
+ cancelAnimationFrame(sheetAnnouncementFrameRef.current);
295
+ sheetAnnouncementFrameRef.current = null;
296
+ }
297
+ if (sheetAnnouncementClearRef.current != null) {
298
+ clearTimeout(sheetAnnouncementClearRef.current);
299
+ sheetAnnouncementClearRef.current = null;
300
+ }
301
+ pendingSheetMessagesRef.current = [];
302
+ }, []);
239
303
  const triggerLabel = labelFromProps ?? 'Manage filters';
240
304
  const fieldPlaceholder = placeholderFromProps ?? 'Filters…';
241
305
  const contentSearchPlaceholder = placeholderFromProps ?? 'Search…';
@@ -244,6 +308,8 @@ export function MobilePowerSearch({
244
308
  const hasContentSearch = contentSearchOperator?.value.type === 'string';
245
309
  const contentSearchSource = useMemo(() => createContentSearchSource(config, t, maxSearchResults), [config, maxSearchResults, t]);
246
310
  const triggerId = useId();
311
+ const triggerLabelId = useId();
312
+ const triggerContentId = useId();
247
313
  const statusMessageId = useId();
248
314
  const contentResultsId = useId();
249
315
  const triggerRef = useRef(null);
@@ -258,6 +324,7 @@ export function MobilePowerSearch({
258
324
  const pendingSheetFocusRef = useRef(null);
259
325
  const pendingMutationFocusRef = useRef(false);
260
326
  const [step, setStep] = useState(null);
327
+ stepRef.current = step;
261
328
  // The draft outlives a step change on purpose: the switcher keeps the
262
329
  // outgoing sheet mounted while the incoming one enters, and clearing the
263
330
  // draft with the step would blank that sheet mid-transition.
@@ -667,12 +734,21 @@ export function MobilePowerSearch({
667
734
  }
668
735
  return resultCount;
669
736
  }, [resultCount, t]);
670
- const hasMountedRef = useRef(false);
737
+
738
+ // This Effect synchronizes a polite live region with the result count: the
739
+ // shared page-body one while the field is closed, the sheets' own while a
740
+ // sheet is open. A count present on mount is not announced unprompted, and
741
+ // the guard compares against the last announced text rather than a mounted
742
+ // flag, so StrictMode's effect replay announces nothing either (FR6). It
743
+ // needs no cleanup of its own: on the open-sheet path `announce` starts a
744
+ // frame and a clear timer, which the sheet announcer's teardown Effect and
745
+ // the next write release.
746
+ const announcedResultCountRef = useRef(resultCountText);
671
747
  useEffect(() => {
672
- if (!hasMountedRef.current) {
673
- hasMountedRef.current = true;
748
+ if (resultCountText === announcedResultCountRef.current) {
674
749
  return;
675
750
  }
751
+ announcedResultCountRef.current = resultCountText;
676
752
  if (resultCountText != null) {
677
753
  announce(resultCountText);
678
754
  }
@@ -758,10 +834,25 @@ export function MobilePowerSearch({
758
834
  const isEditorDisabled = isDisabled || isReadOnly;
759
835
  const isSaveDisabled = isEditorDisabled || draft?.operator == null || draft.value == null;
760
836
  const isDraftRenderable = draft != null && draftField != null && draftOperator != null;
837
+
838
+ // One persistent polite region per sheet, created empty and kept mounted
839
+ // while its text changes (FR3), because the shared page-body channel is
840
+ // not exposed while a native modal dialog is open; only the active sheet's
841
+ // dialog is exposed, so a message is heard once. A polite status region
842
+ // needs no name to announce, so it carries none rather than one assembled
843
+ // from the label and a literal.
844
+ const sheetStatus = /*#__PURE__*/_jsx(VisuallyHidden, {
845
+ role: "status",
846
+ "aria-live": "polite",
847
+ "aria-atomic": "true",
848
+ "data-testid": "mobile-power-search-sheet-status",
849
+ children: sheetAnnouncement
850
+ });
761
851
  return /*#__PURE__*/_jsxs(_Fragment, {
762
852
  children: [/*#__PURE__*/_jsxs(Field, {
763
853
  ref: ref,
764
854
  label: triggerLabel,
855
+ labelID: triggerLabelId,
765
856
  isLabelHidden: isLabelHidden,
766
857
  inputID: triggerId,
767
858
  isDisabled: isDisabled,
@@ -783,6 +874,7 @@ export function MobilePowerSearch({
783
874
  "aria-disabled": isDisabled ? true : undefined,
784
875
  ...stylex.props(inputWrapperStyles.base, styles.wrapper, filters.length > 0 && styles.wrapperWithTokens, sizeStyles[size], isDisabled && inputWrapperStyles.disabled, status && inputStatusBorderStyles[status.type], status && !isDisabled && inputStatusHoverShadowStyles[status.type], status && inputStatusFocusWithinStyles[status.type]),
785
876
  children: [/*#__PURE__*/_jsxs("div", {
877
+ id: triggerContentId,
786
878
  ...{
787
879
  className: "x1n2onr6 xeuugli x1iyjqo2 x78zum5 x6s0dn4 x1a02dak x1lfs0n9 xajebq8"
788
880
  },
@@ -807,6 +899,7 @@ export function MobilePowerSearch({
807
899
  "aria-disabled": isDisabled ? true : undefined,
808
900
  "aria-haspopup": "dialog",
809
901
  "aria-expanded": step != null,
902
+ "aria-labelledby": `${triggerLabelId} ${triggerContentId}`,
810
903
  "aria-describedby": triggerDescribedBy,
811
904
  ...{
812
905
  0: {
@@ -842,7 +935,7 @@ export function MobilePowerSearch({
842
935
  ...{
843
936
  className: "x78zum5 xdt5ytf x1us19tq xc8icb0"
844
937
  },
845
- children: [/*#__PURE__*/_jsx("div", {
938
+ children: [sheetStatus, /*#__PURE__*/_jsx("div", {
846
939
  ...{
847
940
  className: "x7wzq59 x13vifvy x1vjfegm x78zum5 xdt5ytf xjcht0a x1adxfkp xvmdzux x1pzlopt x10xzikg"
848
941
  },
@@ -939,7 +1032,7 @@ export function MobilePowerSearch({
939
1032
  ...{
940
1033
  className: "x78zum5 xdt5ytf x1us19tq xc8icb0"
941
1034
  },
942
- children: [/*#__PURE__*/_jsxs("div", {
1035
+ children: [sheetStatus, /*#__PURE__*/_jsxs("div", {
943
1036
  ...{
944
1037
  className: "x7wzq59 x13vifvy x1vjfegm x78zum5 xdt5ytf xjcht0a x1adxfkp xvmdzux x1pzlopt x10xzikg"
945
1038
  },
@@ -1104,7 +1197,7 @@ export function MobilePowerSearch({
1104
1197
  ...{
1105
1198
  className: "x78zum5 xdt5ytf x1us19tq xc8icb0"
1106
1199
  },
1107
- children: [/*#__PURE__*/_jsx("div", {
1200
+ children: [sheetStatus, /*#__PURE__*/_jsx("div", {
1108
1201
  ...{
1109
1202
  className: "x7wzq59 x13vifvy x1vjfegm x78zum5 xdt5ytf xjcht0a x1adxfkp xvmdzux x1pzlopt x10xzikg"
1110
1203
  },