@astryxdesign/core 0.7.7-canary.fc68123 → 0.7.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +104 -0
- package/dist/AlertDialog/AlertDialog.d.ts +1 -4
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +6 -36
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +4 -23
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
- package/dist/BottomSheet/useSheetGestures.js +1 -3
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +1 -17
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +2 -13
- package/dist/ComplexSelector/ComplexSelector.d.ts +1 -4
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +4 -14
- package/dist/ContextMenu/ContextMenu.js +2 -2
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +31 -7
- package/dist/Field/Field.js +2 -2
- package/dist/HoverCard/HoverCard.d.ts +3 -4
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +2 -27
- package/dist/HoverCard/useHoverCard.d.ts +4 -5
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +31 -17
- package/dist/Icon/Icon.d.ts +1 -5
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +2 -5
- package/dist/Layer/usePressPin.d.ts +5 -17
- package/dist/Layer/usePressPin.d.ts.map +1 -1
- package/dist/Layer/usePressPin.js +12 -62
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +0 -18
- package/dist/PowerSearch/PowerSearch.d.ts +3 -36
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +127 -433
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts +1 -32
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +6 -17
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts +3 -38
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +61 -170
- package/dist/PowerSearch/formatFilterValue.d.ts +0 -7
- package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
- package/dist/PowerSearch/formatFilterValue.js +1 -11
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +2 -3
- package/dist/RadioList/RadioListItem.d.ts +1 -1
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +3 -5
- package/dist/Resizable/ResizeHandle.d.ts +1 -2
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +77 -99
- package/dist/SegmentedControl/useSegmentedSelectionMotion.d.ts.map +1 -1
- package/dist/SegmentedControl/useSegmentedSelectionMotion.js +3 -3
- package/dist/Slider/sliderTouchController.js +2 -2
- package/dist/Spinner/Spinner.d.ts +1 -1
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +58 -60
- package/dist/Switch/useSwitchTouch.js +4 -4
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +8 -29
- package/dist/TextInput/TextInput.d.ts +2 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +7 -10
- package/dist/Toast/Toast.d.ts +1 -11
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +15 -25
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +34 -94
- package/dist/Toast/types.d.ts +3 -9
- package/dist/Toast/types.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.d.ts +1 -19
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +53 -34
- package/dist/Typeahead/TypeaheadItem.d.ts +1 -2
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/astryx.css +6 -35
- package/dist/gestures/PressTracker.d.ts.map +1 -1
- package/dist/gestures/PressTracker.js +3 -4
- package/dist/hooks/actionGroupTracker.d.ts +1 -4
- package/dist/hooks/actionGroupTracker.d.ts.map +1 -1
- package/dist/hooks/actionGroupTracker.js +3 -13
- package/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +0 -1
- package/dist/hooks/useAttachment.d.ts +1 -1
- package/dist/hooks/useAttachment.js +1 -1
- package/dist/hooks/useInputStatusIcon.d.ts +1 -1
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
- package/dist/hooks/useInputStatusIcon.js +2 -2
- package/dist/hooks/useLongPress.d.ts +2 -6
- package/dist/hooks/useLongPress.d.ts.map +1 -1
- package/dist/hooks/useLongPress.js +15 -95
- package/dist/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.d.ts.map +1 -1
- package/dist/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.js +0 -6
- package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/en.generated.js +0 -30
- package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pseudo.generated.js +0 -30
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -4
- package/dist/motion/animatedLayout.d.ts.map +1 -1
- package/dist/motion/animatedLayout.js +6 -5
- package/dist/motion/animator.d.ts +14 -14
- package/dist/motion/animator.d.ts.map +1 -1
- package/dist/motion/animator.js +18 -41
- package/dist/utils/dateParser.d.ts.map +1 -1
- package/dist/utils/dateParser.js +0 -12
- package/dist/utils/focusReturn.d.ts +0 -15
- package/dist/utils/focusReturn.d.ts.map +1 -1
- package/dist/utils/focusReturn.js +0 -28
- package/dist/utils/interactionOverlay.stylex.d.ts +2 -3
- package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
- package/dist/utils/interactionOverlay.stylex.js +2 -3
- package/dist/utils/pressFeedback.d.ts.map +1 -1
- package/dist/utils/pressFeedback.js +6 -19
- package/locales/en.json +0 -120
- package/locales/pseudo.json +0 -90
- package/package.json +5 -10
- package/src/AlertDialog/AlertDialog.doc.mjs +2 -2
- package/src/AlertDialog/AlertDialog.tsx +5 -37
- package/src/BottomSheet/BottomSheetPanel.tsx +3 -37
- package/src/BottomSheet/useSheetGestures.ts +1 -3
- package/src/Button/Button.tsx +4 -26
- package/src/CheckboxInput/CheckboxInput.doc.mjs +0 -18
- package/src/CheckboxInput/CheckboxInput.tsx +9 -36
- package/src/ComplexSelector/ComplexSelector.tsx +5 -20
- package/src/ContextMenu/ContextMenu.tsx +2 -2
- package/src/Dialog/Dialog.tsx +31 -10
- package/src/Field/Field.tsx +2 -2
- package/src/HoverCard/HoverCard.doc.mjs +2 -4
- package/src/HoverCard/HoverCard.tsx +4 -35
- package/src/HoverCard/useHoverCard.doc.mjs +36 -178
- package/src/HoverCard/useHoverCard.tsx +52 -46
- package/src/Icon/Icon.doc.mjs +8 -49
- package/src/Icon/Icon.tsx +7 -15
- package/src/Layer/usePressPin.ts +15 -81
- package/src/Lightbox/Lightbox.tsx +0 -18
- package/src/PowerSearch/PowerSearch.doc.mjs +5 -54
- package/src/PowerSearch/PowerSearch.tsx +155 -609
- package/src/PowerSearch/PowerSearchEditPopover.tsx +6 -28
- package/src/PowerSearch/PowerSearchValueEditor.tsx +38 -203
- package/src/PowerSearch/formatFilterValue.ts +1 -18
- package/src/RadioList/RadioList.tsx +2 -3
- package/src/RadioList/RadioListItem.tsx +3 -5
- package/src/Resizable/Resizable.doc.mjs +4 -5
- package/src/Resizable/ResizeHandle.tsx +109 -167
- package/src/SegmentedControl/useSegmentedSelectionMotion.ts +3 -6
- package/src/Slider/sliderTouchController.ts +2 -2
- package/src/Spinner/Spinner.tsx +63 -77
- package/src/Switch/useSwitchTouch.ts +4 -4
- package/src/Table/BaseTable.tsx +12 -46
- package/src/TextInput/TextInput.tsx +10 -11
- package/src/Toast/Toast.doc.mjs +3 -4
- package/src/Toast/Toast.tsx +32 -52
- package/src/Toast/ToastViewport.tsx +35 -121
- package/src/Toast/types.ts +3 -9
- package/src/Tooltip/useTooltip.doc.mjs +0 -24
- package/src/Tooltip/useTooltip.tsx +56 -61
- package/src/Typeahead/TypeaheadItem.doc.mjs +3 -6
- package/src/Typeahead/TypeaheadItem.tsx +1 -2
- package/src/gestures/PressTracker.ts +3 -4
- package/src/gestures/README.md +1 -7
- package/src/hooks/actionGroupTracker.ts +5 -20
- package/src/hooks/index.ts +0 -2
- package/src/hooks/useAttachment.ts +1 -1
- package/src/hooks/useInputStatusIcon.tsx +2 -3
- package/src/hooks/useLongPress.doc.mjs +2 -2
- package/src/hooks/useLongPress.ts +15 -136
- package/src/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.ts +0 -6
- package/src/i18n/generated-locales/en.generated.ts +0 -41
- package/src/i18n/generated-locales/pseudo.generated.ts +0 -42
- package/src/index.ts +0 -13
- package/src/motion/README.md +5 -9
- package/src/motion/animatedLayout.ts +4 -5
- package/src/motion/animator.ts +29 -61
- package/src/utils/dateParser.ts +0 -16
- package/src/utils/focusReturn.ts +0 -30
- package/src/utils/interactionOverlay.stylex.ts +2 -3
- package/src/utils/pressFeedback.ts +6 -19
- package/dist/PowerSearch/PowerSearchBottomSheet.d.ts +0 -100
- package/dist/PowerSearch/PowerSearchBottomSheet.d.ts.map +0 -1
- package/dist/PowerSearch/PowerSearchBottomSheet.js +0 -1913
- package/dist/PowerSearch/formatTokenValue.d.ts +0 -28
- package/dist/PowerSearch/formatTokenValue.d.ts.map +0 -1
- package/dist/PowerSearch/formatTokenValue.js +0 -160
- package/dist/PowerSearch/powerSearchSheetUtils.d.ts +0 -65
- package/dist/PowerSearch/powerSearchSheetUtils.d.ts.map +0 -1
- package/dist/PowerSearch/powerSearchSheetUtils.js +0 -168
- package/dist/animator/createAnimator.d.ts +0 -98
- package/dist/animator/createAnimator.d.ts.map +0 -1
- package/dist/animator/createAnimator.js +0 -259
- package/dist/hooks/pressGroupContext.d.ts +0 -6
- package/dist/hooks/pressGroupContext.d.ts.map +0 -1
- package/dist/hooks/pressGroupContext.js +0 -20
- package/dist/hooks/useActionGroupTracking.d.ts +0 -53
- package/dist/hooks/useActionGroupTracking.d.ts.map +0 -1
- package/dist/hooks/useActionGroupTracking.js +0 -174
- package/dist/hooks/useAnimator.d.ts +0 -41
- package/dist/hooks/useAnimator.d.ts.map +0 -1
- package/dist/hooks/useAnimator.js +0 -70
- package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.d.ts +0 -8
- package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.d.ts.map +0 -1
- package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.js +0 -42
- package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.d.ts +0 -8
- package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.d.ts.map +0 -1
- package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.js +0 -14
- package/dist/internal/indicatorPress.stylex.d.ts +0 -20
- package/dist/internal/indicatorPress.stylex.d.ts.map +0 -1
- package/dist/internal/indicatorPress.stylex.js +0 -26
- package/dist/motion/progress.d.ts +0 -88
- package/dist/motion/progress.d.ts.map +0 -1
- package/dist/motion/progress.js +0 -128
- package/dist/motion/uikit/alert.d.ts +0 -41
- package/dist/motion/uikit/alert.d.ts.map +0 -1
- package/dist/motion/uikit/alert.js +0 -43
- package/dist/privateAttributes/pressGroupItem.stylex.d.ts +0 -15
- package/dist/privateAttributes/pressGroupItem.stylex.d.ts.map +0 -1
- package/dist/privateAttributes/pressGroupItem.stylex.js +0 -23
- package/dist/utils/triggerFocus.d.ts +0 -36
- package/dist/utils/triggerFocus.d.ts.map +0 -1
- package/dist/utils/triggerFocus.js +0 -65
- package/src/PowerSearch/PowerSearchBottomSheet.tsx +0 -2515
- package/src/PowerSearch/formatTokenValue.ts +0 -215
- package/src/PowerSearch/powerSearchSheetUtils.ts +0 -224
- package/src/animator/createAnimator.doc.mjs +0 -153
- package/src/animator/createAnimator.ts +0 -324
- package/src/hooks/pressGroupContext.ts +0 -21
- package/src/hooks/useActionGroupTracking.ts +0 -224
- package/src/hooks/useAnimator.doc.mjs +0 -109
- package/src/hooks/useAnimator.ts +0 -67
- package/src/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.ts +0 -43
- package/src/i18n/generated-english/PowerSearch/formatTokenValue.generated.ts +0 -15
- package/src/internal/indicatorPress.stylex.ts +0 -24
- package/src/motion/progress.ts +0 -155
- package/src/motion/uikit/alert.ts +0 -43
- package/src/privateAttributes/pressGroupItem.stylex.ts +0 -23
- package/src/utils/triggerFocus.ts +0 -80
|
@@ -4,19 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file PowerSearch.tsx
|
|
7
|
-
* @input PowerSearchConfig, filters, onChange
|
|
8
|
-
* useAdaptivePresentation, and PowerSearchBottomSheet (lazy)
|
|
7
|
+
* @input PowerSearchConfig, filters, onChange
|
|
9
8
|
* @output Structured filter bar with token-based filter management
|
|
10
9
|
* @position Main component; forwards DOM ref and exposes tokenizer control via
|
|
11
|
-
* handleRef
|
|
12
|
-
* field and editor popover for one trigger that opens PowerSearchBottomSheet.
|
|
10
|
+
* handleRef
|
|
13
11
|
*
|
|
14
12
|
* SYNC: When modified, update:
|
|
15
13
|
* - /packages/core/src/PowerSearch/index.ts
|
|
16
|
-
* - /packages/core/src/PowerSearch/PowerSearchBottomSheet.tsx (sheet presentation)
|
|
17
14
|
* - /packages/cli/assets/templates/blocks/components/PowerSearch/ (showcase blocks)
|
|
18
15
|
*/
|
|
19
|
-
import React, {
|
|
16
|
+
import React, { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
20
17
|
import * as stylex from '@stylexjs/stylex';
|
|
21
18
|
import { Tokenizer } from "../Tokenizer/index.js";
|
|
22
19
|
import { TokenizerClearAllMessageContext } from "../Tokenizer/TokenizerClearAllMessageContext.js";
|
|
@@ -26,31 +23,22 @@ import { Token } from "../Token/index.js";
|
|
|
26
23
|
import { TokenNamingContext } from "../Token/TokenNamingContext.js";
|
|
27
24
|
import { Avatar } from "../Avatar/index.js";
|
|
28
25
|
import { layerAnimations } from "../Layer/layerAnimations.stylex.js";
|
|
29
|
-
import { Icon
|
|
30
|
-
import { Field } from "../Field/Field.js";
|
|
31
|
-
import { inputStatusBorderStyles, inputStatusFocusWithinStyles, inputStatusHoverShadowStyles, inputWrapperStyles } from "../Field/inputStyles.stylex.js";
|
|
26
|
+
import { Icon } from "../Icon/index.js";
|
|
32
27
|
import { usePopover } from "../Popover/usePopover.js";
|
|
33
|
-
import { useTooltip } from "../Tooltip/useTooltip.js";
|
|
34
28
|
import "../Layer/layerViewportInset.stylex.js";
|
|
35
29
|
import { layerViewportInset } from "../Layer/layerViewportInset.stylex.js";
|
|
36
30
|
import { useAnnounce } from "../hooks/useAnnounce.js";
|
|
37
|
-
import { useAdaptivePresentation } from "../hooks/useAdaptivePresentation.js";
|
|
38
|
-
import { useDevWarning } from "../hooks/useDevWarning.js";
|
|
39
|
-
import { useIsHydrating } from "../hooks/useIsHydrating.js";
|
|
40
31
|
import "../theme/tokens.stylex.js";
|
|
41
|
-
import { spacingVars, colorVars,
|
|
32
|
+
import { spacingVars, colorVars, typeScaleVars, fontWeightVars } from "../theme/tokens.stylex.js";
|
|
42
33
|
import { useSize } from "../SizeContext/SizeContext.js";
|
|
43
|
-
import { isFocusDetached } from "../utils/focusReturn.js";
|
|
44
|
-
import { isRenderable } from "../utils/isRenderable.js";
|
|
45
34
|
import { useInternalConfig } from "./useInternalConfig.js";
|
|
46
35
|
import { usePowerSearchSource } from "./usePowerSearchSource.js";
|
|
47
|
-
import { formatFilterValue } from "./formatFilterValue.js";
|
|
48
|
-
import {
|
|
49
|
-
import { buildRelativeDateOptions, PowerSearchValueEditor } from "./PowerSearchValueEditor.js";
|
|
36
|
+
import { formatFilterValue, formatDateAbsoluteCompact } from "./formatFilterValue.js";
|
|
37
|
+
import { PowerSearchEditPopover } from "./PowerSearchEditPopover.js";
|
|
50
38
|
import { resolveOperatorLabel } from "./resolveOperatorLabel.js";
|
|
51
39
|
import { themeProps } from "../utils/themeProps.js";
|
|
40
|
+
import { truncateCharacters } from "../utils/characters.js";
|
|
52
41
|
import { useLocale } from "../i18n/useLocale.js";
|
|
53
|
-
import { formatTokenValueText } from "./formatTokenValue.js";
|
|
54
42
|
import { useMergedRefs } from "../hooks/useMergedRefs.js";
|
|
55
43
|
import { registerEnglishFallback, useComponentTranslator } from "../i18n/useComponentTranslator.js";
|
|
56
44
|
import english from "../i18n/generated-english/PowerSearch/PowerSearch.generated.js";
|
|
@@ -95,76 +83,106 @@ const popoverLayerStyles = {
|
|
|
95
83
|
$$css: true
|
|
96
84
|
}
|
|
97
85
|
};
|
|
98
|
-
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
md: {
|
|
107
|
-
kAzted: "x1uogy3y",
|
|
108
|
-
$$css: true
|
|
109
|
-
},
|
|
110
|
-
lg: {
|
|
111
|
-
kAzted: "x1xf4nls",
|
|
112
|
-
$$css: true
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
const sheetTriggerStyles = {
|
|
116
|
-
wrapper: {
|
|
117
|
-
kVAEAm: "x1n2onr6",
|
|
118
|
-
kwnvtZ: "xozqiw3",
|
|
119
|
-
kOIVth: "xzye2dw",
|
|
120
|
-
kZKoxP: "xt7dq6l",
|
|
121
|
-
kkrTdU: "x1ypdohk xvivl9a",
|
|
122
|
-
$$css: true
|
|
123
|
-
},
|
|
124
|
-
wrapperWithTokens: {
|
|
125
|
-
k8WAf4: "x1x7cmac",
|
|
126
|
-
kg3NbH: "xx2oswg",
|
|
127
|
-
$$css: true
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
// The sheet flow (three standalone sheets, the sheet editors) only
|
|
132
|
-
// renders for the bottom-sheet presentation. Loading it on demand keeps it out
|
|
133
|
-
// of pages whose PowerSearch stays a tokenizer field.
|
|
134
|
-
// One import promise, shared by the preload and the lazy element: the sheet
|
|
135
|
-
// presentation loads the flow's chunk as soon as it is active, so the first
|
|
136
|
-
// press does not wait for the network, while nothing of the flow is rendered
|
|
137
|
-
// until a press.
|
|
138
|
-
const loadPowerSearchBottomSheet = async () => import("./PowerSearchBottomSheet.js");
|
|
139
|
-
const LazyPowerSearchBottomSheet = /*#__PURE__*/lazy(async () => loadPowerSearchBottomSheet().then(module => ({
|
|
140
|
-
default: module.PowerSearchBottomSheet
|
|
141
|
-
})));
|
|
142
|
-
// The value step reuses the popover presentation's editors, which this
|
|
143
|
-
// module already loads; see PowerSearchSheetEditors.
|
|
144
|
-
const SHEET_EDITORS = {
|
|
145
|
-
NestedEditor,
|
|
146
|
-
PowerSearchValueEditor,
|
|
147
|
-
buildRelativeDateOptions
|
|
148
|
-
};
|
|
86
|
+
function truncateString(value, limit) {
|
|
87
|
+
// Same semantics as before — strings within limit + 3 pass through, longer
|
|
88
|
+
// ones cut to limit + '...' — but counted in characters, not code units.
|
|
89
|
+
return truncateCharacters(value, limit + 3, '...');
|
|
90
|
+
}
|
|
91
|
+
function getEnumLabel(values, value) {
|
|
92
|
+
return values.find(v => v.value === value)?.label ?? value;
|
|
93
|
+
}
|
|
149
94
|
|
|
150
95
|
/**
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
* would leave server markup incomplete and abort hydration. The closed flow
|
|
154
|
-
* has no visible markup, so it first renders right after hydration.
|
|
96
|
+
* The visible text of a filter token's value. The token renders it, and the
|
|
97
|
+
* token's remove button and editor dialog are named by the same text.
|
|
155
98
|
*/
|
|
156
|
-
function
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
99
|
+
function tokenValueText(operatorValue, filterValue, maxLength, locale) {
|
|
100
|
+
switch (filterValue.type) {
|
|
101
|
+
case 'empty':
|
|
102
|
+
return null;
|
|
103
|
+
case 'string':
|
|
104
|
+
return truncateString(filterValue.value, maxLength);
|
|
105
|
+
case 'integer':
|
|
106
|
+
case 'float':
|
|
107
|
+
return String(filterValue.value);
|
|
108
|
+
case 'enum':
|
|
109
|
+
if (operatorValue.type === 'enum') {
|
|
110
|
+
return truncateString(getEnumLabel(operatorValue.values, filterValue.value), maxLength);
|
|
111
|
+
}
|
|
112
|
+
return truncateString(filterValue.value, maxLength);
|
|
113
|
+
case 'string_list':
|
|
114
|
+
{
|
|
115
|
+
const items = filterValue.value;
|
|
116
|
+
if (items.length === 0) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
if (items.length === 1) {
|
|
120
|
+
return truncateString(items[0], maxLength);
|
|
121
|
+
}
|
|
122
|
+
const totalLength = items.reduce((sum, s) => sum + s.length, 0);
|
|
123
|
+
if (totalLength > maxLength) {
|
|
124
|
+
return `${items.length} items`;
|
|
125
|
+
}
|
|
126
|
+
return items.join(', ');
|
|
127
|
+
}
|
|
128
|
+
case 'enum_list':
|
|
129
|
+
{
|
|
130
|
+
const items = filterValue.value;
|
|
131
|
+
if (items.length === 0) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
if (operatorValue.type === 'enum_list') {
|
|
135
|
+
const labels = items.map(v => getEnumLabel(operatorValue.values, v));
|
|
136
|
+
if (labels.length === 1) {
|
|
137
|
+
return truncateString(labels[0], maxLength);
|
|
138
|
+
}
|
|
139
|
+
const totalLength = labels.reduce((sum, s) => sum + s.length, 0);
|
|
140
|
+
if (totalLength > maxLength) {
|
|
141
|
+
return `${labels.length} items`;
|
|
142
|
+
}
|
|
143
|
+
return labels.join(', ');
|
|
144
|
+
}
|
|
145
|
+
if (items.length === 1) {
|
|
146
|
+
return truncateString(items[0], maxLength);
|
|
147
|
+
}
|
|
148
|
+
return `${items.length} items`;
|
|
149
|
+
}
|
|
150
|
+
case 'entity_list':
|
|
151
|
+
{
|
|
152
|
+
const entities = filterValue.value;
|
|
153
|
+
if (entities.length === 0) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
if (entities.length === 1) {
|
|
157
|
+
return truncateString(entities[0].label, maxLength);
|
|
158
|
+
}
|
|
159
|
+
const totalLength = entities.reduce((sum, e) => sum + e.label.length, 0);
|
|
160
|
+
if (totalLength > maxLength) {
|
|
161
|
+
return `${entities.length} items`;
|
|
162
|
+
}
|
|
163
|
+
return entities.map(e => e.label).join(', ');
|
|
164
|
+
}
|
|
165
|
+
case 'time':
|
|
166
|
+
return filterValue.value;
|
|
167
|
+
case 'date_absolute':
|
|
168
|
+
return truncateString(formatDateAbsoluteCompact(filterValue.unixSeconds, locale), maxLength);
|
|
169
|
+
case 'date_relative':
|
|
170
|
+
return truncateString(filterValue.value, maxLength);
|
|
171
|
+
case 'date_range':
|
|
172
|
+
return 'date range';
|
|
173
|
+
case 'custom':
|
|
174
|
+
if (operatorValue.type === 'custom') {
|
|
175
|
+
return truncateString(operatorValue.getString(filterValue.value), maxLength);
|
|
176
|
+
}
|
|
177
|
+
return filterValue.value;
|
|
178
|
+
case 'nested':
|
|
179
|
+
{
|
|
180
|
+
const count = filterValue.value.length;
|
|
181
|
+
return count === 1 ? '1 filter' : `${count} filters`;
|
|
182
|
+
}
|
|
183
|
+
default:
|
|
184
|
+
return null;
|
|
160
185
|
}
|
|
161
|
-
return /*#__PURE__*/_jsx(Suspense, {
|
|
162
|
-
fallback: null,
|
|
163
|
-
children: /*#__PURE__*/_jsx(LazyPowerSearchBottomSheet, {
|
|
164
|
-
...props,
|
|
165
|
-
editors: SHEET_EDITORS
|
|
166
|
-
})
|
|
167
|
-
});
|
|
168
186
|
}
|
|
169
187
|
function PowerSearchTokenValue({
|
|
170
188
|
text
|
|
@@ -296,8 +314,7 @@ export function PowerSearch({
|
|
|
296
314
|
xstyle,
|
|
297
315
|
className,
|
|
298
316
|
style,
|
|
299
|
-
components: componentOverrides
|
|
300
|
-
experimental
|
|
317
|
+
components: componentOverrides
|
|
301
318
|
}) {
|
|
302
319
|
const size = useSize(sizeProp, 'md');
|
|
303
320
|
const config = useInternalConfig(configProp);
|
|
@@ -308,87 +325,6 @@ export function PowerSearch({
|
|
|
308
325
|
const placeholder = placeholderFromProps ?? t('@astryx.powersearch.placeholder');
|
|
309
326
|
const popoverSaveButtonLabel = popoverSaveButtonLabelFromProps ?? t('@astryx.powersearch.editor.apply');
|
|
310
327
|
const tokenizerRef = useRef(null);
|
|
311
|
-
|
|
312
|
-
// Experimental presentation. `adaptive`
|
|
313
|
-
// resolves through the policy the selection controls share; an open flow
|
|
314
|
-
// keeps its presentation until it closes, so a resolution change mid-task
|
|
315
|
-
// cannot pull the surface out from under the person.
|
|
316
|
-
const presentation = experimental?.presentation ?? 'popover';
|
|
317
|
-
const resolvedPresentation = useAdaptivePresentation(presentation);
|
|
318
|
-
const [isSheetOpen, setIsSheetOpen] = useState(false);
|
|
319
|
-
// Latched for the flow's lifetime: the flow stays presented after it closes
|
|
320
|
-
// until the sheets have run their exit and handed focus back to the trigger.
|
|
321
|
-
// Without the latch, `adaptive` resolving to `popover` mid-session (a phone
|
|
322
|
-
// turned to landscape) would unmount the sheets and the trigger they return
|
|
323
|
-
// focus to in the same render, dropping focus to the page body.
|
|
324
|
-
const [isSheetPresented, setIsSheetPresented] = useState(false);
|
|
325
|
-
const isSheetPresentation = isSheetOpen || isSheetPresented || resolvedPresentation === 'bottom-sheet';
|
|
326
|
-
const triggerRef = useRef(null);
|
|
327
|
-
// `hasAutoFocus` applies only to the control the field first mounts. A
|
|
328
|
-
// presentation swap remounts the control (combobox input or trigger), and
|
|
329
|
-
// React's `autoFocus` on the new one would pull focus from wherever on the
|
|
330
|
-
// page it was; the roots' callback refs hand over the focus the field held
|
|
331
|
-
// instead. A field that never swaps keeps `autoFocus` on every render, so a
|
|
332
|
-
// Dialog that keeps it mounted still finds its `data-autofocus` on open.
|
|
333
|
-
const [autoFocusState, setAutoFocusState] = useState({
|
|
334
|
-
presentation: isSheetPresentation,
|
|
335
|
-
isFirstControl: true
|
|
336
|
-
});
|
|
337
|
-
if (autoFocusState.presentation !== isSheetPresentation) {
|
|
338
|
-
setAutoFocusState({
|
|
339
|
-
presentation: isSheetPresentation,
|
|
340
|
-
isFirstControl: false
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
const autoFocusOnMount = hasAutoFocus && autoFocusState.isFirstControl && autoFocusState.presentation === isSheetPresentation;
|
|
344
|
-
// A focus the swap moves continues the same visit to the field: the
|
|
345
|
-
// control that held focus is gone (no blur fires for a removed element), so
|
|
346
|
-
// the caller is told of neither a blur nor a new focus.
|
|
347
|
-
const isSwapFocusRef = useRef(false);
|
|
348
|
-
const focusAfterSwap = useCallback(control => {
|
|
349
|
-
if (control == null) {
|
|
350
|
-
return;
|
|
351
|
-
}
|
|
352
|
-
isSwapFocusRef.current = true;
|
|
353
|
-
try {
|
|
354
|
-
control.focus();
|
|
355
|
-
} finally {
|
|
356
|
-
isSwapFocusRef.current = false;
|
|
357
|
-
}
|
|
358
|
-
}, []);
|
|
359
|
-
const handleFieldFocus = useCallback(event => {
|
|
360
|
-
if (!isSwapFocusRef.current) {
|
|
361
|
-
onFocus?.(event);
|
|
362
|
-
}
|
|
363
|
-
}, [onFocus]);
|
|
364
|
-
const handleFieldBlur = useCallback(event => {
|
|
365
|
-
onBlur?.(event);
|
|
366
|
-
}, [onBlur]);
|
|
367
|
-
// While the flow is open, the sheet announces its own content from inside
|
|
368
|
-
// its dialog; this component announces only with the flow closed, and
|
|
369
|
-
// `useAnnounce` routes those messages by where the field is — into a Dialog
|
|
370
|
-
// or modal Drawer that holds it, or the shared channel when no modal does.
|
|
371
|
-
// A result count that changed during the flow's exit is spoken once the
|
|
372
|
-
// flow has fully closed and focus is back on the trigger: the closing
|
|
373
|
-
// dialog stays modal through its exit, so neither its region nor the
|
|
374
|
-
// page-body channel is heard before.
|
|
375
|
-
const afterCloseResultCountRef = useRef(null);
|
|
376
|
-
const triggerId = useId();
|
|
377
|
-
const triggerLabelId = useId();
|
|
378
|
-
const triggerContentId = useId();
|
|
379
|
-
const statusMessageId = useId();
|
|
380
|
-
// A field that becomes disabled cannot keep its flow open, and must not
|
|
381
|
-
// reopen it when re-enabled. Adjusted in the
|
|
382
|
-
// render that sees the change, not an effect, so no frame shows both.
|
|
383
|
-
const [wasDisabled, setWasDisabled] = useState(isDisabled);
|
|
384
|
-
if (isDisabled !== wasDisabled) {
|
|
385
|
-
setWasDisabled(isDisabled);
|
|
386
|
-
if (isDisabled && isSheetOpen) {
|
|
387
|
-
setIsSheetOpen(false);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
useDevWarning('PowerSearch', '`menuWidth` has no surface in the bottom-sheet presentation: the sheet flow has no typeahead popover to size. Scope it to the popover presentation or leave it out.', isSheetPresentation && menuWidth != null);
|
|
391
|
-
useDevWarning('PowerSearch', '`tokenOverflowBehavior` has no surface in the bottom-sheet presentation: the trigger wraps its display-only tokens. Scope it to the popover presentation or leave it out.', isSheetPresentation && tokenOverflowBehavior != null);
|
|
392
328
|
const [popoverState, setPopoverStateRaw] = useState({
|
|
393
329
|
type: 'idle'
|
|
394
330
|
});
|
|
@@ -402,7 +338,7 @@ export function PowerSearch({
|
|
|
402
338
|
const fieldLabel = field?.label ?? '';
|
|
403
339
|
const operatorLabel = operator ? resolveOperatorLabel(operator, t) : '';
|
|
404
340
|
const label = `${fieldLabel}: ${operatorLabel}`.trim();
|
|
405
|
-
const value = operator ?
|
|
341
|
+
const value = operator ? tokenValueText(operator.value, filter.value, Math.max(maxTokenLength - fieldLabel.length - operatorLabel.length, 10), locale) : null;
|
|
406
342
|
return {
|
|
407
343
|
label,
|
|
408
344
|
value,
|
|
@@ -414,23 +350,9 @@ export function PowerSearch({
|
|
|
414
350
|
const editedFilter = popoverState.type === 'editing' ? filters[popoverState.filterIndex] : undefined;
|
|
415
351
|
const editedOperator = editedFilter != null ? config.getOperator(editedFilter.field, editedFilter.operator) : undefined;
|
|
416
352
|
const editedBuiltInFilter = editedOperator == null || componentOverrides?.[editedOperator.value.type]?.Token == null ? editedFilter : undefined;
|
|
417
|
-
// Whether the editor popover is open, for the hand-off below, which runs
|
|
418
|
-
// in the commit that swaps presentations.
|
|
419
|
-
const isPopoverOpenRef = useRef(false);
|
|
420
|
-
// When `adaptive` flips to the sheet while the editor popover is open (a
|
|
421
|
-
// phone rotated), the editing ends with the popover: its state returns to
|
|
422
|
-
// idle (through the raw setter, since the tokenizer input is gone), in the
|
|
423
|
-
// render that sees the swap, so a later switch back does not reopen a stale
|
|
424
|
-
// editor.
|
|
425
|
-
if (isSheetPresentation && popoverState.type !== 'idle') {
|
|
426
|
-
setPopoverStateRaw({
|
|
427
|
-
type: 'idle'
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
353
|
|
|
431
354
|
// Layer for positioning the edit popover anchored to the tokenizer
|
|
432
355
|
const handleLayerHide = useCallback(() => {
|
|
433
|
-
isPopoverOpenRef.current = false;
|
|
434
356
|
setPopoverStateRaw({
|
|
435
357
|
type: 'idle'
|
|
436
358
|
});
|
|
@@ -449,47 +371,8 @@ export function PowerSearch({
|
|
|
449
371
|
dialogLabel: editedBuiltInFilter != null ? tokenText(editedBuiltInFilter).full : undefined
|
|
450
372
|
});
|
|
451
373
|
|
|
452
|
-
// A presentation swap removes the focused control, so the other
|
|
453
|
-
// presentation's primary control (the combobox input or the trigger) takes
|
|
454
|
-
// focus and focus never falls to the page body. Each presentation keys its
|
|
455
|
-
// root, so a swap mounts a new root. The detaching root notes that it held
|
|
456
|
-
// focus, which also covers an input focused by server-rendered `autofocus`
|
|
457
|
-
// before hydration. The editor popover is portaled outside the root, so an
|
|
458
|
-
// open editor counts as held focus. The attaching root gives focus to its
|
|
459
|
-
// primary control when focus has fallen to the page body; the sheet root
|
|
460
|
-
// also hides a popover layer left open.
|
|
461
|
-
const isFocusPendingHandOffRef = useRef(false);
|
|
462
|
-
const hidePopover = popover.hide;
|
|
463
|
-
const handOffFocusRef = useCallback(node => {
|
|
464
|
-
if (node == null) {
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
467
|
-
const trigger = triggerRef.current;
|
|
468
|
-
const isSheetRoot = trigger != null && node.contains(trigger);
|
|
469
|
-
// The sheet presentation preloads the flow's chunk, so the first press
|
|
470
|
-
// opens without waiting for the network; nothing renders.
|
|
471
|
-
if (isSheetRoot) {
|
|
472
|
-
void loadPowerSearchBottomSheet();
|
|
473
|
-
}
|
|
474
|
-
if (isSheetRoot && isPopoverOpenRef.current) {
|
|
475
|
-
isPopoverOpenRef.current = false;
|
|
476
|
-
hidePopover();
|
|
477
|
-
}
|
|
478
|
-
const takesFocus = isFocusPendingHandOffRef.current;
|
|
479
|
-
isFocusPendingHandOffRef.current = false;
|
|
480
|
-
if (takesFocus && isFocusDetached(node.ownerDocument)) {
|
|
481
|
-
focusAfterSwap(isSheetRoot ? trigger : tokenizerRef.current);
|
|
482
|
-
}
|
|
483
|
-
return () => {
|
|
484
|
-
if (node.contains(node.ownerDocument.activeElement) || isPopoverOpenRef.current) {
|
|
485
|
-
isFocusPendingHandOffRef.current = true;
|
|
486
|
-
}
|
|
487
|
-
};
|
|
488
|
-
}, [focusAfterSwap, hidePopover]);
|
|
489
|
-
|
|
490
374
|
// Wrapper that manages layer visibility and tokenizer focus alongside state
|
|
491
375
|
const setPopoverState = useCallback(state => {
|
|
492
|
-
isPopoverOpenRef.current = state.type !== 'idle';
|
|
493
376
|
setPopoverStateRaw(state);
|
|
494
377
|
if (state.type !== 'idle') {
|
|
495
378
|
// Schedule after the current frame so React can render the popover
|
|
@@ -504,22 +387,13 @@ export function PowerSearch({
|
|
|
504
387
|
}
|
|
505
388
|
}, [popover]);
|
|
506
389
|
|
|
507
|
-
// Expose imperative handle
|
|
508
|
-
// field's focusable control.
|
|
390
|
+
// Expose imperative handle
|
|
509
391
|
useImperativeHandle(handleRef, () => ({
|
|
510
392
|
focusTypeahead() {
|
|
511
|
-
|
|
512
|
-
triggerRef.current?.focus();
|
|
513
|
-
} else {
|
|
514
|
-
tokenizerRef.current?.focus();
|
|
515
|
-
}
|
|
393
|
+
tokenizerRef.current?.focus();
|
|
516
394
|
},
|
|
517
395
|
blurTypeahead() {
|
|
518
|
-
|
|
519
|
-
triggerRef.current?.blur();
|
|
520
|
-
} else {
|
|
521
|
-
tokenizerRef.current?.blur();
|
|
522
|
-
}
|
|
396
|
+
tokenizerRef.current?.blur();
|
|
523
397
|
}
|
|
524
398
|
}));
|
|
525
399
|
|
|
@@ -680,17 +554,15 @@ export function PowerSearch({
|
|
|
680
554
|
});
|
|
681
555
|
}, [setPopoverState]);
|
|
682
556
|
|
|
683
|
-
//
|
|
684
|
-
//
|
|
685
|
-
|
|
686
|
-
// opens the flow.
|
|
687
|
-
const renderFilterToken = useCallback((item, onRemove) => {
|
|
557
|
+
// Custom token renderer
|
|
558
|
+
// Custom token renderer
|
|
559
|
+
const renderToken = useCallback((item, onRemove) => {
|
|
688
560
|
const auxData = item.auxiliaryData;
|
|
689
561
|
const filterIndex = auxData?.filterIndex ?? -1;
|
|
690
562
|
const filter = filterIndex >= 0 ? filters[filterIndex] : undefined;
|
|
691
563
|
const field = auxData ? config.getField(auxData.fieldKey) : undefined;
|
|
692
564
|
const operator = auxData?.operatorKey ? config.getOperator(auxData.fieldKey, auxData.operatorKey) : undefined;
|
|
693
|
-
const canInteract =
|
|
565
|
+
const canInteract = !isReadOnly && !isDisabled && !filter?.isReadOnly;
|
|
694
566
|
const handleClick = canInteract ? () => handleTokenClick(filterIndex) : undefined;
|
|
695
567
|
const handleRemove = canInteract ? onRemove : undefined;
|
|
696
568
|
|
|
@@ -764,7 +636,6 @@ export function PowerSearch({
|
|
|
764
636
|
})
|
|
765
637
|
});
|
|
766
638
|
}, [filters, config, configProp, maxTokenLength, size, isReadOnly, isDisabled, handleTokenClick, componentOverrides, t, popoverState, tokenText]);
|
|
767
|
-
const renderToken = useCallback((item, onRemove) => renderFilterToken(item, onRemove), [renderFilterToken]);
|
|
768
639
|
|
|
769
640
|
// Custom typeahead item renderer — adds field icon and description
|
|
770
641
|
const renderItem = useCallback(item => {
|
|
@@ -852,38 +723,28 @@ export function PowerSearch({
|
|
|
852
723
|
return resultCount;
|
|
853
724
|
}, [resultCount, t]);
|
|
854
725
|
|
|
855
|
-
//
|
|
856
|
-
// mirroring the way Typeahead announces its dropdown result count
|
|
857
|
-
// is otherwise only shown visually and stays silent to assistive
|
|
858
|
-
//
|
|
859
|
-
//
|
|
860
|
-
//
|
|
861
|
-
//
|
|
862
|
-
// announced unprompted — and the guard compares against the last announced
|
|
863
|
-
// text rather than a mounted flag, so StrictMode's effect replay announces
|
|
864
|
-
// nothing either. A change that lands while the flow is closing waits for
|
|
865
|
-
// the trigger focus, since the dialog is still modal through its exit. The
|
|
866
|
-
// announcement acquires no resource, so there is no cleanup.
|
|
726
|
+
// Announce result-count changes to screen readers through a polite live
|
|
727
|
+
// region, mirroring the way Typeahead announces its dropdown result count.
|
|
728
|
+
// The count is otherwise only shown visually and stays silent to assistive
|
|
729
|
+
// tech. Only a change after mount is spoken: the guard compares against the
|
|
730
|
+
// last announced text rather than a mounted flag, so StrictMode's effect
|
|
731
|
+
// replay (which resets a flag and would speak the count present on mount
|
|
732
|
+
// unprompted) announces nothing until the count changes.
|
|
867
733
|
const announce = useAnnounce();
|
|
868
734
|
// PowerSearch words its Clear all as its record does; the field announces
|
|
869
735
|
// these words instead of Tokenizer's (component:Tokenizer AR7).
|
|
870
736
|
const hasReadOnlyFilter = filters.some(filter => filter.isReadOnly);
|
|
871
737
|
const clearAllMessage = useMemo(() => hasReadOnlyFilter ? t('@astryx.powersearch.editableFiltersRemoved') : t('@astryx.powersearch.allFiltersRemoved'), [hasReadOnlyFilter, t]);
|
|
872
738
|
const announcedResultCountRef = useRef(resultCountText);
|
|
873
|
-
const isSheetExiting = isSheetPresented && !isSheetOpen;
|
|
874
739
|
useEffect(() => {
|
|
875
740
|
if (resultCountText === announcedResultCountRef.current) {
|
|
876
741
|
return;
|
|
877
742
|
}
|
|
878
743
|
announcedResultCountRef.current = resultCountText;
|
|
879
744
|
if (resultCountText != null) {
|
|
880
|
-
|
|
881
|
-
afterCloseResultCountRef.current = resultCountText;
|
|
882
|
-
} else if (!isSheetOpen) {
|
|
883
|
-
announce(resultCountText);
|
|
884
|
-
}
|
|
745
|
+
announce(resultCountText);
|
|
885
746
|
}
|
|
886
|
-
}, [resultCountText, announce
|
|
747
|
+
}, [resultCountText, announce]);
|
|
887
748
|
|
|
888
749
|
// Build combined endContent from resultCount + endContent props
|
|
889
750
|
const combinedEndContent = useMemo(() => {
|
|
@@ -902,176 +763,9 @@ export function PowerSearch({
|
|
|
902
763
|
}
|
|
903
764
|
return resultCountNode || endContent || undefined;
|
|
904
765
|
}, [resultCountText, endContent]);
|
|
905
|
-
|
|
906
|
-
// ------------------------------------------------------- sheet trigger --
|
|
907
|
-
|
|
908
|
-
// Disabled-reason tooltip for the sheet trigger. Disabled controls swallow
|
|
909
|
-
// pointer events, so the listeners attach to the field's control box; the
|
|
910
|
-
// trigger stays perceivable through aria-disabled.
|
|
911
|
-
const showsDisabledMessage = isDisabled && !!disabledMessage;
|
|
912
|
-
const disabledMessageTooltip = useTooltip({
|
|
913
|
-
placement: 'above',
|
|
914
|
-
focusTrigger: 'always',
|
|
915
|
-
isEnabled: isSheetPresentation && showsDisabledMessage
|
|
916
|
-
});
|
|
917
|
-
const rootRef = useMergedRefs(ref, popover.triggerRef, handOffFocusRef);
|
|
918
|
-
const openSheet = useCallback(() => {
|
|
919
|
-
if (isDisabled) {
|
|
920
|
-
return;
|
|
921
|
-
}
|
|
922
|
-
// The flow restores focus to the element that was active when it opened;
|
|
923
|
-
// make sure that is the trigger even for a tap on a token.
|
|
924
|
-
triggerRef.current?.focus({
|
|
925
|
-
preventScroll: true
|
|
926
|
-
});
|
|
927
|
-
setIsSheetPresented(true);
|
|
928
|
-
setIsSheetOpen(true);
|
|
929
|
-
}, [isDisabled]);
|
|
930
|
-
|
|
931
|
-
// The field's end lane — the result count and `endContent` — sits outside
|
|
932
|
-
// the trigger button: a caller's action button there keeps its own tab stop
|
|
933
|
-
// and taps, and an interactive control must not nest in a component
|
|
934
|
-
// button, so a tap on it must not open the flow.
|
|
935
|
-
const endLaneRef = useRef(null);
|
|
936
|
-
const handleTriggerWrapperClick = useCallback(event => {
|
|
937
|
-
// Tokens are display-only; a tap on them or the empty space around them
|
|
938
|
-
// opens the flow. The trigger button handles its own click, and the end
|
|
939
|
-
// lane handles its own.
|
|
940
|
-
if (event.target instanceof Node && (triggerRef.current?.contains(event.target) || endLaneRef.current?.contains(event.target))) {
|
|
941
|
-
return;
|
|
942
|
-
}
|
|
943
|
-
openSheet();
|
|
944
|
-
}, [openSheet]);
|
|
945
|
-
const handleTriggerFocusWithin = useCallback(event => {
|
|
946
|
-
// The flow focuses the trigger only after its exit completes; that focus
|
|
947
|
-
// is the signal that the retained sheets can leave. If the resolution
|
|
948
|
-
// moved to the popover meanwhile, the tokenizer input takes over the
|
|
949
|
-
// focus once it mounts (the hand-off above).
|
|
950
|
-
if (!isSheetOpen && isSheetPresented) {
|
|
951
|
-
setIsSheetPresented(false);
|
|
952
|
-
// The dialogs have closed: the page-body channel is exposed again.
|
|
953
|
-
const resultCount = afterCloseResultCountRef.current;
|
|
954
|
-
afterCloseResultCountRef.current = null;
|
|
955
|
-
if (resultCount != null) {
|
|
956
|
-
announce(resultCount);
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
if (!(event.relatedTarget instanceof Node) || !event.currentTarget.contains(event.relatedTarget)) {
|
|
960
|
-
handleFieldFocus(event);
|
|
961
|
-
}
|
|
962
|
-
}, [announce, handleFieldFocus, isSheetOpen, isSheetPresented]);
|
|
963
|
-
const handleTriggerBlurWithin = useCallback(event => {
|
|
964
|
-
if (!(event.relatedTarget instanceof Node) || !event.currentTarget.contains(event.relatedTarget)) {
|
|
965
|
-
handleFieldBlur(event);
|
|
966
|
-
}
|
|
967
|
-
}, [handleFieldBlur]);
|
|
968
|
-
if (isSheetPresentation) {
|
|
969
|
-
const triggerDescribedBy = [status?.message ? statusMessageId : null, showsDisabledMessage ? disabledMessageTooltip.describedBy : null].filter(Boolean).join(' ') || undefined;
|
|
970
|
-
return /*#__PURE__*/_jsxs("div", {
|
|
971
|
-
ref: rootRef,
|
|
972
|
-
...themeProps('power-search'),
|
|
973
|
-
children: [/*#__PURE__*/_jsxs(Field, {
|
|
974
|
-
label: label,
|
|
975
|
-
isLabelHidden: isLabelHidden,
|
|
976
|
-
inputID: triggerId,
|
|
977
|
-
labelID: triggerLabelId,
|
|
978
|
-
isDisabled: isDisabled,
|
|
979
|
-
status: status ? {
|
|
980
|
-
type: status.type,
|
|
981
|
-
message: status.message,
|
|
982
|
-
messageID: status.message ? statusMessageId : undefined
|
|
983
|
-
} : undefined,
|
|
984
|
-
statusVariant: statusVariant,
|
|
985
|
-
xstyle: xstyle,
|
|
986
|
-
className: className,
|
|
987
|
-
style: style,
|
|
988
|
-
children: [/*#__PURE__*/_jsxs("div", {
|
|
989
|
-
ref: disabledMessageTooltip.ref,
|
|
990
|
-
onClick: handleTriggerWrapperClick,
|
|
991
|
-
onFocus: handleTriggerFocusWithin,
|
|
992
|
-
onBlur: handleTriggerBlurWithin,
|
|
993
|
-
"aria-disabled": isDisabled ? true : undefined,
|
|
994
|
-
...stylex.props(inputWrapperStyles.base, sheetTriggerStyles.wrapper, filters.length > 0 && sheetTriggerStyles.wrapperWithTokens, sheetTriggerSizeStyles[size], isDisabled && inputWrapperStyles.disabled, status && inputStatusBorderStyles[status.type], status && !isDisabled && inputStatusHoverShadowStyles[status.type], status && inputStatusFocusWithinStyles[status.type]),
|
|
995
|
-
children: [/*#__PURE__*/_jsxs("div", {
|
|
996
|
-
id: triggerContentId,
|
|
997
|
-
...{
|
|
998
|
-
className: "x1n2onr6 xeuugli x1iyjqo2 x78zum5 x6s0dn4 x1a02dak x1lfs0n9 xajebq8"
|
|
999
|
-
},
|
|
1000
|
-
children: [isRenderable(startIcon) && /*#__PURE__*/_jsx("span", {
|
|
1001
|
-
...{
|
|
1002
|
-
0: {},
|
|
1003
|
-
1: {
|
|
1004
|
-
className: "x1xrm450"
|
|
1005
|
-
}
|
|
1006
|
-
}[!!(filters.length > 0) << 0],
|
|
1007
|
-
children: renderIconSlot(startIcon, {
|
|
1008
|
-
size: 'sm',
|
|
1009
|
-
color: 'secondary'
|
|
1010
|
-
})
|
|
1011
|
-
}), tokenizerValue.map(item => /*#__PURE__*/_jsx(React.Fragment, {
|
|
1012
|
-
children: renderFilterToken(item, undefined)
|
|
1013
|
-
}, item.id)), /*#__PURE__*/_jsx("button", {
|
|
1014
|
-
type: "button",
|
|
1015
|
-
id: triggerId,
|
|
1016
|
-
ref: triggerRef
|
|
1017
|
-
// The field's primary control: `data-testid` lands here, as it
|
|
1018
|
-
// lands on the combobox input in the popover presentation.
|
|
1019
|
-
,
|
|
1020
|
-
"data-testid": testId,
|
|
1021
|
-
autoFocus: autoFocusOnMount,
|
|
1022
|
-
onClick: openSheet,
|
|
1023
|
-
"aria-disabled": isDisabled ? true : undefined,
|
|
1024
|
-
"aria-haspopup": "dialog",
|
|
1025
|
-
"aria-expanded": isSheetOpen,
|
|
1026
|
-
"aria-labelledby": `${triggerLabelId} ${triggerContentId}`,
|
|
1027
|
-
"aria-describedby": triggerDescribedBy,
|
|
1028
|
-
...{
|
|
1029
|
-
0: {
|
|
1030
|
-
className: "xjyslct xfoc8du x1fns5xo xkh2ocl x78zum5 x6s0dn4 xt970qd x7a5moj x1ghz6dp xc342km xng3xce xjbqb8w xv1l7n4 x9ynric xjm74w1 xw6l6zx x1yc453h xuxw1ft x1ypdohk xvivl9a x1a2a7pz"
|
|
1031
|
-
},
|
|
1032
|
-
1: {
|
|
1033
|
-
className: "xjyslct xfoc8du xkh2ocl x78zum5 x6s0dn4 xt970qd x7a5moj x1ghz6dp xc342km xng3xce xjbqb8w xv1l7n4 x9ynric xjm74w1 xw6l6zx x1yc453h xuxw1ft x1ypdohk xvivl9a x1a2a7pz x10l6tqk x10a8y8t xeuugli x1717udv"
|
|
1034
|
-
}
|
|
1035
|
-
}[!!(filters.length > 0) << 0],
|
|
1036
|
-
children: filters.length === 0 ? placeholder : null
|
|
1037
|
-
})]
|
|
1038
|
-
}), (endContent || isRenderable(resultCountText)) && /*#__PURE__*/_jsxs("div", {
|
|
1039
|
-
ref: endLaneRef,
|
|
1040
|
-
...{
|
|
1041
|
-
className: "x78zum5 x6s0dn4 x1txdalj x2lah0s x1nryj5t"
|
|
1042
|
-
},
|
|
1043
|
-
children: [isRenderable(resultCountText) && /*#__PURE__*/_jsx("span", {
|
|
1044
|
-
...{
|
|
1045
|
-
className: "x141an7d x1ltkj2j xv1l7n4 xuxw1ft"
|
|
1046
|
-
},
|
|
1047
|
-
children: resultCountText
|
|
1048
|
-
}), endContent]
|
|
1049
|
-
})]
|
|
1050
|
-
}), showsDisabledMessage && disabledMessageTooltip.renderTooltip(disabledMessage)]
|
|
1051
|
-
}), (isSheetOpen || isSheetPresented) && /*#__PURE__*/_jsx(PowerSearchSheetHost, {
|
|
1052
|
-
isOpen: isSheetOpen,
|
|
1053
|
-
onOpenChange: setIsSheetOpen,
|
|
1054
|
-
finalFocusRef: triggerRef,
|
|
1055
|
-
resultCountText: resultCountText,
|
|
1056
|
-
config: config,
|
|
1057
|
-
configProp: configProp,
|
|
1058
|
-
filters: filters,
|
|
1059
|
-
onChange: onChange,
|
|
1060
|
-
searchSource: searchSource,
|
|
1061
|
-
placeholder: placeholder,
|
|
1062
|
-
isReadOnly: isReadOnly,
|
|
1063
|
-
isDisabled: isDisabled,
|
|
1064
|
-
hasClear: hasClear,
|
|
1065
|
-
maxOperatorMenuItems: maxOperatorMenuItems,
|
|
1066
|
-
maxSearchResults: maxSearchResults,
|
|
1067
|
-
saveButtonLabel: popoverSaveButtonLabelFromProps,
|
|
1068
|
-
components: componentOverrides
|
|
1069
|
-
})]
|
|
1070
|
-
}, "sheet");
|
|
1071
|
-
}
|
|
1072
766
|
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
1073
767
|
children: [/*#__PURE__*/_jsx("div", {
|
|
1074
|
-
ref:
|
|
768
|
+
ref: useMergedRefs(ref, popover.triggerRef),
|
|
1075
769
|
...themeProps('power-search'),
|
|
1076
770
|
children: /*#__PURE__*/_jsx(TokenizerClearAllMessageContext, {
|
|
1077
771
|
value: clearAllMessage,
|
|
@@ -1089,7 +783,7 @@ export function PowerSearch({
|
|
|
1089
783
|
maxMenuItems: MAX_BROWSE_MENU_ITEMS,
|
|
1090
784
|
menuWidth: menuWidth,
|
|
1091
785
|
placeholder: filters.length === 0 ? placeholder : '',
|
|
1092
|
-
hasAutoFocus:
|
|
786
|
+
hasAutoFocus: hasAutoFocus,
|
|
1093
787
|
hasClear: hasClear && !isReadOnly,
|
|
1094
788
|
startIcon: startIcon,
|
|
1095
789
|
endContent: combinedEndContent,
|
|
@@ -1101,8 +795,8 @@ export function PowerSearch({
|
|
|
1101
795
|
debounceMs: 0,
|
|
1102
796
|
status: status,
|
|
1103
797
|
statusVariant: statusVariant,
|
|
1104
|
-
onFocus:
|
|
1105
|
-
onBlur:
|
|
798
|
+
onFocus: onFocus,
|
|
799
|
+
onBlur: onBlur,
|
|
1106
800
|
containerXstyle: xstyle,
|
|
1107
801
|
containerClassName: className,
|
|
1108
802
|
containerStyle: style,
|
|
@@ -1110,7 +804,7 @@ export function PowerSearch({
|
|
|
1110
804
|
})
|
|
1111
805
|
})
|
|
1112
806
|
})
|
|
1113
|
-
}
|
|
807
|
+
}), popover.render(popoverContent, {
|
|
1114
808
|
placement: 'below',
|
|
1115
809
|
alignment: 'start',
|
|
1116
810
|
offset: spacingVars['--spacing-1'],
|