@astryxdesign/lab 0.7.7-canary.c0929c8 → 0.7.7-canary.c19ca12

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 (31) hide show
  1. package/dist/InfoTip/index.d.ts +21 -3
  2. package/dist/InfoTip/index.d.ts.map +1 -1
  3. package/dist/InfoTip/index.js +22 -2
  4. package/dist/MobilePowerSearch/MobilePowerSearch.d.ts.map +1 -1
  5. package/dist/MobilePowerSearch/MobilePowerSearch.js +5 -4
  6. package/dist/MobileTokenizer/MobileTokenizer.d.ts +1 -1
  7. package/dist/MobileTokenizer/MobileTokenizer.d.ts.map +1 -1
  8. package/dist/MobileTokenizer/MobileTokenizer.js +10 -37
  9. package/dist/lab.css +0 -3
  10. package/package.json +5 -5
  11. package/src/InfoTip/InfoTip.test.tsx +24 -229
  12. package/src/InfoTip/index.ts +28 -3
  13. package/src/MobilePowerSearch/MobilePowerSearch.test.tsx +11 -0
  14. package/src/MobilePowerSearch/MobilePowerSearch.tsx +18 -7
  15. package/src/MobileTokenizer/MobileTokenizer.test.tsx +6 -5
  16. package/src/MobileTokenizer/MobileTokenizer.tsx +25 -51
  17. package/dist/InfoTip/InfoTip.d.ts +0 -58
  18. package/dist/InfoTip/InfoTip.d.ts.map +0 -1
  19. package/dist/InfoTip/InfoTip.js +0 -94
  20. package/dist/internal/MobileSheetConfirmation.d.ts +0 -12
  21. package/dist/internal/MobileSheetConfirmation.d.ts.map +0 -1
  22. package/dist/internal/MobileSheetConfirmation.js +0 -88
  23. package/dist/internal/useDismissSearchOnTouchDrag.d.ts +0 -21
  24. package/dist/internal/useDismissSearchOnTouchDrag.d.ts.map +0 -1
  25. package/dist/internal/useDismissSearchOnTouchDrag.js +0 -43
  26. package/src/InfoTip/InfoTip.doc.mjs +0 -100
  27. package/src/InfoTip/InfoTip.tsx +0 -128
  28. package/src/internal/MobileSheetConfirmation.test.tsx +0 -68
  29. package/src/internal/MobileSheetConfirmation.tsx +0 -97
  30. package/src/internal/useDismissSearchOnTouchDrag.test.tsx +0 -94
  31. package/src/internal/useDismissSearchOnTouchDrag.ts +0 -57
@@ -1,6 +1,24 @@
1
1
  /**
2
- * @file InfoTip component barrel export
2
+ * @file InfoTip deprecated re-export
3
+ * @input `@astryxdesign/core/InfoTip`
4
+ * @output Exports InfoTip, InfoTipProps, InfoTipSize, each deprecated
5
+ * @position Lab entry kept for one release after InfoTip moved to Core;
6
+ * consumed by packages/lab/src/index.ts
3
7
  */
4
- export { InfoTip } from './InfoTip.js';
5
- export type { InfoTipProps, InfoTipSize } from './InfoTip.js';
8
+ import { InfoTip as CoreInfoTip, type InfoTipProps as CoreInfoTipProps, type InfoTipSize as CoreInfoTipSize } from '@astryxdesign/core/InfoTip';
9
+ /**
10
+ * @deprecated InfoTip moved to Core: import it from `@astryxdesign/core`.
11
+ * This Lab export is removed in the next release.
12
+ */
13
+ export declare const InfoTip: typeof CoreInfoTip;
14
+ /**
15
+ * @deprecated Import `InfoTipProps` from `@astryxdesign/core`. This Lab
16
+ * export is removed in the next release.
17
+ */
18
+ export type InfoTipProps = CoreInfoTipProps;
19
+ /**
20
+ * @deprecated Import `InfoTipSize` from `@astryxdesign/core`. This Lab export
21
+ * is removed in the next release.
22
+ */
23
+ export type InfoTipSize = CoreInfoTipSize;
6
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/InfoTip/index.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAClC,YAAY,EAAC,YAAY,EAAE,WAAW,EAAC,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/InfoTip/index.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,OAAO,EACL,OAAO,IAAI,WAAW,EACtB,KAAK,YAAY,IAAI,gBAAgB,EACrC,KAAK,WAAW,IAAI,eAAe,EACpC,MAAM,4BAA4B,CAAC;AAEpC;;;GAGG;AACH,eAAO,MAAM,OAAO,oBAAc,CAAC;AAEnC;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,gBAAgB,CAAC;AAE5C;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,eAAe,CAAC"}
@@ -3,6 +3,26 @@
3
3
  'use client';
4
4
 
5
5
  /**
6
- * @file InfoTip component barrel export
6
+ * @file InfoTip deprecated re-export
7
+ * @input `@astryxdesign/core/InfoTip`
8
+ * @output Exports InfoTip, InfoTipProps, InfoTipSize, each deprecated
9
+ * @position Lab entry kept for one release after InfoTip moved to Core;
10
+ * consumed by packages/lab/src/index.ts
7
11
  */
8
- export { InfoTip } from "./InfoTip.js";
12
+ import { InfoTip as CoreInfoTip } from '@astryxdesign/core/InfoTip';
13
+
14
+ /**
15
+ * @deprecated InfoTip moved to Core: import it from `@astryxdesign/core`.
16
+ * This Lab export is removed in the next release.
17
+ */
18
+ export const InfoTip = CoreInfoTip;
19
+
20
+ /**
21
+ * @deprecated Import `InfoTipProps` from `@astryxdesign/core`. This Lab
22
+ * export is removed in the next release.
23
+ */
24
+
25
+ /**
26
+ * @deprecated Import `InfoTipSize` from `@astryxdesign/core`. This Lab export
27
+ * is removed in the next release.
28
+ */
@@ -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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"}
@@ -97,8 +97,7 @@ import { useLocale, useTranslator } from '@astryxdesign/core/i18n';
97
97
  import '@astryxdesign/core/theme/tokens.stylex';
98
98
  import { colorVars, fontWeightVars, radiusVars, sizeVars, spacingVars, typeScaleVars, typographyVars } from '@astryxdesign/core/theme/tokens.stylex';
99
99
  import { isImeKeyEvent, isRenderable, rtlStyles } from '@astryxdesign/core/utils';
100
- import { MobileSheetConfirmation } from "../internal/MobileSheetConfirmation.js";
101
- import { useDismissSearchOnTouchDrag } from "../internal/useDismissSearchOnTouchDrag.js";
100
+ import { SheetConfirmation, useDismissSearchOnTouchDrag } from '@astryxdesign/core/internal/touch-sheet';
102
101
  import { MobilePowerSearchValueEditor } from "./MobilePowerSearchValueEditor.js";
103
102
  import { createContentSearchSource, createFilterIdentities, fieldMatchesQuery, filterSignature, isSupportedOperator, nearestEditableIndex, resolveFilterIdentityIndex, useMobilePowerSearchConfig } from "./mobilePowerSearchUtils.js";
104
103
 
@@ -493,7 +492,9 @@ export function MobilePowerSearch({
493
492
 
494
493
  // ------------------------------------------------------------------ focus --
495
494
 
496
- const fieldPickerDragProps = useDismissSearchOnTouchDrag(() => [contentSearchRef.current?.querySelector('input'), fieldSearchRef.current?.querySelector('input')]);
495
+ // A drag moves focus to the sheet's panel, never to the page body behind
496
+ // the open modal.
497
+ const fieldPickerDragProps = useDismissSearchOnTouchDrag(() => [contentSearchRef.current?.querySelector('input'), fieldSearchRef.current?.querySelector('input')], () => (fieldSearchRef.current ?? contentSearchRef.current)?.closest('[tabindex="-1"]'));
497
498
  const focusPendingSheetTarget = useCallback(() => {
498
499
  const target = pendingSheetFocusRef.current;
499
500
  if (target == null) {
@@ -1721,7 +1722,7 @@ export function MobilePowerSearch({
1721
1722
  })]
1722
1723
  })]
1723
1724
  })
1724
- }), /*#__PURE__*/_jsx(MobileSheetConfirmation, {
1725
+ }), /*#__PURE__*/_jsx(SheetConfirmation, {
1725
1726
  isOpen: isClearConfirmationOpen,
1726
1727
  onOpenChange: setIsClearConfirmationOpen,
1727
1728
  title: "Clear all filters?",
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @file MobileTokenizer.tsx
3
3
  * @input Public @astryxdesign/core components and hooks, plus private Lab
4
- * mobile-sheet confirmation and search-drag dismissal owners
4
+ * touch-sheet confirmation and search-drag dismissal from Core's internal entry
5
5
  * @output Exports MobileTokenizer — Lab prototype of the touch Tokenizer
6
6
  * flow with the inline-compatible closed trigger, a searchable draft-selection
7
7
  * sheet, persistent Clear all / Save footer, dirty-dismiss confirmation,
@@ -1 +1 @@
1
- {"version":3,"file":"MobileTokenizer.d.ts","sourceRoot":"","sources":["../../src/MobileTokenizer/MobileTokenizer.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EASL,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAclD,OAAO,KAAK,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,8BAA8B,CAAC;AAY/E,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,cAAc,IACtD;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAC,GACtB;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAC,GACzB;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAC,GACzB;IAAC,IAAI,EAAE,SAAS,CAAA;CAAC,CAAC;AAEtB,MAAM,WAAW,oBAAoB,CAAC,CAAC,SAAS,cAAc,CAAE,SAAQ,IAAI,CAC1E,SAAS,CAAC,cAAc,CAAC,EACzB,UAAU,CACX;IACC,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAC9B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IACjE;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8DAA8D;IAC9D,MAAM,CAAC,EAAE;QAAC,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAC;IAClE;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAoMD,wBAAgB,eAAe,CAAC,CAAC,SAAS,cAAc,EAAE,EACxD,KAAK,EACL,aAAa,EACb,YAAY,EACZ,KAAK,EACL,QAAQ,EACR,UAAU,EACV,WAAW,EACX,WAAW,EACX,MAAM,EACN,eAAe,EACf,QAAQ,EACR,UAAU,EACV,UAAkB,EAClB,SAAiB,EACjB,UAAU,EACV,YAAiB,EACjB,cAAkB,EAClB,UAAgB,EAChB,sBAAsB,EACtB,aAAa,EACb,MAAM,EACN,EAAE,EACF,SAAS,EACT,KAAK,EACL,YAAY,EAAE,aAAa,EAC3B,kBAAkB,EAAE,mBAAmB,EACvC,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,YAAY,EACpB,GAAG,IAAI,EACR,EAAE,oBAAoB,CAAC,CAAC,CAAC,qBAwPzB;yBAvRe,eAAe"}
1
+ {"version":3,"file":"MobileTokenizer.d.ts","sourceRoot":"","sources":["../../src/MobileTokenizer/MobileTokenizer.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EASL,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAclD,OAAO,KAAK,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,8BAA8B,CAAC;AAiB/E,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,cAAc,IACtD;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAC,GACtB;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAC,GACzB;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAC,GACzB;IAAC,IAAI,EAAE,SAAS,CAAA;CAAC,CAAC;AAEtB,MAAM,WAAW,oBAAoB,CAAC,CAAC,SAAS,cAAc,CAAE,SAAQ,IAAI,CAC1E,SAAS,CAAC,cAAc,CAAC,EACzB,UAAU,CACX;IACC,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAC9B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IACjE;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8DAA8D;IAC9D,MAAM,CAAC,EAAE;QAAC,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAC;IAClE;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAwLD,wBAAgB,eAAe,CAAC,CAAC,SAAS,cAAc,EAAE,EACxD,KAAK,EACL,aAAa,EACb,YAAY,EACZ,KAAK,EACL,QAAQ,EACR,UAAU,EACV,WAAW,EACX,WAAW,EACX,MAAM,EACN,eAAe,EACf,QAAQ,EACR,UAAU,EACV,UAAkB,EAClB,SAAiB,EACjB,UAAU,EACV,YAAiB,EACjB,cAAkB,EAClB,UAAgB,EAChB,sBAAsB,EACtB,aAAa,EACb,MAAM,EACN,EAAE,EACF,SAAS,EACT,KAAK,EACL,YAAY,EAAE,aAAa,EAC3B,kBAAkB,EAAE,mBAAmB,EACvC,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,YAAY,EACpB,GAAG,IAAI,EACR,EAAE,oBAAoB,CAAC,CAAC,CAAC,qBAwPzB;yBAvRe,eAAe"}
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * @file MobileTokenizer.tsx
7
7
  * @input Public @astryxdesign/core components and hooks, plus private Lab
8
- * mobile-sheet confirmation and search-drag dismissal owners
8
+ * touch-sheet confirmation and search-drag dismissal from Core's internal entry
9
9
  * @output Exports MobileTokenizer — Lab prototype of the touch Tokenizer
10
10
  * flow with the inline-compatible closed trigger, a searchable draft-selection
11
11
  * sheet, persistent Clear all / Save footer, dirty-dismiss confirmation,
@@ -53,8 +53,7 @@ import { composeEventHandlers, mergeProps } from '@astryxdesign/core/utils';
53
53
  import { VisuallyHidden } from '@astryxdesign/core/VisuallyHidden';
54
54
  import '@astryxdesign/core/theme/tokens.stylex';
55
55
  import { colorVars, radiusVars, sizeVars, spacingVars } from '@astryxdesign/core/theme/tokens.stylex';
56
- import { MobileSheetConfirmation } from "../internal/MobileSheetConfirmation.js";
57
- import { useDismissSearchOnTouchDrag } from "../internal/useDismissSearchOnTouchDrag.js";
56
+ import { SheetConfirmation, hasSameSelection, nameSheetDraftChange, useDismissSearchOnTouchDrag } from '@astryxdesign/core/internal/touch-sheet';
58
57
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
59
58
  const CREATABLE_ID_PREFIX = '__xds_create__';
60
59
  const LIST_RENDER_BATCH_SIZE = 50;
@@ -64,9 +63,6 @@ const LIST_LOAD_MORE_THRESHOLD_PX = 200;
64
63
  // concentric with the field's (radius-2) when inset = radius-2 − radius-1 −
65
64
  // border = 3px. The same number is the row gap, so wrapped rows read evenly.
66
65
  const TOKEN_ROW_INSET = `calc(${spacingVars['--spacing-1']} - 1px)`;
67
- function hasSameSelection(a, b) {
68
- return a.length === b.length && a.every(item => b.some(candidate => candidate.id === item.id));
69
- }
70
66
  const styles = {
71
67
  trigger: {
72
68
  kzqmXN: "xh8yej3",
@@ -657,34 +653,9 @@ function MobileTokenizerSheetContent({
657
653
  if (isDraftOverMax) {
658
654
  return;
659
655
  }
660
- if (isDraftDirty) {
661
- const added = draftValue.find(item => !valueAtOpen.some(openItem => openItem.id === item.id));
662
- const removed = valueAtOpen.find(item => !draftValue.some(draftItem => draftItem.id === item.id));
663
- const lastDraftChange = lastDraftChangeRef.current;
664
- const lastChangeIsNet = lastDraftChange != null && (lastDraftChange.type === 'remove' ? valueAtOpen.some(item => item.id === lastDraftChange.item.id) && !draftValue.some(item => item.id === lastDraftChange.item.id) : draftValue.some(item => item.id === lastDraftChange.item.id) && !valueAtOpen.some(item => item.id === lastDraftChange.item.id));
665
- let change = null;
666
- if (lastChangeIsNet) {
667
- change = lastDraftChange;
668
- } else if (lastDraftChange?.type === 'remove' && removed != null) {
669
- change = {
670
- item: removed,
671
- type: 'remove'
672
- };
673
- } else if (added != null) {
674
- const type = lastDraftChange?.item.id === added.id && lastDraftChange.type === 'create' ? 'create' : 'add';
675
- change = {
676
- item: added,
677
- type
678
- };
679
- } else if (removed != null) {
680
- change = {
681
- item: removed,
682
- type: 'remove'
683
- };
684
- }
685
- if (change != null) {
686
- onCommit([...draftValue], change);
687
- }
656
+ const change = isDraftDirty ? nameSheetDraftChange(valueAtOpen, draftValue, lastDraftChangeRef.current) : null;
657
+ if (change != null) {
658
+ onCommit([...draftValue], change);
688
659
  }
689
660
  onCloseSheet();
690
661
  };
@@ -692,7 +663,9 @@ function MobileTokenizerSheetContent({
692
663
  label
693
664
  });
694
665
  const noResultsTitle = emptySearchResultsText ?? t('@astryx.typeahead.emptySearchResults');
695
- const listDragProps = useDismissSearchOnTouchDrag(() => [searchRef.current]);
666
+ // A drag moves focus to the sheet's panel, never to the page body behind
667
+ // the open modal.
668
+ const listDragProps = useDismissSearchOnTouchDrag(() => [searchRef.current], () => searchRef.current?.closest('[tabindex="-1"]'));
696
669
  return /*#__PURE__*/_jsxs("div", {
697
670
  ...{
698
671
  className: "x78zum5 xdt5ytf x5yr21d x2lwn1j xrrkdod xoxd1wu xvmdzux"
@@ -881,7 +854,7 @@ function MobileTokenizerSheetContent({
881
854
  onClick: handleSave,
882
855
  xstyle: styles.footerAction
883
856
  })]
884
- }), isClearConfirmationOpen && /*#__PURE__*/_jsx(MobileSheetConfirmation, {
857
+ }), isClearConfirmationOpen && /*#__PURE__*/_jsx(SheetConfirmation, {
885
858
  isOpen: true,
886
859
  onOpenChange: next => {
887
860
  if (!next) {
@@ -905,7 +878,7 @@ function MobileTokenizerSheetContent({
905
878
  }
906
879
  closeClearConfirmation(true);
907
880
  }
908
- }), isDiscardConfirmationOpen && /*#__PURE__*/_jsx(MobileSheetConfirmation, {
881
+ }), isDiscardConfirmationOpen && /*#__PURE__*/_jsx(SheetConfirmation, {
909
882
  isOpen: true,
910
883
  onOpenChange: next => {
911
884
  if (!next) {
package/dist/lab.css CHANGED
@@ -71,7 +71,6 @@
71
71
  .x1fx55se:not(#\#){padding:calc((var(--size-element-lg) - 28px) / 2 - var(--border-width))}
72
72
  .xnvfkzk:not(#\#){padding:calc((var(--size-element-md) - 24px) / 2 - var(--border-width))}
73
73
  .x5pt662:not(#\#){padding:calc((var(--size-element-sm) - 22px) / 2 - var(--border-width))}
74
- .x12nba7r:not(#\#){padding:var(--spacing-0-5)}
75
74
  .x1b2ylru:not(#\#){padding:var(--spacing-3)}
76
75
  .x1shk3sm:not(#\#){padding:var(--spacing-4)}
77
76
  .x70o2i5:not(#\#):not(#\#){border-color:#26262a}
@@ -563,7 +562,6 @@
563
562
  .x80gvsz:not(#\#):not(#\#):not(#\#){transition-duration:var(--duration-medium)}
564
563
  .x15406qy:not(#\#):not(#\#):not(#\#){transition-property:background-color}
565
564
  .xq90yva:not(#\#):not(#\#):not(#\#){transition-property:border-color,background-color}
566
- .xt3l3uh:not(#\#):not(#\#):not(#\#){transition-property:color}
567
565
  .x13b0p5u:not(#\#):not(#\#):not(#\#){transition-property:none}
568
566
  .x19991ni:not(#\#):not(#\#):not(#\#){transition-property:opacity}
569
567
  .x1gfj591:not(#\#):not(#\#):not(#\#){transition-property:top,left,width,height}
@@ -635,7 +633,6 @@
635
633
  @media (hover: hover){.x1fkayqs.x1fkayqs.x1fkayqs:hover:where(:not(:disabled,[aria-disabled="true"])):not(#\#):not(#\#):not(#\#){background-color:#1d1d21}}
636
634
  @media (hover: hover){.xkqrm7g.xkqrm7g.xkqrm7g:hover:where(:not(:disabled,[aria-disabled="true"])):not(#\#):not(#\#):not(#\#){background-color:var(--color-background-muted)}}
637
635
  @media (hover: hover){.xoevpu5.xoevpu5.xoevpu5:hover:where(:not(:disabled,[aria-disabled="true"])):not(#\#):not(#\#):not(#\#){background-color:var(--color-overlay-hover)}}
638
- @media (hover: hover){.x10ue8fs.x10ue8fs.x10ue8fs:hover:where(:not(:disabled,[aria-disabled="true"])):not(#\#):not(#\#):not(#\#){color:var(--color-icon-primary)}}
639
636
  @container (max-width: 40rem){.x101j7pr.x101j7pr:not(#\#):not(#\#):not(#\#){background-color:var(--color-background-body)}}
640
637
  @container (max-width: 40rem){.x12eanku.x12eanku:not(#\#):not(#\#):not(#\#){border-inline-start-width:0}}
641
638
  @container list-input (max-width: 640px){.x1jiamoa.x1jiamoa:not(#\#):not(#\#):not(#\#){display:block}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/lab",
3
- "version": "0.7.7-canary.c0929c8",
3
+ "version": "0.7.7-canary.c19ca12",
4
4
  "description": "Experimental Astryx components — published to npm only under the @canary dist-tag for early testing; never released as a stable (latest) version.",
5
5
  "author": "Meta Open Source",
6
6
  "license": "MIT",
@@ -49,7 +49,7 @@
49
49
  },
50
50
  "peerDependencies": {
51
51
  "@stylexjs/stylex": ">=0.10.0",
52
- "@astryxdesign/core": "0.7.7-canary.c0929c8",
52
+ "@astryxdesign/core": "0.7.7-canary.c19ca12",
53
53
  "react": ">=19.0.0",
54
54
  "react-dom": ">=19.0.0"
55
55
  },
@@ -59,9 +59,9 @@
59
59
  "d3-shape": "^3.2.0"
60
60
  },
61
61
  "devDependencies": {
62
- "@astryxdesign/a11y-spec": "0.7.7-canary.c0929c8",
63
- "@astryxdesign/cli": "0.7.7-canary.c0929c8",
64
- "@astryxdesign/interaction-harness": "0.7.7-canary.c0929c8",
62
+ "@astryxdesign/a11y-spec": "0.7.7-canary.c19ca12",
63
+ "@astryxdesign/cli": "0.7.7-canary.c19ca12",
64
+ "@astryxdesign/interaction-harness": "0.7.7-canary.c19ca12",
65
65
  "@babel/cli": "^7.29.7",
66
66
  "@babel/core": "^7.29.7",
67
67
  "@babel/preset-react": "^7.29.7",
@@ -2,237 +2,32 @@
2
2
 
3
3
  /**
4
4
  * @file InfoTip.test.tsx
5
- * @input Uses vitest, @testing-library/react, @testing-library/user-event, InfoTip component
6
- * @output Unit tests for InfoTip trigger accessibility and tooltip behavior
7
- * @position Testing; validates InfoTip.tsx implementation
8
- *
9
- * SYNC: When InfoTip.tsx changes, update tests to match new behavior
5
+ * @input The Lab InfoTip entry and the Core component
6
+ * @output Tests that the Lab entry re-exports the Core component, deprecated
7
+ * @position Testing; validates index.ts (component:InfoTip FR4)
10
8
  */
11
9
 
12
- import {describe, it, expect, vi, beforeAll, afterAll} from 'vitest';
13
- import {render, screen, fireEvent, waitFor, act} from '@testing-library/react';
14
- import userEvent from '@testing-library/user-event';
15
- import {InfoTip} from './InfoTip';
16
-
17
- // Store original matches to restore later
18
- const originalMatches = HTMLElement.prototype.matches;
19
-
20
- // Track popover open state per element
21
- const popoverOpenState = new WeakMap<HTMLElement, boolean>();
22
-
23
- // Mock Popover API for jsdom, and :focus-visible for keyboard-focus tests
24
- // (same harness as core Tooltip.test.tsx, plus :focus-visible)
25
- beforeAll(() => {
26
- HTMLElement.prototype.showPopover = vi.fn(function (this: HTMLElement) {
27
- popoverOpenState.set(this, true);
28
- });
29
- HTMLElement.prototype.hidePopover = vi.fn(function (this: HTMLElement) {
30
- popoverOpenState.set(this, false);
31
- });
32
-
33
- // Intercept :popover-open and :focus-visible, delegate everything else
34
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
- (HTMLElement.prototype as any).matches = function (
36
- selector: string,
37
- ): boolean {
38
- if (selector === ':popover-open') {
39
- return popoverOpenState.get(this) ?? false;
40
- }
41
- if (selector === ':focus-visible') {
42
- // Treat any focused element as keyboard-focused in tests
43
- return this === document.activeElement;
10
+ import {readFileSync} from 'node:fs';
11
+ import path from 'node:path';
12
+ import {describe, expect, it} from 'vitest';
13
+ import {InfoTip as CoreInfoTip} from '@astryxdesign/core/InfoTip';
14
+ import {InfoTip} from './index';
15
+
16
+ describe('Lab InfoTip', () => {
17
+ it('is the Core component', () => {
18
+ expect(InfoTip).toBe(CoreInfoTip);
19
+ });
20
+
21
+ it('marks each of its exports deprecated', () => {
22
+ // Static metadata only: editors and type checkers show it, and nothing
23
+ // warns at runtime.
24
+ const source = readFileSync(path.join(__dirname, 'index.ts'), 'utf8');
25
+ for (const name of ['InfoTip', 'InfoTipProps', 'InfoTipSize']) {
26
+ // The doc comment right above the export, whatever it contains.
27
+ const comment = new RegExp(
28
+ String.raw`/\*\*((?:(?!\*/)[\s\S])*)\*/\nexport (?:const|type) ${name}\b`,
29
+ ).exec(source);
30
+ expect(comment?.[1], name).toContain('@deprecated');
44
31
  }
45
- return originalMatches.call(this, selector);
46
- };
47
- });
48
-
49
- afterAll(() => {
50
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
51
- (HTMLElement.prototype as any).matches = originalMatches;
52
- });
53
-
54
- /** Focus the trigger the way a keyboard user would land on it. */
55
- function focusTrigger(trigger: HTMLElement) {
56
- act(() => {
57
- trigger.focus();
58
- });
59
- fireEvent.focusIn(trigger);
60
- }
61
-
62
- describe('InfoTip', () => {
63
- it('renders a button trigger with the default accessible name', () => {
64
- render(<InfoTip content="Helpful context" />);
65
- expect(
66
- screen.getByRole('button', {name: 'More information'}),
67
- ).toBeInTheDocument();
68
- });
69
-
70
- it('uses a custom label as the accessible name', () => {
71
- render(
72
- <InfoTip content="30-day rolling average." label="About this metric" />,
73
- );
74
- const trigger = screen.getByRole('button', {name: 'About this metric'});
75
- expect(trigger).toHaveAttribute('aria-label', 'About this metric');
76
- });
77
-
78
- it('links the trigger to the tooltip layer via aria-describedby', () => {
79
- render(<InfoTip content="Helpful context" />);
80
- const layer = screen.getByRole('tooltip', {hidden: true});
81
- expect(layer).toHaveTextContent('Helpful context');
82
- const trigger = screen.getByRole('button', {name: 'More information'});
83
- expect(trigger.getAttribute('aria-describedby')).toBe(layer.id);
84
- });
85
-
86
- it('is reachable with Tab', async () => {
87
- const user = userEvent.setup();
88
- render(<InfoTip content="Helpful context" />);
89
- const trigger = screen.getByRole('button', {name: 'More information'});
90
- await user.tab();
91
- expect(trigger).toHaveFocus();
92
- });
93
-
94
- it('shows the tooltip on hover', async () => {
95
- vi.mocked(HTMLElement.prototype.showPopover).mockClear();
96
- render(<InfoTip content="Helpful context" />);
97
- const trigger = screen.getByRole('button', {name: 'More information'});
98
-
99
- fireEvent.mouseEnter(trigger);
100
-
101
- await waitFor(() => {
102
- expect(HTMLElement.prototype.showPopover).toHaveBeenCalled();
103
- });
104
- });
105
-
106
- it('shows the tooltip on keyboard focus', async () => {
107
- vi.mocked(HTMLElement.prototype.showPopover).mockClear();
108
- render(<InfoTip content="Helpful context" />);
109
- const trigger = screen.getByRole('button', {name: 'More information'});
110
-
111
- focusTrigger(trigger);
112
-
113
- await waitFor(() => {
114
- expect(HTMLElement.prototype.showPopover).toHaveBeenCalled();
115
- });
116
- const layer = screen.getByRole('tooltip', {hidden: true});
117
- expect(popoverOpenState.get(layer)).toBe(true);
118
- });
119
-
120
- it('closes the tooltip on Escape', async () => {
121
- render(<InfoTip content="Helpful context" />);
122
- const trigger = screen.getByRole('button', {name: 'More information'});
123
- const layer = screen.getByRole('tooltip', {hidden: true});
124
-
125
- focusTrigger(trigger);
126
- await waitFor(() => {
127
- expect(popoverOpenState.get(layer)).toBe(true);
128
- });
129
-
130
- fireEvent.keyDown(trigger, {key: 'Escape'});
131
-
132
- await waitFor(() => {
133
- expect(popoverOpenState.get(layer)).toBe(false);
134
- });
135
- });
136
-
137
- it('re-opens after Escape once the trigger is left and re-hovered', async () => {
138
- render(<InfoTip content="Helpful context" />);
139
- const trigger = screen.getByRole('button', {name: 'More information'});
140
- const layer = screen.getByRole('tooltip', {hidden: true});
141
-
142
- focusTrigger(trigger);
143
- await waitFor(() => {
144
- expect(popoverOpenState.get(layer)).toBe(true);
145
- });
146
-
147
- fireEvent.keyDown(trigger, {key: 'Escape'});
148
- await waitFor(() => {
149
- expect(popoverOpenState.get(layer)).toBe(false);
150
- });
151
-
152
- // Leave (resets dismissal), then re-enter
153
- act(() => {
154
- trigger.blur();
155
- });
156
- fireEvent.focusOut(trigger);
157
- fireEvent.mouseLeave(trigger);
158
-
159
- fireEvent.mouseEnter(trigger);
160
- await waitFor(() => {
161
- expect(popoverOpenState.get(layer)).toBe(true);
162
- });
163
- });
164
-
165
- it('renders ReactNode tooltip content', () => {
166
- render(<InfoTip content={<span data-testid="rich-content">Rich</span>} />);
167
- expect(screen.getByTestId('rich-content')).toBeInTheDocument();
168
- });
169
- describe('touch', () => {
170
- /**
171
- * A tap, in the order a browser dispatches it: the finger's pointer events,
172
- * the hover it synthesizes, then the `click` that says the touch was a tap.
173
- */
174
- const tap = (element: HTMLElement) => {
175
- fireEvent.pointerEnter(element, {pointerType: 'touch'});
176
- fireEvent.pointerDown(element, {pointerType: 'touch'});
177
- fireEvent.pointerUp(element, {pointerType: 'touch'});
178
- fireEvent.mouseEnter(element);
179
- fireEvent.click(element);
180
- };
181
-
182
- it('opens on a tap, though the trigger is a button', async () => {
183
- render(<InfoTip content="30-day rolling average." />);
184
- const trigger = screen.getByRole('button');
185
- const layer = screen.getByRole('tooltip', {hidden: true});
186
-
187
- // Tooltip's `auto` rule would give this tap to the button and suppress
188
- // the tooltip; revealing it is the button's whole purpose, so InfoTip
189
- // opts in. Without this its content is unreachable on a phone.
190
- tap(trigger);
191
-
192
- await waitFor(() => {
193
- expect(popoverOpenState.get(layer)).toBe(true);
194
- });
195
- });
196
-
197
- it('closes on a second tap of the trigger', async () => {
198
- render(<InfoTip content="30-day rolling average." />);
199
- const trigger = screen.getByRole('button');
200
- const layer = screen.getByRole('tooltip', {hidden: true});
201
-
202
- tap(trigger);
203
- await waitFor(() => {
204
- expect(popoverOpenState.get(layer)).toBe(true);
205
- });
206
-
207
- tap(trigger);
208
- await waitFor(() => {
209
- expect(popoverOpenState.get(layer)).toBe(false);
210
- });
211
- });
212
-
213
- it('closes on a tap outside', async () => {
214
- render(
215
- <>
216
- <InfoTip content="30-day rolling average." />
217
- <button type="button">Elsewhere</button>
218
- </>,
219
- );
220
- const trigger = screen.getByRole('button', {name: 'More information'});
221
- const layer = screen.getByRole('tooltip', {hidden: true});
222
-
223
- tap(trigger);
224
- await waitFor(() => {
225
- expect(popoverOpenState.get(layer)).toBe(true);
226
- });
227
-
228
- // The tap outside counts when the finger lifts.
229
- const elsewhere = screen.getByRole('button', {name: 'Elsewhere'});
230
- fireEvent.pointerDown(elsewhere, {pointerType: 'touch'});
231
- fireEvent.pointerUp(elsewhere, {pointerType: 'touch'});
232
-
233
- await waitFor(() => {
234
- expect(popoverOpenState.get(layer)).toBe(false);
235
- });
236
- });
237
32
  });
238
33
  });
@@ -3,8 +3,33 @@
3
3
  'use client';
4
4
 
5
5
  /**
6
- * @file InfoTip component barrel export
6
+ * @file InfoTip deprecated re-export
7
+ * @input `@astryxdesign/core/InfoTip`
8
+ * @output Exports InfoTip, InfoTipProps, InfoTipSize, each deprecated
9
+ * @position Lab entry kept for one release after InfoTip moved to Core;
10
+ * consumed by packages/lab/src/index.ts
7
11
  */
8
12
 
9
- export {InfoTip} from './InfoTip';
10
- export type {InfoTipProps, InfoTipSize} from './InfoTip';
13
+ import {
14
+ InfoTip as CoreInfoTip,
15
+ type InfoTipProps as CoreInfoTipProps,
16
+ type InfoTipSize as CoreInfoTipSize,
17
+ } from '@astryxdesign/core/InfoTip';
18
+
19
+ /**
20
+ * @deprecated InfoTip moved to Core: import it from `@astryxdesign/core`.
21
+ * This Lab export is removed in the next release.
22
+ */
23
+ export const InfoTip = CoreInfoTip;
24
+
25
+ /**
26
+ * @deprecated Import `InfoTipProps` from `@astryxdesign/core`. This Lab
27
+ * export is removed in the next release.
28
+ */
29
+ export type InfoTipProps = CoreInfoTipProps;
30
+
31
+ /**
32
+ * @deprecated Import `InfoTipSize` from `@astryxdesign/core`. This Lab export
33
+ * is removed in the next release.
34
+ */
35
+ export type InfoTipSize = CoreInfoTipSize;
@@ -822,6 +822,9 @@ describe('MobilePowerSearch Filters sheet', () => {
822
822
  const confirmation = screen.getByRole('alertdialog', {
823
823
  name: 'Clear all filters?',
824
824
  });
825
+ // A scrim press starts and ends on the dialog itself.
826
+ fireEvent.pointerDown(confirmation);
827
+ fireEvent.pointerUp(confirmation);
825
828
  fireEvent.click(confirmation);
826
829
  expect(
827
830
  screen.queryByRole('alertdialog', {name: 'Clear all filters?'}),
@@ -1856,6 +1859,10 @@ describe('MobilePowerSearch content search', () => {
1856
1859
  expect(
1857
1860
  within(sheet()).getByRole('heading', {name: 'Filters'}),
1858
1861
  ).toBeTruthy();
1862
+ // The search sheet held focus as it closed, so words sent with the close
1863
+ // wait for its exit to end (component:BottomSheet FR9, spec:AST-086
1864
+ // FR14); settle that exit.
1865
+ act(() => settleSheets());
1859
1866
  // The add is announced inside the sheet the flow is now on, not on the
1860
1867
  // page body, which assistive technology does not expose under a native
1861
1868
  // modal dialog.
@@ -1890,6 +1897,10 @@ describe('MobilePowerSearch content search', () => {
1890
1897
  within(sheet()).getByRole('button', {name: '"release notes"'}),
1891
1898
  );
1892
1899
  await waitFor(() => expect(isSheetOpen()).toBe(true));
1900
+ // The search sheet held focus as it closed, so words sent with the close
1901
+ // wait for its exit to end (component:BottomSheet FR9, spec:AST-086
1902
+ // FR14); settle that exit.
1903
+ act(() => settleSheets());
1893
1904
  await waitFor(() =>
1894
1905
  expect(sheetRegion().textContent).toBe(
1895
1906
  'Added "release notes" 20 results',