@caratlogic/design-system 0.1.43 → 0.1.45
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/dist/components/molecules/FloatingSlideOver/FloatingSlideOver.d.ts +11 -0
- package/dist/components/molecules/FloatingSlideOver/FloatingSlideOver.d.ts.map +1 -0
- package/dist/components/molecules/FloatingSlideOver/FloatingSlideOver.hooks.d.ts +23 -0
- package/dist/components/molecules/FloatingSlideOver/FloatingSlideOver.hooks.d.ts.map +1 -0
- package/dist/components/molecules/FloatingSlideOver/FloatingSlideOver.types.d.ts +19 -0
- package/dist/components/molecules/FloatingSlideOver/FloatingSlideOver.types.d.ts.map +1 -0
- package/dist/components/molecules/FloatingSlideOver/FloatingSlideOver.utils.d.ts +9 -0
- package/dist/components/molecules/FloatingSlideOver/FloatingSlideOver.utils.d.ts.map +1 -0
- package/dist/components/molecules/FloatingSlideOver/index.d.ts +3 -0
- package/dist/components/molecules/FloatingSlideOver/index.d.ts.map +1 -0
- package/dist/components/molecules/Sidebar/Sidebar.parts.d.ts.map +1 -1
- package/dist/components/molecules/SlideOut/SlideOut.parts.d.ts +2 -0
- package/dist/components/molecules/SlideOut/SlideOut.parts.d.ts.map +1 -1
- package/dist/components/organisms/Filters/FilterSurface/FilterSurface.accessibility.d.ts +4 -0
- package/dist/components/organisms/Filters/FilterSurface/FilterSurface.accessibility.d.ts.map +1 -1
- package/dist/components/organisms/Filters/FilterSurface/FilterSurface.d.ts +9 -4
- package/dist/components/organisms/Filters/FilterSurface/FilterSurface.d.ts.map +1 -1
- package/dist/components/organisms/Filters/FilterSurface/FilterSurface.hooks.d.ts +33 -2
- package/dist/components/organisms/Filters/FilterSurface/FilterSurface.hooks.d.ts.map +1 -1
- package/dist/components/organisms/Filters/FilterSurface/FilterSurface.parts.d.ts +12 -1
- package/dist/components/organisms/Filters/FilterSurface/FilterSurface.parts.d.ts.map +1 -1
- package/dist/components/organisms/Filters/FilterSurface/FilterSurface.types.d.ts +95 -2
- package/dist/components/organisms/Filters/FilterSurface/FilterSurface.types.d.ts.map +1 -1
- package/dist/components/organisms/Filters/FilterSurface/FilterSurface.utils.d.ts +32 -0
- package/dist/components/organisms/Filters/FilterSurface/FilterSurface.utils.d.ts.map +1 -1
- package/dist/components/organisms/Filters/FilterSurface/index.d.ts +2 -2
- package/dist/components/organisms/Filters/FilterSurface/index.d.ts.map +1 -1
- package/dist/index.cjs.js +1026 -49
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +1025 -50
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -22650,6 +22650,20 @@ function distanceBetween(p1, p2) {
|
|
|
22650
22650
|
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
|
|
22651
22651
|
}
|
|
22652
22652
|
|
|
22653
|
+
function getRelativeTransformOrigin(event, rect) {
|
|
22654
|
+
const eventCoordinates = getEventCoordinates(event);
|
|
22655
|
+
|
|
22656
|
+
if (!eventCoordinates) {
|
|
22657
|
+
return '0 0';
|
|
22658
|
+
}
|
|
22659
|
+
|
|
22660
|
+
const transformOrigin = {
|
|
22661
|
+
x: (eventCoordinates.x - rect.left) / rect.width * 100,
|
|
22662
|
+
y: (eventCoordinates.y - rect.top) / rect.height * 100
|
|
22663
|
+
};
|
|
22664
|
+
return transformOrigin.x + "% " + transformOrigin.y + "%";
|
|
22665
|
+
}
|
|
22666
|
+
|
|
22653
22667
|
/**
|
|
22654
22668
|
* Sort collisions from smallest to greatest value
|
|
22655
22669
|
*/
|
|
@@ -25934,6 +25948,396 @@ function useDroppable(_ref) {
|
|
|
25934
25948
|
};
|
|
25935
25949
|
}
|
|
25936
25950
|
|
|
25951
|
+
function AnimationManager(_ref) {
|
|
25952
|
+
let {
|
|
25953
|
+
animation,
|
|
25954
|
+
children
|
|
25955
|
+
} = _ref;
|
|
25956
|
+
const [clonedChildren, setClonedChildren] = useState(null);
|
|
25957
|
+
const [element, setElement] = useState(null);
|
|
25958
|
+
const previousChildren = usePrevious(children);
|
|
25959
|
+
|
|
25960
|
+
if (!children && !clonedChildren && previousChildren) {
|
|
25961
|
+
setClonedChildren(previousChildren);
|
|
25962
|
+
}
|
|
25963
|
+
|
|
25964
|
+
useIsomorphicLayoutEffect$1(() => {
|
|
25965
|
+
if (!element) {
|
|
25966
|
+
return;
|
|
25967
|
+
}
|
|
25968
|
+
|
|
25969
|
+
const key = clonedChildren == null ? void 0 : clonedChildren.key;
|
|
25970
|
+
const id = clonedChildren == null ? void 0 : clonedChildren.props.id;
|
|
25971
|
+
|
|
25972
|
+
if (key == null || id == null) {
|
|
25973
|
+
setClonedChildren(null);
|
|
25974
|
+
return;
|
|
25975
|
+
}
|
|
25976
|
+
|
|
25977
|
+
Promise.resolve(animation(id, element)).then(() => {
|
|
25978
|
+
setClonedChildren(null);
|
|
25979
|
+
});
|
|
25980
|
+
}, [animation, clonedChildren, element]);
|
|
25981
|
+
return React__default.createElement(React__default.Fragment, null, children, clonedChildren ? cloneElement(clonedChildren, {
|
|
25982
|
+
ref: setElement
|
|
25983
|
+
}) : null);
|
|
25984
|
+
}
|
|
25985
|
+
|
|
25986
|
+
const defaultTransform = {
|
|
25987
|
+
x: 0,
|
|
25988
|
+
y: 0,
|
|
25989
|
+
scaleX: 1,
|
|
25990
|
+
scaleY: 1
|
|
25991
|
+
};
|
|
25992
|
+
function NullifiedContextProvider(_ref) {
|
|
25993
|
+
let {
|
|
25994
|
+
children
|
|
25995
|
+
} = _ref;
|
|
25996
|
+
return React__default.createElement(InternalContext.Provider, {
|
|
25997
|
+
value: defaultInternalContext
|
|
25998
|
+
}, React__default.createElement(ActiveDraggableContext.Provider, {
|
|
25999
|
+
value: defaultTransform
|
|
26000
|
+
}, children));
|
|
26001
|
+
}
|
|
26002
|
+
|
|
26003
|
+
const baseStyles = {
|
|
26004
|
+
position: 'fixed',
|
|
26005
|
+
touchAction: 'none'
|
|
26006
|
+
};
|
|
26007
|
+
|
|
26008
|
+
const defaultTransition$1 = activatorEvent => {
|
|
26009
|
+
const isKeyboardActivator = isKeyboardEvent(activatorEvent);
|
|
26010
|
+
return isKeyboardActivator ? 'transform 250ms ease' : undefined;
|
|
26011
|
+
};
|
|
26012
|
+
|
|
26013
|
+
const PositionedOverlay = /*#__PURE__*/forwardRef((_ref, ref) => {
|
|
26014
|
+
let {
|
|
26015
|
+
as,
|
|
26016
|
+
activatorEvent,
|
|
26017
|
+
adjustScale,
|
|
26018
|
+
children,
|
|
26019
|
+
className,
|
|
26020
|
+
rect,
|
|
26021
|
+
style,
|
|
26022
|
+
transform,
|
|
26023
|
+
transition = defaultTransition$1
|
|
26024
|
+
} = _ref;
|
|
26025
|
+
|
|
26026
|
+
if (!rect) {
|
|
26027
|
+
return null;
|
|
26028
|
+
}
|
|
26029
|
+
|
|
26030
|
+
const scaleAdjustedTransform = adjustScale ? transform : { ...transform,
|
|
26031
|
+
scaleX: 1,
|
|
26032
|
+
scaleY: 1
|
|
26033
|
+
};
|
|
26034
|
+
const styles = { ...baseStyles,
|
|
26035
|
+
width: rect.width,
|
|
26036
|
+
height: rect.height,
|
|
26037
|
+
top: rect.top,
|
|
26038
|
+
left: rect.left,
|
|
26039
|
+
transform: CSS$1.Transform.toString(scaleAdjustedTransform),
|
|
26040
|
+
transformOrigin: adjustScale && activatorEvent ? getRelativeTransformOrigin(activatorEvent, rect) : undefined,
|
|
26041
|
+
transition: typeof transition === 'function' ? transition(activatorEvent) : transition,
|
|
26042
|
+
...style
|
|
26043
|
+
};
|
|
26044
|
+
return React__default.createElement(as, {
|
|
26045
|
+
className,
|
|
26046
|
+
style: styles,
|
|
26047
|
+
ref
|
|
26048
|
+
}, children);
|
|
26049
|
+
});
|
|
26050
|
+
|
|
26051
|
+
const defaultDropAnimationSideEffects = options => _ref => {
|
|
26052
|
+
let {
|
|
26053
|
+
active,
|
|
26054
|
+
dragOverlay
|
|
26055
|
+
} = _ref;
|
|
26056
|
+
const originalStyles = {};
|
|
26057
|
+
const {
|
|
26058
|
+
styles,
|
|
26059
|
+
className
|
|
26060
|
+
} = options;
|
|
26061
|
+
|
|
26062
|
+
if (styles != null && styles.active) {
|
|
26063
|
+
for (const [key, value] of Object.entries(styles.active)) {
|
|
26064
|
+
if (value === undefined) {
|
|
26065
|
+
continue;
|
|
26066
|
+
}
|
|
26067
|
+
|
|
26068
|
+
originalStyles[key] = active.node.style.getPropertyValue(key);
|
|
26069
|
+
active.node.style.setProperty(key, value);
|
|
26070
|
+
}
|
|
26071
|
+
}
|
|
26072
|
+
|
|
26073
|
+
if (styles != null && styles.dragOverlay) {
|
|
26074
|
+
for (const [key, value] of Object.entries(styles.dragOverlay)) {
|
|
26075
|
+
if (value === undefined) {
|
|
26076
|
+
continue;
|
|
26077
|
+
}
|
|
26078
|
+
|
|
26079
|
+
dragOverlay.node.style.setProperty(key, value);
|
|
26080
|
+
}
|
|
26081
|
+
}
|
|
26082
|
+
|
|
26083
|
+
if (className != null && className.active) {
|
|
26084
|
+
active.node.classList.add(className.active);
|
|
26085
|
+
}
|
|
26086
|
+
|
|
26087
|
+
if (className != null && className.dragOverlay) {
|
|
26088
|
+
dragOverlay.node.classList.add(className.dragOverlay);
|
|
26089
|
+
}
|
|
26090
|
+
|
|
26091
|
+
return function cleanup() {
|
|
26092
|
+
for (const [key, value] of Object.entries(originalStyles)) {
|
|
26093
|
+
active.node.style.setProperty(key, value);
|
|
26094
|
+
}
|
|
26095
|
+
|
|
26096
|
+
if (className != null && className.active) {
|
|
26097
|
+
active.node.classList.remove(className.active);
|
|
26098
|
+
}
|
|
26099
|
+
};
|
|
26100
|
+
};
|
|
26101
|
+
|
|
26102
|
+
const defaultKeyframeResolver = _ref2 => {
|
|
26103
|
+
let {
|
|
26104
|
+
transform: {
|
|
26105
|
+
initial,
|
|
26106
|
+
final
|
|
26107
|
+
}
|
|
26108
|
+
} = _ref2;
|
|
26109
|
+
return [{
|
|
26110
|
+
transform: CSS$1.Transform.toString(initial)
|
|
26111
|
+
}, {
|
|
26112
|
+
transform: CSS$1.Transform.toString(final)
|
|
26113
|
+
}];
|
|
26114
|
+
};
|
|
26115
|
+
|
|
26116
|
+
const defaultDropAnimationConfiguration = {
|
|
26117
|
+
duration: 250,
|
|
26118
|
+
easing: 'ease',
|
|
26119
|
+
keyframes: defaultKeyframeResolver,
|
|
26120
|
+
sideEffects: /*#__PURE__*/defaultDropAnimationSideEffects({
|
|
26121
|
+
styles: {
|
|
26122
|
+
active: {
|
|
26123
|
+
opacity: '0'
|
|
26124
|
+
}
|
|
26125
|
+
}
|
|
26126
|
+
})
|
|
26127
|
+
};
|
|
26128
|
+
function useDropAnimation(_ref3) {
|
|
26129
|
+
let {
|
|
26130
|
+
config,
|
|
26131
|
+
draggableNodes,
|
|
26132
|
+
droppableContainers,
|
|
26133
|
+
measuringConfiguration
|
|
26134
|
+
} = _ref3;
|
|
26135
|
+
return useEvent((id, node) => {
|
|
26136
|
+
if (config === null) {
|
|
26137
|
+
return;
|
|
26138
|
+
}
|
|
26139
|
+
|
|
26140
|
+
const activeDraggable = draggableNodes.get(id);
|
|
26141
|
+
|
|
26142
|
+
if (!activeDraggable) {
|
|
26143
|
+
return;
|
|
26144
|
+
}
|
|
26145
|
+
|
|
26146
|
+
const activeNode = activeDraggable.node.current;
|
|
26147
|
+
|
|
26148
|
+
if (!activeNode) {
|
|
26149
|
+
return;
|
|
26150
|
+
}
|
|
26151
|
+
|
|
26152
|
+
const measurableNode = getMeasurableNode(node);
|
|
26153
|
+
|
|
26154
|
+
if (!measurableNode) {
|
|
26155
|
+
return;
|
|
26156
|
+
}
|
|
26157
|
+
|
|
26158
|
+
const {
|
|
26159
|
+
transform
|
|
26160
|
+
} = getWindow$1(node).getComputedStyle(node);
|
|
26161
|
+
const parsedTransform = parseTransform(transform);
|
|
26162
|
+
|
|
26163
|
+
if (!parsedTransform) {
|
|
26164
|
+
return;
|
|
26165
|
+
}
|
|
26166
|
+
|
|
26167
|
+
const animation = typeof config === 'function' ? config : createDefaultDropAnimation(config);
|
|
26168
|
+
scrollIntoViewIfNeeded(activeNode, measuringConfiguration.draggable.measure);
|
|
26169
|
+
return animation({
|
|
26170
|
+
active: {
|
|
26171
|
+
id,
|
|
26172
|
+
data: activeDraggable.data,
|
|
26173
|
+
node: activeNode,
|
|
26174
|
+
rect: measuringConfiguration.draggable.measure(activeNode)
|
|
26175
|
+
},
|
|
26176
|
+
draggableNodes,
|
|
26177
|
+
dragOverlay: {
|
|
26178
|
+
node,
|
|
26179
|
+
rect: measuringConfiguration.dragOverlay.measure(measurableNode)
|
|
26180
|
+
},
|
|
26181
|
+
droppableContainers,
|
|
26182
|
+
measuringConfiguration,
|
|
26183
|
+
transform: parsedTransform
|
|
26184
|
+
});
|
|
26185
|
+
});
|
|
26186
|
+
}
|
|
26187
|
+
|
|
26188
|
+
function createDefaultDropAnimation(options) {
|
|
26189
|
+
const {
|
|
26190
|
+
duration,
|
|
26191
|
+
easing,
|
|
26192
|
+
sideEffects,
|
|
26193
|
+
keyframes
|
|
26194
|
+
} = { ...defaultDropAnimationConfiguration,
|
|
26195
|
+
...options
|
|
26196
|
+
};
|
|
26197
|
+
return _ref4 => {
|
|
26198
|
+
let {
|
|
26199
|
+
active,
|
|
26200
|
+
dragOverlay,
|
|
26201
|
+
transform,
|
|
26202
|
+
...rest
|
|
26203
|
+
} = _ref4;
|
|
26204
|
+
|
|
26205
|
+
if (!duration) {
|
|
26206
|
+
// Do not animate if animation duration is zero.
|
|
26207
|
+
return;
|
|
26208
|
+
}
|
|
26209
|
+
|
|
26210
|
+
const delta = {
|
|
26211
|
+
x: dragOverlay.rect.left - active.rect.left,
|
|
26212
|
+
y: dragOverlay.rect.top - active.rect.top
|
|
26213
|
+
};
|
|
26214
|
+
const scale = {
|
|
26215
|
+
scaleX: transform.scaleX !== 1 ? active.rect.width * transform.scaleX / dragOverlay.rect.width : 1,
|
|
26216
|
+
scaleY: transform.scaleY !== 1 ? active.rect.height * transform.scaleY / dragOverlay.rect.height : 1
|
|
26217
|
+
};
|
|
26218
|
+
const finalTransform = {
|
|
26219
|
+
x: transform.x - delta.x,
|
|
26220
|
+
y: transform.y - delta.y,
|
|
26221
|
+
...scale
|
|
26222
|
+
};
|
|
26223
|
+
const animationKeyframes = keyframes({ ...rest,
|
|
26224
|
+
active,
|
|
26225
|
+
dragOverlay,
|
|
26226
|
+
transform: {
|
|
26227
|
+
initial: transform,
|
|
26228
|
+
final: finalTransform
|
|
26229
|
+
}
|
|
26230
|
+
});
|
|
26231
|
+
const [firstKeyframe] = animationKeyframes;
|
|
26232
|
+
const lastKeyframe = animationKeyframes[animationKeyframes.length - 1];
|
|
26233
|
+
|
|
26234
|
+
if (JSON.stringify(firstKeyframe) === JSON.stringify(lastKeyframe)) {
|
|
26235
|
+
// The start and end keyframes are the same, infer that there is no animation needed.
|
|
26236
|
+
return;
|
|
26237
|
+
}
|
|
26238
|
+
|
|
26239
|
+
const cleanup = sideEffects == null ? void 0 : sideEffects({
|
|
26240
|
+
active,
|
|
26241
|
+
dragOverlay,
|
|
26242
|
+
...rest
|
|
26243
|
+
});
|
|
26244
|
+
const animation = dragOverlay.node.animate(animationKeyframes, {
|
|
26245
|
+
duration,
|
|
26246
|
+
easing,
|
|
26247
|
+
fill: 'forwards'
|
|
26248
|
+
});
|
|
26249
|
+
return new Promise(resolve => {
|
|
26250
|
+
animation.onfinish = () => {
|
|
26251
|
+
cleanup == null ? void 0 : cleanup();
|
|
26252
|
+
resolve();
|
|
26253
|
+
};
|
|
26254
|
+
});
|
|
26255
|
+
};
|
|
26256
|
+
}
|
|
26257
|
+
|
|
26258
|
+
let key = 0;
|
|
26259
|
+
function useKey(id) {
|
|
26260
|
+
return useMemo(() => {
|
|
26261
|
+
if (id == null) {
|
|
26262
|
+
return;
|
|
26263
|
+
}
|
|
26264
|
+
|
|
26265
|
+
key++;
|
|
26266
|
+
return key;
|
|
26267
|
+
}, [id]);
|
|
26268
|
+
}
|
|
26269
|
+
|
|
26270
|
+
const DragOverlay = /*#__PURE__*/React__default.memo(_ref => {
|
|
26271
|
+
let {
|
|
26272
|
+
adjustScale = false,
|
|
26273
|
+
children,
|
|
26274
|
+
dropAnimation: dropAnimationConfig,
|
|
26275
|
+
style,
|
|
26276
|
+
transition,
|
|
26277
|
+
modifiers,
|
|
26278
|
+
wrapperElement = 'div',
|
|
26279
|
+
className,
|
|
26280
|
+
zIndex = 999
|
|
26281
|
+
} = _ref;
|
|
26282
|
+
const {
|
|
26283
|
+
activatorEvent,
|
|
26284
|
+
active,
|
|
26285
|
+
activeNodeRect,
|
|
26286
|
+
containerNodeRect,
|
|
26287
|
+
draggableNodes,
|
|
26288
|
+
droppableContainers,
|
|
26289
|
+
dragOverlay,
|
|
26290
|
+
over,
|
|
26291
|
+
measuringConfiguration,
|
|
26292
|
+
scrollableAncestors,
|
|
26293
|
+
scrollableAncestorRects,
|
|
26294
|
+
windowRect
|
|
26295
|
+
} = useDndContext();
|
|
26296
|
+
const transform = useContext(ActiveDraggableContext);
|
|
26297
|
+
const key = useKey(active == null ? void 0 : active.id);
|
|
26298
|
+
const modifiedTransform = applyModifiers(modifiers, {
|
|
26299
|
+
activatorEvent,
|
|
26300
|
+
active,
|
|
26301
|
+
activeNodeRect,
|
|
26302
|
+
containerNodeRect,
|
|
26303
|
+
draggingNodeRect: dragOverlay.rect,
|
|
26304
|
+
over,
|
|
26305
|
+
overlayNodeRect: dragOverlay.rect,
|
|
26306
|
+
scrollableAncestors,
|
|
26307
|
+
scrollableAncestorRects,
|
|
26308
|
+
transform,
|
|
26309
|
+
windowRect
|
|
26310
|
+
});
|
|
26311
|
+
const initialRect = useInitialValue(activeNodeRect);
|
|
26312
|
+
const dropAnimation = useDropAnimation({
|
|
26313
|
+
config: dropAnimationConfig,
|
|
26314
|
+
draggableNodes,
|
|
26315
|
+
droppableContainers,
|
|
26316
|
+
measuringConfiguration
|
|
26317
|
+
}); // We need to wait for the active node to be measured before connecting the drag overlay ref
|
|
26318
|
+
// otherwise collisions can be computed against a mispositioned drag overlay
|
|
26319
|
+
|
|
26320
|
+
const ref = initialRect ? dragOverlay.setRef : undefined;
|
|
26321
|
+
return React__default.createElement(NullifiedContextProvider, null, React__default.createElement(AnimationManager, {
|
|
26322
|
+
animation: dropAnimation
|
|
26323
|
+
}, active && key ? React__default.createElement(PositionedOverlay, {
|
|
26324
|
+
key: key,
|
|
26325
|
+
id: active.id,
|
|
26326
|
+
ref: ref,
|
|
26327
|
+
as: wrapperElement,
|
|
26328
|
+
activatorEvent: activatorEvent,
|
|
26329
|
+
adjustScale: adjustScale,
|
|
26330
|
+
className: className,
|
|
26331
|
+
transition: transition,
|
|
26332
|
+
rect: initialRect,
|
|
26333
|
+
style: {
|
|
26334
|
+
zIndex,
|
|
26335
|
+
...style
|
|
26336
|
+
},
|
|
26337
|
+
transform: modifiedTransform
|
|
26338
|
+
}, children) : null));
|
|
26339
|
+
});
|
|
26340
|
+
|
|
25937
26341
|
const PERMISSIONS = {
|
|
25938
26342
|
NONE: 0, // no access
|
|
25939
26343
|
READ: 2, // can only read
|
|
@@ -43398,6 +43802,154 @@ function TriStateFilter({ value, onChange, ariaLabel, compact = false, }) {
|
|
|
43398
43802
|
}) }));
|
|
43399
43803
|
}
|
|
43400
43804
|
|
|
43805
|
+
const SlideOut = ({ open, onOpenChange, ...props }) => {
|
|
43806
|
+
const scheduleLockRelease = useOverlayBodyLockRelease(open);
|
|
43807
|
+
return (jsx(DialogPrimitive.Root, { ...props, open: open, onOpenChange: (next) => {
|
|
43808
|
+
onOpenChange?.(next);
|
|
43809
|
+
if (!next)
|
|
43810
|
+
scheduleLockRelease();
|
|
43811
|
+
} }));
|
|
43812
|
+
};
|
|
43813
|
+
const SlideOutTrigger = DialogPrimitive.Trigger;
|
|
43814
|
+
const SlideOutClose = DialogPrimitive.Close;
|
|
43815
|
+
const SlideOutPortal = DialogPrimitive.Portal;
|
|
43816
|
+
// Overlay
|
|
43817
|
+
const SLIDE_OUT_OVERLAY_CLASS_NAME = 'fixed inset-0 z-40 bg-black/50';
|
|
43818
|
+
const SLIDE_OUT_OVERLAY_BLUR_CLASS_NAME = 'backdrop-blur-sm';
|
|
43819
|
+
/** The slide-outs' backdrop, dimmed and slightly blurred; other panels over the page reuse it to match. */
|
|
43820
|
+
const SLIDE_OUT_BACKDROP_CLASS_NAME = cn(SLIDE_OUT_OVERLAY_CLASS_NAME, SLIDE_OUT_OVERLAY_BLUR_CLASS_NAME);
|
|
43821
|
+
const SlideOutOverlay = React.forwardRef(({ className, ...props }, ref) => (jsx(DialogPrimitive.Overlay, { ref: ref, className: cn(SLIDE_OUT_OVERLAY_CLASS_NAME, className), ...props })));
|
|
43822
|
+
SlideOutOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
43823
|
+
// Positional classes per edge. `right` is the historical default and its
|
|
43824
|
+
// value is byte-for-byte what SlideOutContent always rendered.
|
|
43825
|
+
const slideOutSideClasses = {
|
|
43826
|
+
right: 'right-0 top-0 h-full w-[488px] max-w-full border-l slide-in-from-right',
|
|
43827
|
+
left: 'left-0 top-0 h-full w-[488px] max-w-full border-r slide-in-from-left',
|
|
43828
|
+
top: 'inset-x-0 top-0 h-1/3 w-full border-b slide-in-from-top',
|
|
43829
|
+
bottom: 'inset-x-0 bottom-0 h-1/3 w-full border-t slide-in-from-bottom',
|
|
43830
|
+
};
|
|
43831
|
+
// Content — slide-out panel. Defaults to a right-anchored 488px drawer;
|
|
43832
|
+
// pass `side` to anchor to any edge (absorbs the old sheet/drawer use cases).
|
|
43833
|
+
const SlideOutContent = React.forwardRef(({ className, children, overlayClassName, side = 'right', ...props }, ref) => (jsxs(SlideOutPortal, { children: [jsx(SlideOutOverlay, { className: overlayClassName ?? SLIDE_OUT_OVERLAY_BLUR_CLASS_NAME }), jsx(DialogPrimitive.Content, { ref: ref, className: cn('fixed z-50 border-border bg-card text-card-foreground shadow-xl animate-in', slideOutSideClasses[side], className), ...props, children: children })] })));
|
|
43834
|
+
SlideOutContent.displayName = DialogPrimitive.Content.displayName;
|
|
43835
|
+
// Header — owns the standard 16px padding and bottom border.
|
|
43836
|
+
const SlideOutHeader = ({ className, ...props }) => (jsx("div", { className: cn('flex flex-col space-y-1.5 border-b border-border px-4 py-4 text-xs', className), ...props }));
|
|
43837
|
+
SlideOutHeader.displayName = 'SlideOutHeader';
|
|
43838
|
+
// Title
|
|
43839
|
+
const SlideOutTitle = React.forwardRef(({ className, ...props }, ref) => (jsx(DialogPrimitive.Title, { ref: ref, className: cn('text-lg font-semibold', className), ...props })));
|
|
43840
|
+
SlideOutTitle.displayName = DialogPrimitive.Title.displayName;
|
|
43841
|
+
// Description
|
|
43842
|
+
const SlideOutDescription = React.forwardRef(({ className, ...props }, ref) => (jsx(DialogPrimitive.Description, { ref: ref, className: cn('text-sm text-muted-foreground', className), ...props })));
|
|
43843
|
+
SlideOutDescription.displayName = DialogPrimitive.Description.displayName;
|
|
43844
|
+
|
|
43845
|
+
/** The app's content area, right of the sidebar; the panel starts at its left edge. */
|
|
43846
|
+
const SIDEBAR_INSET_SELECTOR = '[data-slot="sidebar-inset"]';
|
|
43847
|
+
/** Dropdowns, menus and listboxes, portaled outside the panel; an outside click first closes them. */
|
|
43848
|
+
const OPEN_LAYER_SELECTOR = '[data-slot="popover-content"], [role="menu"], [role="listbox"]';
|
|
43849
|
+
/** How long the panel takes to slide out; it stays mounted until then. */
|
|
43850
|
+
const SLIDE_OUT_MS = 200;
|
|
43851
|
+
/** The top-level element under `<body>` that holds `node`: the app root, for a node in the page. */
|
|
43852
|
+
function getBodyChild(node) {
|
|
43853
|
+
let current = node;
|
|
43854
|
+
while (current && current.parentElement !== node.ownerDocument.body)
|
|
43855
|
+
current = current.parentElement;
|
|
43856
|
+
return current;
|
|
43857
|
+
}
|
|
43858
|
+
|
|
43859
|
+
/**
|
|
43860
|
+
* Backdrop handlers that call `onClose` on a click outside the panel, unless a dropdown or menu was open
|
|
43861
|
+
* when the press began: that click only closes the dropdown.
|
|
43862
|
+
*/
|
|
43863
|
+
function useBackdropClose(onClose) {
|
|
43864
|
+
const layerOpenRef = useRef(false);
|
|
43865
|
+
return {
|
|
43866
|
+
onPointerDown: () => {
|
|
43867
|
+
layerOpenRef.current = !!document.querySelector(OPEN_LAYER_SELECTOR);
|
|
43868
|
+
},
|
|
43869
|
+
onClick: () => {
|
|
43870
|
+
if (!layerOpenRef.current)
|
|
43871
|
+
onClose?.();
|
|
43872
|
+
layerOpenRef.current = false;
|
|
43873
|
+
},
|
|
43874
|
+
};
|
|
43875
|
+
}
|
|
43876
|
+
/** Keeps the panel mounted while it slides out; `closing` is true for that time. */
|
|
43877
|
+
function useSlideOverPresence(open) {
|
|
43878
|
+
const [mounted, setMounted] = useState(open);
|
|
43879
|
+
useEffect(() => {
|
|
43880
|
+
if (open) {
|
|
43881
|
+
setMounted(true);
|
|
43882
|
+
return;
|
|
43883
|
+
}
|
|
43884
|
+
const timer = window.setTimeout(() => setMounted(false), SLIDE_OUT_MS);
|
|
43885
|
+
return () => window.clearTimeout(timer);
|
|
43886
|
+
}, [open]);
|
|
43887
|
+
return { mounted: mounted || open, closing: mounted && !open };
|
|
43888
|
+
}
|
|
43889
|
+
/** Where the content area right of the sidebar starts, in px from the viewport's left; 0 without a sidebar. */
|
|
43890
|
+
function useSidebarInsetLeft(active) {
|
|
43891
|
+
const [left, setLeft] = useState(0);
|
|
43892
|
+
useLayoutEffect(() => {
|
|
43893
|
+
if (!active)
|
|
43894
|
+
return;
|
|
43895
|
+
const inset = document.querySelector(SIDEBAR_INSET_SELECTOR);
|
|
43896
|
+
if (!inset)
|
|
43897
|
+
return;
|
|
43898
|
+
const measure = () => setLeft(Math.max(0, inset.getBoundingClientRect().left));
|
|
43899
|
+
measure();
|
|
43900
|
+
// The inset narrows or widens with the window and the sidebar.
|
|
43901
|
+
const observer = new ResizeObserver(measure);
|
|
43902
|
+
observer.observe(inset);
|
|
43903
|
+
window.addEventListener('resize', measure);
|
|
43904
|
+
return () => {
|
|
43905
|
+
observer.disconnect();
|
|
43906
|
+
window.removeEventListener('resize', measure);
|
|
43907
|
+
};
|
|
43908
|
+
}, [active]);
|
|
43909
|
+
return left;
|
|
43910
|
+
}
|
|
43911
|
+
/**
|
|
43912
|
+
* While `active`, makes the app behind the panel inert (no clicks, focus or screen reader) and moves focus
|
|
43913
|
+
* into `panel`; on close, focus goes back where it was. Popovers and menus portal outside the app root, so
|
|
43914
|
+
* they stay usable.
|
|
43915
|
+
*/
|
|
43916
|
+
function useModalPanel(anchor, panel, active) {
|
|
43917
|
+
useEffect(() => {
|
|
43918
|
+
const root = anchor.current && getBodyChild(anchor.current);
|
|
43919
|
+
if (!active || !(root instanceof HTMLElement))
|
|
43920
|
+
return;
|
|
43921
|
+
const previousFocus = document.activeElement;
|
|
43922
|
+
const wasInert = root.inert;
|
|
43923
|
+
root.inert = true;
|
|
43924
|
+
panel.current?.focus({ preventScroll: true });
|
|
43925
|
+
return () => {
|
|
43926
|
+
root.inert = wasInert;
|
|
43927
|
+
if (previousFocus instanceof HTMLElement)
|
|
43928
|
+
previousFocus.focus({ preventScroll: true });
|
|
43929
|
+
};
|
|
43930
|
+
}, [anchor, panel, active]);
|
|
43931
|
+
}
|
|
43932
|
+
|
|
43933
|
+
/**
|
|
43934
|
+
* A large panel that slides in from the right over the page and covers everything right of the sidebar,
|
|
43935
|
+
* floating with a small gap on every side and rounded corners, on the slide-outs' dimmed, slightly blurred
|
|
43936
|
+
* backdrop. The page behind, sidebar included, can't be used until it closes. A click outside calls
|
|
43937
|
+
* `onClose`; the content closes it otherwise (a close button, Escape).
|
|
43938
|
+
*/
|
|
43939
|
+
function FloatingSlideOver({ open, title, onClose, className, children, }) {
|
|
43940
|
+
const anchorRef = useRef(null);
|
|
43941
|
+
const panelRef = useRef(null);
|
|
43942
|
+
const { mounted, closing } = useSlideOverPresence(open);
|
|
43943
|
+
const left = useSidebarInsetLeft(mounted);
|
|
43944
|
+
useModalPanel(anchorRef, panelRef, mounted);
|
|
43945
|
+
const backdrop = useBackdropClose(onClose);
|
|
43946
|
+
const state = closing ? 'closed' : 'open';
|
|
43947
|
+
return (jsxs(Fragment$2, { children: [jsx("span", { ref: anchorRef, hidden: true }), mounted &&
|
|
43948
|
+
createPortal(jsxs(Fragment$2, { children: [jsx("div", { "aria-hidden": "true", "data-state": state, className: SLIDE_OUT_BACKDROP_CLASS_NAME, onPointerDown: backdrop.onPointerDown, onClick: backdrop.onClick }), jsx("div", { ref: panelRef, role: "dialog", "aria-modal": "true", "aria-label": title, tabIndex: -1, "data-state": state,
|
|
43949
|
+
// The same gap from the sidebar's edge as on the other sides.
|
|
43950
|
+
style: { left: `calc(${left}px + 0.5rem)` }, className: cn('fixed inset-y-2 right-2 z-50 flex flex-col overflow-hidden rounded-xl border border-border bg-background shadow-xl outline-none', 'data-[state=open]:animate-in data-[state=open]:slide-in-from-right data-[state=open]:duration-300 data-[state=open]:ease-out', 'data-[state=closed]:animate-out data-[state=closed]:slide-out-to-right data-[state=closed]:duration-200 data-[state=closed]:ease-in', 'motion-reduce:animate-none', className), children: children })] }), document.body)] }));
|
|
43951
|
+
}
|
|
43952
|
+
|
|
43401
43953
|
/** Read-only filter summaries of a saved search, as pills; optionally one line ending in "+N more". */
|
|
43402
43954
|
function SavedSearchChipList({ chips, emptyText = 'No filters', collapsible = false, className, }) {
|
|
43403
43955
|
const { listRef, expanded, toggle, visibleChips, hiddenCount } = useChipOverflow(chips, collapsible);
|
|
@@ -73045,7 +73597,7 @@ const SidebarRail = React.forwardRef(({ className, ...props }, ref) => {
|
|
|
73045
73597
|
return (jsx("button", { ref: ref, "data-sidebar": "rail", "aria-label": "Toggle Sidebar", tabIndex: -1, onClick: toggleSidebar, title: "Toggle Sidebar", className: cn('absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex', '[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize', '[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize', 'group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar', 'group-data-[side=left][data-collapsible=offcanvas]:-right-2', 'group-data-[side=right][data-collapsible=offcanvas]:-left-2', className), ...props }));
|
|
73046
73598
|
});
|
|
73047
73599
|
SidebarRail.displayName = 'SidebarRail';
|
|
73048
|
-
const SidebarInset = React.forwardRef(({ className, ...props }, ref) => (jsx("main", { ref: ref, className: cn('relative flex min-h-screen flex-1 flex-col bg-background', 'peer-data-[variant=inset]:min-h-[calc(100svh-1rem)] md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow', className), ...props })));
|
|
73600
|
+
const SidebarInset = React.forwardRef(({ className, ...props }, ref) => (jsx("main", { ref: ref, "data-slot": "sidebar-inset", className: cn('relative flex min-h-screen flex-1 flex-col bg-background', 'peer-data-[variant=inset]:min-h-[calc(100svh-1rem)] md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow', className), ...props })));
|
|
73049
73601
|
SidebarInset.displayName = 'SidebarInset';
|
|
73050
73602
|
const SidebarInput = React.forwardRef(({ className, ...props }, ref) => (jsx("input", { ref: ref, "data-sidebar": "input", className: cn('h-8 w-full bg-background text-sm shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring', className), ...props })));
|
|
73051
73603
|
SidebarInput.displayName = 'SidebarInput';
|
|
@@ -73183,42 +73735,6 @@ const AppSidebar = ({ brand, navGroups = [], footer, className, }) => {
|
|
|
73183
73735
|
return (jsxs(Sidebar, { collapsible: "icon", className: className, children: [brand && (jsx(SidebarHeader, { children: jsx(BrandHeader$1, { brand: brand }) })), jsx(SidebarContent, { children: navGroups.map((group) => (jsx(NavGroupSection, { group: group }, group.label ?? 'nav-group'))) }), footer && jsx(SidebarFooter, { children: footer }), jsx(SidebarRail, {})] }));
|
|
73184
73736
|
};
|
|
73185
73737
|
|
|
73186
|
-
const SlideOut = ({ open, onOpenChange, ...props }) => {
|
|
73187
|
-
const scheduleLockRelease = useOverlayBodyLockRelease(open);
|
|
73188
|
-
return (jsx(DialogPrimitive.Root, { ...props, open: open, onOpenChange: (next) => {
|
|
73189
|
-
onOpenChange?.(next);
|
|
73190
|
-
if (!next)
|
|
73191
|
-
scheduleLockRelease();
|
|
73192
|
-
} }));
|
|
73193
|
-
};
|
|
73194
|
-
const SlideOutTrigger = DialogPrimitive.Trigger;
|
|
73195
|
-
const SlideOutClose = DialogPrimitive.Close;
|
|
73196
|
-
const SlideOutPortal = DialogPrimitive.Portal;
|
|
73197
|
-
// Overlay
|
|
73198
|
-
const SlideOutOverlay = React.forwardRef(({ className, ...props }, ref) => (jsx(DialogPrimitive.Overlay, { ref: ref, className: cn('fixed inset-0 z-40 bg-black/50', className), ...props })));
|
|
73199
|
-
SlideOutOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
73200
|
-
// Positional classes per edge. `right` is the historical default and its
|
|
73201
|
-
// value is byte-for-byte what SlideOutContent always rendered.
|
|
73202
|
-
const slideOutSideClasses = {
|
|
73203
|
-
right: 'right-0 top-0 h-full w-[488px] max-w-full border-l slide-in-from-right',
|
|
73204
|
-
left: 'left-0 top-0 h-full w-[488px] max-w-full border-r slide-in-from-left',
|
|
73205
|
-
top: 'inset-x-0 top-0 h-1/3 w-full border-b slide-in-from-top',
|
|
73206
|
-
bottom: 'inset-x-0 bottom-0 h-1/3 w-full border-t slide-in-from-bottom',
|
|
73207
|
-
};
|
|
73208
|
-
// Content — slide-out panel. Defaults to a right-anchored 488px drawer;
|
|
73209
|
-
// pass `side` to anchor to any edge (absorbs the old sheet/drawer use cases).
|
|
73210
|
-
const SlideOutContent = React.forwardRef(({ className, children, overlayClassName, side = 'right', ...props }, ref) => (jsxs(SlideOutPortal, { children: [jsx(SlideOutOverlay, { className: overlayClassName ?? 'backdrop-blur-sm' }), jsx(DialogPrimitive.Content, { ref: ref, className: cn('fixed z-50 border-border bg-card text-card-foreground shadow-xl animate-in', slideOutSideClasses[side], className), ...props, children: children })] })));
|
|
73211
|
-
SlideOutContent.displayName = DialogPrimitive.Content.displayName;
|
|
73212
|
-
// Header — owns the standard 16px padding and bottom border.
|
|
73213
|
-
const SlideOutHeader = ({ className, ...props }) => (jsx("div", { className: cn('flex flex-col space-y-1.5 border-b border-border px-4 py-4 text-xs', className), ...props }));
|
|
73214
|
-
SlideOutHeader.displayName = 'SlideOutHeader';
|
|
73215
|
-
// Title
|
|
73216
|
-
const SlideOutTitle = React.forwardRef(({ className, ...props }, ref) => (jsx(DialogPrimitive.Title, { ref: ref, className: cn('text-lg font-semibold', className), ...props })));
|
|
73217
|
-
SlideOutTitle.displayName = DialogPrimitive.Title.displayName;
|
|
73218
|
-
// Description
|
|
73219
|
-
const SlideOutDescription = React.forwardRef(({ className, ...props }, ref) => (jsx(DialogPrimitive.Description, { ref: ref, className: cn('text-sm text-muted-foreground', className), ...props })));
|
|
73220
|
-
SlideOutDescription.displayName = DialogPrimitive.Description.displayName;
|
|
73221
|
-
|
|
73222
73738
|
const SpecList = ({ rows, zebra = true, className, }) => {
|
|
73223
73739
|
const visible = rows.filter((r) => !r.hidden);
|
|
73224
73740
|
if (visible.length === 0)
|
|
@@ -77452,11 +77968,30 @@ function FilterField(props) {
|
|
|
77452
77968
|
|
|
77453
77969
|
/** Leaves without applying; the draft is discarded. */
|
|
77454
77970
|
const BACK_LABEL = 'Back without applying';
|
|
77971
|
+
const CLOSE_LABEL = 'Close without applying';
|
|
77455
77972
|
const LOADING_LABEL = 'Loading filters';
|
|
77456
77973
|
const ERROR_TITLE = "Couldn't load filters";
|
|
77457
77974
|
const DEFAULT_ERROR_MESSAGE = 'Something went wrong while loading the filters. Check your connection and try again.';
|
|
77458
77975
|
const RETRY_LABEL = 'Try again';
|
|
77976
|
+
const CARD_REORDER_HINT = 'Drag to rearrange';
|
|
77977
|
+
const getCardGripLabel = (card) => `Move ${card}`;
|
|
77978
|
+
const EMPTY_GROUP_LABEL = 'Drag filter cards here';
|
|
77459
77979
|
|
|
77980
|
+
/** Popovers, dialogs, menus and listboxes opened on top of the surface. */
|
|
77981
|
+
const NESTED_LAYER_SELECTOR = '[data-slot="popover-content"], [role="dialog"], [role="menu"], [role="listbox"]';
|
|
77982
|
+
/**
|
|
77983
|
+
* Closes the open popover or menu (not one that holds `from`) as Escape would. Radix closes a popover on
|
|
77984
|
+
* the click after an outside press, which a card drag never makes, so a grab would leave it open.
|
|
77985
|
+
*/
|
|
77986
|
+
function dismissOpenLayer(from) {
|
|
77987
|
+
const layer = Array.from(from.ownerDocument.querySelectorAll(NESTED_LAYER_SELECTOR)).find((node) => !node.contains(from));
|
|
77988
|
+
// Sent from inside the layer, so the surface's own Escape handler leaves it alone.
|
|
77989
|
+
layer?.dispatchEvent(new KeyboardEvent('keydown', {
|
|
77990
|
+
key: 'Escape',
|
|
77991
|
+
bubbles: true,
|
|
77992
|
+
cancelable: true,
|
|
77993
|
+
}));
|
|
77994
|
+
}
|
|
77460
77995
|
/** Placeholder cards while the filters load; roughly the first rows of a card grid. */
|
|
77461
77996
|
const SKELETON_CARD_COUNT = 8;
|
|
77462
77997
|
const SKELETON_GRID_CLASS_NAME = 'grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4';
|
|
@@ -77466,8 +78001,82 @@ const MASONRY_ROW_PX = 4;
|
|
|
77466
78001
|
const getMasonrySpan = (height) => height > 0 ? Math.ceil(height / MASONRY_ROW_PX) : 0;
|
|
77467
78002
|
/** Dense 4px rows; the vertical gap comes from each item's bottom padding. */
|
|
77468
78003
|
const MASONRY_GRID_CLASS_NAME = 'grid-flow-row-dense auto-rows-[4px] gap-x-3';
|
|
78004
|
+
// Card drag: the DOM marks each card, group grid and "More filters" toggle, so a pointer hit is found by attribute.
|
|
78005
|
+
const CARD_ID_ATTR = 'data-filter-card-id';
|
|
78006
|
+
const GROUP_ID_ATTR = 'data-filter-group-id';
|
|
78007
|
+
const MORE_TOGGLE_ATTR = 'data-filter-more-toggle';
|
|
78008
|
+
const CARD_BODY_ATTR = 'data-filter-card-body';
|
|
78009
|
+
/** The group holding `id`, if any. */
|
|
78010
|
+
function findCardGroup(layout, id) {
|
|
78011
|
+
return Object.keys(layout).find((group) => layout[group].includes(id));
|
|
78012
|
+
}
|
|
78013
|
+
/** `layout` with `id` taken out of its group and put into `target.group`, beside `target.key` or at the end. */
|
|
78014
|
+
function moveCard(layout, id, target) {
|
|
78015
|
+
const rest = (layout[target.group] ?? []).filter((key) => key !== id);
|
|
78016
|
+
let at = rest.length;
|
|
78017
|
+
if (target.key !== undefined) {
|
|
78018
|
+
const index = rest.indexOf(target.key);
|
|
78019
|
+
if (index === -1)
|
|
78020
|
+
return layout;
|
|
78021
|
+
at = index + (target.side === 'after' ? 1 : 0);
|
|
78022
|
+
}
|
|
78023
|
+
const next = Object.fromEntries(Object.entries(layout).map(([group, ids]) => [
|
|
78024
|
+
group,
|
|
78025
|
+
ids.filter((key) => key !== id),
|
|
78026
|
+
]));
|
|
78027
|
+
next[target.group] = [...rest.slice(0, at), id, ...rest.slice(at)];
|
|
78028
|
+
return next;
|
|
78029
|
+
}
|
|
78030
|
+
function isSameLayout(a, b) {
|
|
78031
|
+
const groups = Object.keys(a);
|
|
78032
|
+
return (groups.length === Object.keys(b).length &&
|
|
78033
|
+
groups.every((group) => b[group]?.length === a[group].length &&
|
|
78034
|
+
a[group].every((id, index) => b[group][index] === id)));
|
|
78035
|
+
}
|
|
78036
|
+
/**
|
|
78037
|
+
* Where a card lands when dropped on `hit` at height `y`. In its own group it takes the hit card's place
|
|
78038
|
+
* (after it when moving forward), the way a sortable list swaps; from another group the pointer's half
|
|
78039
|
+
* of the hit card decides.
|
|
78040
|
+
*/
|
|
78041
|
+
function getCardDropTarget(layout, activeId, hit, y) {
|
|
78042
|
+
const ids = layout[hit.group] ?? [];
|
|
78043
|
+
const from = ids.indexOf(activeId);
|
|
78044
|
+
const side = from === -1
|
|
78045
|
+
? y > hit.rect.top + hit.rect.height / 2
|
|
78046
|
+
? 'after'
|
|
78047
|
+
: 'before'
|
|
78048
|
+
: from < ids.indexOf(hit.id)
|
|
78049
|
+
? 'after'
|
|
78050
|
+
: 'before';
|
|
78051
|
+
return { group: hit.group, key: hit.id, side };
|
|
78052
|
+
}
|
|
78053
|
+
/** The card, group or "More filters" toggle at a viewport point. */
|
|
78054
|
+
function getDropHit(x, y) {
|
|
78055
|
+
const element = document.elementFromPoint(x, y);
|
|
78056
|
+
if (!element)
|
|
78057
|
+
return null;
|
|
78058
|
+
const group = element.closest(`[${GROUP_ID_ATTR}]`);
|
|
78059
|
+
const groupId = group?.getAttribute(GROUP_ID_ATTR);
|
|
78060
|
+
const card = element.closest(`[${CARD_ID_ATTR}]`);
|
|
78061
|
+
const cardId = card?.getAttribute(CARD_ID_ATTR);
|
|
78062
|
+
if (card && cardId && groupId)
|
|
78063
|
+
return {
|
|
78064
|
+
kind: 'card',
|
|
78065
|
+
id: cardId,
|
|
78066
|
+
group: groupId,
|
|
78067
|
+
rect: card.getBoundingClientRect(),
|
|
78068
|
+
};
|
|
78069
|
+
if (groupId)
|
|
78070
|
+
return { kind: 'group', group: groupId };
|
|
78071
|
+
const toggle = element.closest(`[${MORE_TOGGLE_ATTR}]`);
|
|
78072
|
+
return toggle ? { kind: 'more', toggle } : null;
|
|
78073
|
+
}
|
|
78074
|
+
/** The dropped card's copy settles into its slot at the speed the other cards slide. */
|
|
78075
|
+
const CARD_DROP_ANIMATION = {
|
|
78076
|
+
duration: 200,
|
|
78077
|
+
easing: 'ease',
|
|
78078
|
+
};
|
|
77469
78079
|
|
|
77470
|
-
const NESTED_LAYER_SELECTOR = '[data-slot="popover-content"], [role="dialog"], [role="menu"], [role="listbox"]';
|
|
77471
78080
|
function useCloseOnEscape(onClose) {
|
|
77472
78081
|
useEffect(() => {
|
|
77473
78082
|
const handleKeyDown = (event) => {
|
|
@@ -77485,12 +78094,27 @@ function useCloseOnEscape(onClose) {
|
|
|
77485
78094
|
}
|
|
77486
78095
|
function useFilterSurfaceMore(defaultExpanded = false) {
|
|
77487
78096
|
const [expanded, setExpanded] = useState(defaultExpanded);
|
|
77488
|
-
|
|
78097
|
+
const [toggleNode, setToggleNode] = useState(null);
|
|
78098
|
+
const registerExpander = useContext(FilterSurfaceSortableContext)?.registerExpander;
|
|
78099
|
+
// Inside a sortable surface, a dragged card resting on the toggle opens the section.
|
|
78100
|
+
useEffect(() => {
|
|
78101
|
+
if (!toggleNode || !registerExpander)
|
|
78102
|
+
return;
|
|
78103
|
+
return registerExpander(toggleNode, () => setExpanded(true));
|
|
78104
|
+
}, [toggleNode, registerExpander]);
|
|
78105
|
+
return {
|
|
78106
|
+
expanded,
|
|
78107
|
+
toggle: () => setExpanded((current) => !current),
|
|
78108
|
+
toggleRef: setToggleNode,
|
|
78109
|
+
};
|
|
77489
78110
|
}
|
|
77490
|
-
/**
|
|
77491
|
-
|
|
78111
|
+
/**
|
|
78112
|
+
* Measures a masonry card and keeps its row span in step with its height (content opening, wrapping…).
|
|
78113
|
+
* `initialSpan` lets a remounted card take its known height on the first render.
|
|
78114
|
+
*/
|
|
78115
|
+
function useMasonrySpan(initialSpan = 0) {
|
|
77492
78116
|
const [node, setNode] = useState(null);
|
|
77493
|
-
const [span, setSpan] = useState(
|
|
78117
|
+
const [span, setSpan] = useState(initialSpan);
|
|
77494
78118
|
useEffect(() => {
|
|
77495
78119
|
if (!node)
|
|
77496
78120
|
return;
|
|
@@ -77505,6 +78129,308 @@ function useMasonrySpan() {
|
|
|
77505
78129
|
}, [node]);
|
|
77506
78130
|
return { ref: useCallback((next) => setNode(next), []), span };
|
|
77507
78131
|
}
|
|
78132
|
+
const FilterSurfaceSortableContext = createContext(null);
|
|
78133
|
+
/** The surrounding `FilterSurfaceSortable`, or null outside one. */
|
|
78134
|
+
function useFilterSurfaceSortable() {
|
|
78135
|
+
return useContext(FilterSurfaceSortableContext);
|
|
78136
|
+
}
|
|
78137
|
+
/** A sortable card's drag wiring, masonry span and registration for the slide animation. */
|
|
78138
|
+
function useSortableFilterCard(id) {
|
|
78139
|
+
const sortable = useContext(FilterSurfaceSortableContext);
|
|
78140
|
+
if (!sortable)
|
|
78141
|
+
throw new Error('SortableFilterCard must be inside FilterSurfaceSortable');
|
|
78142
|
+
const { spans, registerCard, unregisterCard } = sortable;
|
|
78143
|
+
const { setNodeRef, setActivatorNodeRef, listeners } = useDraggable({ id });
|
|
78144
|
+
const { ref: spanRef, span } = useMasonrySpan(spans.get(id));
|
|
78145
|
+
const nodeRef = useRef(null);
|
|
78146
|
+
useEffect(() => {
|
|
78147
|
+
if (span > 0)
|
|
78148
|
+
spans.set(id, span);
|
|
78149
|
+
}, [spans, id, span]);
|
|
78150
|
+
const cardRef = useCallback((node) => {
|
|
78151
|
+
setNodeRef(node);
|
|
78152
|
+
if (node)
|
|
78153
|
+
registerCard(id, node);
|
|
78154
|
+
else
|
|
78155
|
+
unregisterCard(id, nodeRef.current);
|
|
78156
|
+
nodeRef.current = node;
|
|
78157
|
+
}, [id, setNodeRef, registerCard, unregisterCard]);
|
|
78158
|
+
return {
|
|
78159
|
+
ref: { card: cardRef, span: spanRef },
|
|
78160
|
+
span,
|
|
78161
|
+
isActive: sortable.activeId === id,
|
|
78162
|
+
dragging: sortable.activeId !== null,
|
|
78163
|
+
label: sortable.cardLabel(id),
|
|
78164
|
+
setActivatorNodeRef,
|
|
78165
|
+
listeners,
|
|
78166
|
+
};
|
|
78167
|
+
}
|
|
78168
|
+
const FLIP_MS = 200;
|
|
78169
|
+
const FLIP_TRANSITION = `transform ${FLIP_MS}ms ease`;
|
|
78170
|
+
// After a move the cards repack and a different card can end up under a still pointer; the pointer must
|
|
78171
|
+
// travel this far before the next move, so cards never rock back and forth on their own.
|
|
78172
|
+
const MOVE_TRAVEL_PX = 32;
|
|
78173
|
+
// Long enough that sweeping past "More filters" doesn't open it.
|
|
78174
|
+
const EXPAND_DELAY_MS = 400;
|
|
78175
|
+
function prefersReducedMotion() {
|
|
78176
|
+
return window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;
|
|
78177
|
+
}
|
|
78178
|
+
/** Slides each card from where it was (`from`) to where the new layout put it. */
|
|
78179
|
+
function playFlip(nodes, from) {
|
|
78180
|
+
nodes.forEach((node, id) => {
|
|
78181
|
+
const before = from.get(id);
|
|
78182
|
+
if (!before)
|
|
78183
|
+
return;
|
|
78184
|
+
const after = node.getBoundingClientRect();
|
|
78185
|
+
const dx = before.left - after.left;
|
|
78186
|
+
const dy = before.top - after.top;
|
|
78187
|
+
if (!dx && !dy)
|
|
78188
|
+
return;
|
|
78189
|
+
node.style.transition = 'none';
|
|
78190
|
+
node.style.transform = `translate(${dx}px, ${dy}px)`;
|
|
78191
|
+
// Commit the offset before transitioning it away.
|
|
78192
|
+
void node.offsetWidth;
|
|
78193
|
+
node.style.transition = FLIP_TRANSITION;
|
|
78194
|
+
node.style.transform = '';
|
|
78195
|
+
node.addEventListener('transitionend', () => {
|
|
78196
|
+
node.style.transition = '';
|
|
78197
|
+
}, { once: true });
|
|
78198
|
+
});
|
|
78199
|
+
}
|
|
78200
|
+
/** A copy of the card for the drag overlay, without ids that would clash with the original. */
|
|
78201
|
+
function cloneCardBody(card) {
|
|
78202
|
+
const body = card?.querySelector(`[${CARD_BODY_ATTR}]`);
|
|
78203
|
+
if (!body)
|
|
78204
|
+
return null;
|
|
78205
|
+
const clone = body.cloneNode(true);
|
|
78206
|
+
if (!(clone instanceof HTMLElement))
|
|
78207
|
+
return null;
|
|
78208
|
+
clone.removeAttribute(CARD_BODY_ATTR);
|
|
78209
|
+
clone.querySelectorAll('[id]').forEach((el) => el.removeAttribute('id'));
|
|
78210
|
+
return clone;
|
|
78211
|
+
}
|
|
78212
|
+
/**
|
|
78213
|
+
* Card drag-to-reorder across a surface's groups. The live order is a draft: cards reflow as the pointer
|
|
78214
|
+
* crosses them and slide (FLIP) from their old spots, and the draft is handed over on drop. The pointer is
|
|
78215
|
+
* hit-tested against what is on screen, so masonry cards of any height land where they look.
|
|
78216
|
+
*/
|
|
78217
|
+
function useFilterCardReorder({ layout, onLayoutChange, }) {
|
|
78218
|
+
const [draft, setDraft] = useState(null);
|
|
78219
|
+
const [activeId, setActiveId] = useState(null);
|
|
78220
|
+
const [overlay, setOverlay] = useState(null);
|
|
78221
|
+
const shown = draft ?? layout;
|
|
78222
|
+
const shownRef = useRef(shown);
|
|
78223
|
+
const activeRef = useRef(null);
|
|
78224
|
+
const nodesRef = useRef(new Map());
|
|
78225
|
+
const spansRef = useRef(new Map());
|
|
78226
|
+
const flipFromRef = useRef(null);
|
|
78227
|
+
const expandersRef = useRef(new Map());
|
|
78228
|
+
useLayoutEffect(() => {
|
|
78229
|
+
shownRef.current = shown;
|
|
78230
|
+
}, [shown]);
|
|
78231
|
+
// A new layout from the consumer (usually the one just dropped) replaces the draft.
|
|
78232
|
+
useEffect(() => {
|
|
78233
|
+
if (activeRef.current === null)
|
|
78234
|
+
setDraft(null);
|
|
78235
|
+
}, [layout]);
|
|
78236
|
+
const applyDraft = useCallback((next) => {
|
|
78237
|
+
if (!prefersReducedMotion()) {
|
|
78238
|
+
const rects = new Map();
|
|
78239
|
+
nodesRef.current.forEach((node, id) => rects.set(id, node.getBoundingClientRect()));
|
|
78240
|
+
flipFromRef.current = rects;
|
|
78241
|
+
}
|
|
78242
|
+
setDraft(next);
|
|
78243
|
+
}, []);
|
|
78244
|
+
useLayoutEffect(() => {
|
|
78245
|
+
const from = flipFromRef.current;
|
|
78246
|
+
if (!from)
|
|
78247
|
+
return;
|
|
78248
|
+
flipFromRef.current = null;
|
|
78249
|
+
playFlip(nodesRef.current, from);
|
|
78250
|
+
}, [draft]);
|
|
78251
|
+
useCardDragTracking(activeId, shownRef, applyDraft, expandersRef.current);
|
|
78252
|
+
const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 4 } }));
|
|
78253
|
+
const registerCard = useCallback((id, node) => {
|
|
78254
|
+
nodesRef.current.set(id, node);
|
|
78255
|
+
}, []);
|
|
78256
|
+
// A card moving between groups remounts; only forget it if the new node hasn't registered already.
|
|
78257
|
+
const unregisterCard = useCallback((id, node) => {
|
|
78258
|
+
if (nodesRef.current.get(id) === node)
|
|
78259
|
+
nodesRef.current.delete(id);
|
|
78260
|
+
}, []);
|
|
78261
|
+
const registerExpander = useCallback((toggle, expand) => {
|
|
78262
|
+
const expanders = expandersRef.current;
|
|
78263
|
+
expanders.set(toggle, expand);
|
|
78264
|
+
return () => {
|
|
78265
|
+
expanders.delete(toggle);
|
|
78266
|
+
};
|
|
78267
|
+
}, []);
|
|
78268
|
+
const onDragStart = useCallback((event) => {
|
|
78269
|
+
const id = String(event.active.id);
|
|
78270
|
+
activeRef.current = id;
|
|
78271
|
+
setOverlay(cloneCardBody(nodesRef.current.get(id)));
|
|
78272
|
+
setActiveId(id);
|
|
78273
|
+
}, []);
|
|
78274
|
+
const finish = useCallback((commit) => {
|
|
78275
|
+
activeRef.current = null;
|
|
78276
|
+
setActiveId(null);
|
|
78277
|
+
setOverlay(null);
|
|
78278
|
+
const next = shownRef.current;
|
|
78279
|
+
if (commit && !isSameLayout(next, layout)) {
|
|
78280
|
+
// The draft stays on screen until the consumer passes the saved layout back.
|
|
78281
|
+
onLayoutChange(next);
|
|
78282
|
+
return;
|
|
78283
|
+
}
|
|
78284
|
+
applyDraft(null);
|
|
78285
|
+
}, [layout, onLayoutChange, applyDraft]);
|
|
78286
|
+
const onDragEnd = useCallback(() => finish(true), [finish]);
|
|
78287
|
+
const onDragCancel = useCallback(() => finish(false), [finish]);
|
|
78288
|
+
return {
|
|
78289
|
+
layout: shown,
|
|
78290
|
+
activeId,
|
|
78291
|
+
overlay,
|
|
78292
|
+
sensors,
|
|
78293
|
+
spans: spansRef.current,
|
|
78294
|
+
registerCard,
|
|
78295
|
+
unregisterCard,
|
|
78296
|
+
registerExpander,
|
|
78297
|
+
onDragStart,
|
|
78298
|
+
onDragEnd,
|
|
78299
|
+
onDragCancel,
|
|
78300
|
+
};
|
|
78301
|
+
}
|
|
78302
|
+
/**
|
|
78303
|
+
* While a card drags: follows the pointer, moves the card in the draft as it crosses other cards or an
|
|
78304
|
+
* empty group, and opens a collapsed "More filters" the pointer rests on.
|
|
78305
|
+
*/
|
|
78306
|
+
function useCardDragTracking(activeId, shownRef, applyDraft, expanders) {
|
|
78307
|
+
useEffect(() => {
|
|
78308
|
+
if (activeId === null)
|
|
78309
|
+
return;
|
|
78310
|
+
let point = null;
|
|
78311
|
+
let frame = null;
|
|
78312
|
+
// Cards are mid-slide until then; hit-testing them would chase a moving target.
|
|
78313
|
+
let settledAt = 0;
|
|
78314
|
+
let settleTimer;
|
|
78315
|
+
// The card last moved beside: staying over it does nothing, or two cards of different heights would swap forever.
|
|
78316
|
+
let lastOver = null;
|
|
78317
|
+
// Where the pointer was at the last move.
|
|
78318
|
+
let movedAt = null;
|
|
78319
|
+
const hasTravelled = (x, y) => !movedAt || Math.hypot(x - movedAt.x, y - movedAt.y) >= MOVE_TRAVEL_PX;
|
|
78320
|
+
let expandTimer;
|
|
78321
|
+
let expandToggle = null;
|
|
78322
|
+
const stopExpand = () => {
|
|
78323
|
+
window.clearTimeout(expandTimer);
|
|
78324
|
+
expandToggle = null;
|
|
78325
|
+
};
|
|
78326
|
+
const handleHit = (hit, x, y) => {
|
|
78327
|
+
if (hit?.kind !== 'more')
|
|
78328
|
+
stopExpand();
|
|
78329
|
+
if (!hit)
|
|
78330
|
+
return;
|
|
78331
|
+
const layout = shownRef.current;
|
|
78332
|
+
if (hit.kind === 'more') {
|
|
78333
|
+
if (hit.toggle === expandToggle)
|
|
78334
|
+
return;
|
|
78335
|
+
stopExpand();
|
|
78336
|
+
const expand = expanders.get(hit.toggle);
|
|
78337
|
+
if (!expand || hit.toggle.getAttribute('aria-expanded') !== 'false')
|
|
78338
|
+
return;
|
|
78339
|
+
expandToggle = hit.toggle;
|
|
78340
|
+
// Not a click: the drag swallows clicks until the drop.
|
|
78341
|
+
expandTimer = window.setTimeout(expand, EXPAND_DELAY_MS);
|
|
78342
|
+
return;
|
|
78343
|
+
}
|
|
78344
|
+
if (!hasTravelled(x, y))
|
|
78345
|
+
return;
|
|
78346
|
+
let next;
|
|
78347
|
+
if (hit.kind === 'group') {
|
|
78348
|
+
// Only an empty group takes a drop here; between cards of a full one the pointer is in a gap.
|
|
78349
|
+
if ((layout[hit.group] ?? []).some((id) => id !== activeId))
|
|
78350
|
+
return;
|
|
78351
|
+
if (findCardGroup(layout, activeId) === hit.group)
|
|
78352
|
+
return;
|
|
78353
|
+
next = moveCard(layout, activeId, { group: hit.group });
|
|
78354
|
+
}
|
|
78355
|
+
else {
|
|
78356
|
+
if (hit.id === activeId) {
|
|
78357
|
+
lastOver = null;
|
|
78358
|
+
return;
|
|
78359
|
+
}
|
|
78360
|
+
if (hit.id === lastOver)
|
|
78361
|
+
return;
|
|
78362
|
+
lastOver = hit.id;
|
|
78363
|
+
next = moveCard(layout, activeId, getCardDropTarget(layout, activeId, hit, y));
|
|
78364
|
+
}
|
|
78365
|
+
if (isSameLayout(next, layout))
|
|
78366
|
+
return;
|
|
78367
|
+
settledAt = performance.now() + FLIP_MS;
|
|
78368
|
+
movedAt = { x, y };
|
|
78369
|
+
applyDraft(next);
|
|
78370
|
+
};
|
|
78371
|
+
const check = () => {
|
|
78372
|
+
frame = null;
|
|
78373
|
+
if (!point)
|
|
78374
|
+
return;
|
|
78375
|
+
const wait = settledAt - performance.now();
|
|
78376
|
+
if (wait > 0) {
|
|
78377
|
+
window.clearTimeout(settleTimer);
|
|
78378
|
+
settleTimer = window.setTimeout(schedule, wait);
|
|
78379
|
+
return;
|
|
78380
|
+
}
|
|
78381
|
+
handleHit(getDropHit(point.x, point.y), point.x, point.y);
|
|
78382
|
+
};
|
|
78383
|
+
const schedule = () => {
|
|
78384
|
+
if (frame === null)
|
|
78385
|
+
frame = requestAnimationFrame(check);
|
|
78386
|
+
};
|
|
78387
|
+
const onPointerMove = (event) => {
|
|
78388
|
+
point = { x: event.clientX, y: event.clientY };
|
|
78389
|
+
schedule();
|
|
78390
|
+
};
|
|
78391
|
+
// Escape cancels the drag; marked handled so the surface doesn't also close.
|
|
78392
|
+
const onKeyDown = (event) => {
|
|
78393
|
+
if (event.key === 'Escape')
|
|
78394
|
+
event.preventDefault();
|
|
78395
|
+
};
|
|
78396
|
+
window.addEventListener('pointermove', onPointerMove);
|
|
78397
|
+
// Auto-scroll moves the cards under a still pointer.
|
|
78398
|
+
window.addEventListener('scroll', schedule, true);
|
|
78399
|
+
window.addEventListener('keydown', onKeyDown, true);
|
|
78400
|
+
return () => {
|
|
78401
|
+
window.removeEventListener('pointermove', onPointerMove);
|
|
78402
|
+
window.removeEventListener('scroll', schedule, true);
|
|
78403
|
+
window.removeEventListener('keydown', onKeyDown, true);
|
|
78404
|
+
if (frame !== null)
|
|
78405
|
+
cancelAnimationFrame(frame);
|
|
78406
|
+
window.clearTimeout(settleTimer);
|
|
78407
|
+
stopExpand();
|
|
78408
|
+
};
|
|
78409
|
+
}, [activeId, shownRef, applyDraft, expanders]);
|
|
78410
|
+
}
|
|
78411
|
+
/** The context the sortable groups and cards read. */
|
|
78412
|
+
function useSortableContextValue(reorder, renderCard, cardLabel) {
|
|
78413
|
+
const { layout, activeId, spans, registerCard, unregisterCard, registerExpander, } = reorder;
|
|
78414
|
+
return useMemo(() => ({
|
|
78415
|
+
layout,
|
|
78416
|
+
activeId,
|
|
78417
|
+
spans,
|
|
78418
|
+
renderCard,
|
|
78419
|
+
cardLabel: cardLabel ?? ((id) => id),
|
|
78420
|
+
registerCard,
|
|
78421
|
+
unregisterCard,
|
|
78422
|
+
registerExpander,
|
|
78423
|
+
}), [
|
|
78424
|
+
layout,
|
|
78425
|
+
activeId,
|
|
78426
|
+
spans,
|
|
78427
|
+
renderCard,
|
|
78428
|
+
cardLabel,
|
|
78429
|
+
registerCard,
|
|
78430
|
+
unregisterCard,
|
|
78431
|
+
registerExpander,
|
|
78432
|
+
]);
|
|
78433
|
+
}
|
|
77508
78434
|
|
|
77509
78435
|
const DEFAULT_SKELETON_CARDS = Array.from({ length: SKELETON_CARD_COUNT }, (_, index) => `card-${index}`);
|
|
77510
78436
|
/** Loading placeholder: the page's own skeleton, or generic list cards. */
|
|
@@ -77520,23 +78446,72 @@ function MasonryItem({ children }) {
|
|
|
77520
78446
|
const { ref, span } = useMasonrySpan();
|
|
77521
78447
|
return (jsx("div", { style: span > 0 ? { gridRowEnd: `span ${span}` } : undefined, children: jsx("div", { ref: ref, className: "pb-3", children: children }) }));
|
|
77522
78448
|
}
|
|
78449
|
+
/**
|
|
78450
|
+
* A grab tab on the middle of the card's top edge, always visible so the cards read as movable, and clear
|
|
78451
|
+
* of the header's title and actions. It lights up with its card on hover. The only place a card drag starts.
|
|
78452
|
+
*/
|
|
78453
|
+
function CardReorderGrip({ label, dragging, setActivatorNodeRef, listeners, }) {
|
|
78454
|
+
return (jsx(TooltipProvider, { delayDuration: 500, children: jsxs(Tooltip, { open: dragging ? false : undefined, children: [jsx(TooltipTrigger, { asChild: true, children: jsx("button", { ref: setActivatorNodeRef, type: "button",
|
|
78455
|
+
// Mouse and touch only, like column reorder.
|
|
78456
|
+
tabIndex: -1, "aria-label": getCardGripLabel(label), className: cn(
|
|
78457
|
+
// The ::before pads the tab's hit area beyond what it shows.
|
|
78458
|
+
'absolute left-1/2 top-0 z-10 flex h-4 w-10 -translate-x-1/2 -translate-y-1/2 cursor-grab touch-none select-none items-center justify-center rounded-full border border-border bg-card text-foreground/50 shadow-sm transition-colors before:absolute before:-inset-2 before:content-[""] active:cursor-grabbing', dragging
|
|
78459
|
+
? 'pointer-events-none'
|
|
78460
|
+
: 'group-hover/card:border-primary/50 group-hover/card:text-primary group-hover/card:hover:border-primary group-hover/card:hover:bg-primary group-hover/card:hover:text-primary-foreground'), onClick: (event) => event.stopPropagation(), ...listeners,
|
|
78461
|
+
// A grab closes any open dropdown first, so it doesn't stay open over the drag.
|
|
78462
|
+
onPointerDown: (event) => {
|
|
78463
|
+
dismissOpenLayer(event.currentTarget);
|
|
78464
|
+
listeners?.onPointerDown?.(event);
|
|
78465
|
+
}, children: jsx(GripHorizontal, { "aria-hidden": "true", className: "size-3.5", strokeWidth: 2.5 }) }) }), jsx(TooltipContent, { side: "top", children: CARD_REORDER_HINT })] }) }));
|
|
78466
|
+
}
|
|
78467
|
+
/** A card in a sortable group: draggable from its grip, and a dashed slot where it will land while it drags. */
|
|
78468
|
+
function SortableFilterCard({ id, masonry, children, }) {
|
|
78469
|
+
const { ref, span, isActive, dragging, label, setActivatorNodeRef, listeners, } = useSortableFilterCard(id);
|
|
78470
|
+
return (jsx("div", { ref: ref.card, "data-filter-card-id": id, className: "group/card", style: masonry && span > 0 ? { gridRowEnd: `span ${span}` } : undefined, children: jsx("div", { ref: masonry ? ref.span : undefined, className: cn(masonry && 'pb-3'), children: jsxs("div", { className: cn('relative rounded-xl transition-shadow', !dragging &&
|
|
78471
|
+
'group-hover/card:ring-2 group-hover/card:ring-primary/20'), children: [jsx("div", { "data-filter-card-body": "", className: cn(isActive && 'invisible'), children: children }), isActive ? (jsx("div", { className: "absolute inset-0 rounded-xl border-2 border-dashed border-primary/40 bg-primary/5" })) : (jsx(CardReorderGrip, { label: label, dragging: dragging, setActivatorNodeRef: setActivatorNodeRef, listeners: listeners }))] }) }) }));
|
|
78472
|
+
}
|
|
78473
|
+
/** Where a group with no cards takes a drop. */
|
|
78474
|
+
function EmptyGroupDropZone({ groupId, }) {
|
|
78475
|
+
return (jsx("div", { "data-filter-group-id": groupId, className: "flex min-h-24 items-center justify-center rounded-xl border-2 border-dashed border-border text-sm text-muted-foreground", children: EMPTY_GROUP_LABEL }));
|
|
78476
|
+
}
|
|
78477
|
+
/** The copy of the dragged card under the pointer. */
|
|
78478
|
+
function FilterCardOverlay({ node, }) {
|
|
78479
|
+
return (jsxs("div", { "aria-hidden": "true", className: "relative cursor-grabbing rounded-xl shadow-lg ring-2 ring-primary/20", children: [jsx("div", { ref: (element) => {
|
|
78480
|
+
element?.replaceChildren(node);
|
|
78481
|
+
} }), jsx("span", { className: "absolute left-1/2 top-0 flex h-4 w-10 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full border border-primary bg-primary text-primary-foreground shadow-sm", children: jsx(GripHorizontal, { "aria-hidden": "true", className: "size-3.5", strokeWidth: 2.5 }) })] }));
|
|
78482
|
+
}
|
|
77523
78483
|
|
|
77524
78484
|
/** Full-page filter screen (e.g. an advanced search): one sticky header with every action, then the scrolling card grid. */
|
|
77525
|
-
function FilterSurface({ title, headerActions, primaryActions, chips, onClose, status = 'ready', errorMessage, onRetry, skeleton, children, }) {
|
|
78485
|
+
function FilterSurface({ title, headerActions, primaryActions, chips, onClose, closeButton = 'back', status = 'ready', errorMessage, onRetry, skeleton, children, }) {
|
|
77526
78486
|
useCloseOnEscape(onClose);
|
|
77527
78487
|
const ready = status === 'ready';
|
|
77528
78488
|
const actions = ready ? primaryActions : undefined;
|
|
77529
|
-
return (jsxs("div", { role: "region", "aria-label": title, className: "flex h-full min-h-0 flex-col bg-background", children: [jsxs("header", { className: "sticky top-0 z-20 flex shrink-0 flex-wrap items-center gap-x-3 gap-y-2 bg-background px-3 py-2.5", children: [jsx(IconButton, { appearance: "ghost", size: "sm", "aria-label": BACK_LABEL, title: BACK_LABEL, onClick: onClose, children: jsx(ArrowLeft, {}) }), jsx("h1", { className: "sr-only", children: title }), jsx("div", { className: "min-w-0 flex-1", children: ready && chips }), jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [headerActions, actions] })] }), jsx("div", { className: "min-h-0 flex-1 overflow-y-auto px-3 pb-3", children: status === 'loading' ? (jsx(FilterSurfaceSkeleton, { children: skeleton })) : status === 'error' ? (jsx(FilterSurfaceError, { message: errorMessage ?? DEFAULT_ERROR_MESSAGE, onRetry: onRetry })) : (jsx("div", { className: "flex flex-col gap-3", children: children })) })] }));
|
|
78489
|
+
return (jsxs("div", { role: "region", "aria-label": title, className: "flex h-full min-h-0 flex-col bg-background", children: [jsxs("header", { className: "sticky top-0 z-20 flex shrink-0 flex-wrap items-center gap-x-3 gap-y-2 bg-background px-3 py-2.5", children: [closeButton === 'back' && (jsx(IconButton, { appearance: "ghost", size: "sm", "aria-label": BACK_LABEL, title: BACK_LABEL, onClick: onClose, children: jsx(ArrowLeft, {}) })), jsx("h1", { className: "sr-only", children: title }), jsx("div", { className: "min-w-0 flex-1", children: ready && chips }), jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [headerActions, actions, closeButton === 'close' && (jsxs(Fragment$2, { children: [jsx("span", { "aria-hidden": "true", className: "mx-1 h-6 w-px bg-border" }), jsx(IconButton, { appearance: "ghost", size: "sm", "aria-label": CLOSE_LABEL, title: CLOSE_LABEL, onClick: onClose, children: jsx(X$2, {}) })] }))] })] }), jsx("div", { className: "min-h-0 flex-1 overflow-y-auto px-3 pb-3", children: status === 'loading' ? (jsx(FilterSurfaceSkeleton, { children: skeleton })) : status === 'error' ? (jsx(FilterSurfaceError, { message: errorMessage ?? DEFAULT_ERROR_MESSAGE, onRetry: onRetry })) : (jsx("div", { className: "flex flex-col gap-3", children: children })) })] }));
|
|
78490
|
+
}
|
|
78491
|
+
/**
|
|
78492
|
+
* Lets the user drag the cards of its `FilterSurfaceGroup`s (those with a `sortableId`) into any order and
|
|
78493
|
+
* between groups, from a grip on each card. A collapsed `FilterSurfaceMore` opens when a card rests on it.
|
|
78494
|
+
*/
|
|
78495
|
+
function FilterSurfaceSortable({ layout, onLayoutChange, renderCard, cardLabel, children, }) {
|
|
78496
|
+
const reorder = useFilterCardReorder({ layout, onLayoutChange });
|
|
78497
|
+
const context = useSortableContextValue(reorder, renderCard, cardLabel);
|
|
78498
|
+
return (jsxs(DndContext, { sensors: reorder.sensors, onDragStart: reorder.onDragStart, onDragEnd: reorder.onDragEnd, onDragCancel: reorder.onDragCancel, children: [jsx(FilterSurfaceSortableContext.Provider, { value: context, children: children }), jsx(DragOverlay, { className: "pointer-events-none", dropAnimation: CARD_DROP_ANIMATION, children: reorder.overlay && jsx(FilterCardOverlay, { node: reorder.overlay }) })] }));
|
|
77530
78499
|
}
|
|
77531
|
-
function FilterSurfaceGroup({ title, masonry = false, className, children, }) {
|
|
77532
|
-
|
|
78500
|
+
function FilterSurfaceGroup({ title, masonry = false, sortableId, className, children, }) {
|
|
78501
|
+
const sortable = useFilterSurfaceSortable();
|
|
78502
|
+
const ids = sortable && sortableId ? (sortable.layout[sortableId] ?? []) : null;
|
|
78503
|
+
// Cards keep their own height (no stretching to the row's tallest), so short cards carry no empty space.
|
|
78504
|
+
const gridClassName = cn('grid grid-cols-1 items-start lg:grid-cols-6', masonry ? MASONRY_GRID_CLASS_NAME : 'gap-3', className);
|
|
78505
|
+
return (jsxs("section", { className: "flex flex-col gap-3", children: [title && (jsx("h2", { className: "text-xs font-semibold uppercase tracking-wide text-label", children: title })), sortable && sortableId && ids ? (ids.length === 0 ? (jsx(EmptyGroupDropZone, { groupId: sortableId })) : (
|
|
78506
|
+
// Top room for the first row's grab tabs, which sit on the cards' top edge.
|
|
78507
|
+
jsx("div", { className: cn(gridClassName, 'pt-2'), "data-filter-group-id": sortableId, children: ids.map((id) => (jsx(SortableFilterCard, { id: id, masonry: masonry, children: sortable.renderCard(id) }, id))) }))) : (jsx("div", { className: gridClassName, children: masonry
|
|
77533
78508
|
? Children.map(children, (child) => child ? jsx(MasonryItem, { children: child }) : null)
|
|
77534
|
-
: children })] }));
|
|
78509
|
+
: children }))] }));
|
|
77535
78510
|
}
|
|
77536
78511
|
/** Collapsed "More filters" divider that reveals extra cards. */
|
|
77537
78512
|
function FilterSurfaceMore({ label, defaultExpanded, children, }) {
|
|
77538
|
-
const { expanded, toggle } = useFilterSurfaceMore(defaultExpanded);
|
|
77539
|
-
return (jsxs("section", { className: "flex flex-col gap-3", children: [jsxs("div", { className: "flex items-center gap-3", children: [jsx("span", { className: "h-px flex-1 bg-border" }), jsxs("button", { type: "button", "aria-expanded": expanded, onClick: toggle, className: "inline-flex cursor-pointer items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-xs font-medium text-primary outline-none hover:bg-muted/50 focus-visible:ring-2 focus-visible:ring-primary/30", children: [label, jsx(ChevronDown, { "aria-hidden": "true", className: cn('size-3.5 transition-transform', expanded && 'rotate-180') })] }), jsx("span", { className: "h-px flex-1 bg-border" })] }), expanded && children] }));
|
|
78513
|
+
const { expanded, toggle, toggleRef } = useFilterSurfaceMore(defaultExpanded);
|
|
78514
|
+
return (jsxs("section", { className: "flex flex-col gap-3", children: [jsxs("div", { className: "flex items-center gap-3", children: [jsx("span", { className: "h-px flex-1 bg-border" }), jsxs("button", { ref: toggleRef, type: "button", "aria-expanded": expanded, onClick: toggle, "data-filter-more-toggle": "", className: "inline-flex cursor-pointer items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-xs font-medium text-primary outline-none hover:bg-muted/50 focus-visible:ring-2 focus-visible:ring-primary/30", children: [label, jsx(ChevronDown, { "aria-hidden": "true", className: cn('size-3.5 transition-transform', expanded && 'rotate-180') })] }), jsx("span", { className: "h-px flex-1 bg-border" })] }), expanded && children] }));
|
|
77540
78515
|
}
|
|
77541
78516
|
|
|
77542
78517
|
/** Falls back to counting the current page when the caller has no total. */
|
|
@@ -80112,5 +81087,5 @@ var RichTextAreaImpl = /*#__PURE__*/Object.freeze({
|
|
|
80112
81087
|
RichTextarea: RichTextarea
|
|
80113
81088
|
});
|
|
80114
81089
|
|
|
80115
|
-
export { ACTIVITY_CATEGORIES, ACTIVITY_CATEGORY_META, ActionBadge, ActionButtonWithTooltip, ActiveFilterChips, ActivityFeed, AdvancedSearchDrawer, Alert, ApiComboBox, AppSidebar, AuditEntryCard, AuditHistoryPanel, AuditTimeline, AuditTimelineShimmer, Badge, BadgeType, BusinessContactStatusFilter, Button, CUSTOMER_AUDIT_CONFIG, CertificateRowList, ChangePill, Collapsible, CollapsibleCard, CollapsibleContent, CollapsibleTrigger, CompanyCard, ConfirmDialog, ContactTypeFilter, ContainsFilter, CopyButton, CountrySelect, CreateFormPageHeader, CreateFormPageShell, CurrencyDisplayTabs, CurrencyInput, CurrencyToggle, CustomCombobox, CustomFieldInput, CustomFieldValue, CustomTable, CustomizeColumnsDrawer, DATE_PRESET_OPTIONS, DIAMOND_AUDIT_CONFIG, DashboardShell, DataEditableTable, DataTable, DateInput, DateRangeFilter, DetailChip, DetailPageLayout, DetailPageSkeleton, DetailSection, DocumentDeleteDialog, DocumentDetailSkeleton, DocumentHero, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyValue, EntityHeader, FILTER_COUNT_BADGE_CLASS_NAME, Field, FieldSkeleton, FileUploader, FilterCardSkeleton, FilterCellPopover, FilterEmptyState, FilterField, FilterFieldCard, FilterFieldCell, FilterFieldControl, FilterMultiSelect, FilterPanel, FilterSelect, FilterSurface, FilterSurfaceGroup, FilterSurfaceMore, FormSectionCard, FormSectionCardSkeleton, GEM_AUDIT_CONFIG, HistoryEntryCard, HistoryTimeline, HistoryTimelineShimmer, INVOICE_AUDIT_CONFIG, IconButton, IdHyperlinkText, IdListInput, InAppNotificationCard, InAppNotificationsPanel, InfoBanner, InventoryComboBox, InventoryItemCard, InventoryItemRow, InvoiceComboBox, KYCStatusFilter, KeyValueGrid, LAYOUT_AUDIT_CONFIG, LabeledToggle, LineItemsCard, LineProductCell, LineProductThumb, LineProductTypeChip, LineRowActionsMenu, LineTable, LineTableEmpty, MEMO_IN_AUDIT_CONFIG, MEMO_OUT_AUDIT_CONFIG, MediaGallery, MemoInComboBox, MetricCard, MetricRow, MetricTile, Modal, MoreInfoPanel, MoreInfoTrigger, NOT_CAPTURED, Navbar, NavbarActions, NavbarAvatar, NavbarIconButton, NavbarSearch, NavbarTitle, NumberExpressionFilter, NumberInput, NumberRangeInputs, NumberedStepCard, OtpInput, OwnershipFilter, OwnershipSplitCard, PROFORMA_AUDIT_CONFIG, PageHeader, PageTabs, Pagination, PaginationSelect, PartnerShareCard, PickListDropdown, PickListFilter, PriceInput, Protected, PurchaseOrderComboBox, QUOTATION_AUDIT_CONFIG, RadioCardGroup, ReadMoreText, RefreshButton, RichTextarea$1 as RichTextarea, SAVED_SEARCH_NAME_MAX_LENGTH, SEARCHABLE_SELECT_PAGE_SIZE, SafeImage, SaveSearchDialog, SavedSearchChipList, SavedSearchDetail, SavedSearchesMenu, ScaleRangeFilter, ScrollFade, SearchBox, SearchInput, SearchableSelect, SectionCard, SectionIcon, SegmentedControl, ShareDialog, ShareMenu, ShimmerTable, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupLabel, SidebarHeader, SidebarInset, SidebarMenu, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SlideOut, SlideOutClose, SlideOutContent, SlideOutDescription, SlideOutHeader, SlideOutOverlay, SlideOutPortal, SlideOutTitle, SlideOutTrigger, Slider, SpecList, Spinner, SquareSkeleton, StateSelect, StatusBadge$1 as StatusBadge, StatusFilter, Stepper, StockTypeFilter, TablePagination, TableRowsSkeleton, TableSkeleton, Tabs, TabsContent, TabsList, TabsTrigger, TagsInput, TextHyperlink, TimePicker, ToggleSwitch, TriStateFilter, TruncateTooltip, TruncatedLabel, WarehouseComboBox, WarehouseFilter, ZoomSplitViewer, asList, asText, badgeVariants, buildBulkShareMessage, buildBulkShareTitle, buildInventoryPublicUrl, buildInventoryRowProps, buildInventoryShareTitle, buildNumberRuleHelp, buildWhatsappUrl, buttonVariants, cn, countries, countryByCode, createVideoMediaItem, describeFilterValue, dropdownMenuItemDestructiveClass, expandScaleRange, fieldTypeIcon, filterSavedSearches, findRegion, flagEmoji, formatAddressLocation, formatDateRange, formatFileSize, formatNumberRange, formatScaleRange, formatSelectedCount, generateActionDescription, generateTitle, getBadgeTypeForStatus, getChangePills, getCountryName, getInitials, getStatesOfCountry, iconButtonVariants, inAppNotificationCardA11y, inAppNotificationsPanelA11y, isBlank, isDuplicateSearchName, isFilterValueActive, isIndiaCountry, isKnownRegion, isPathActive, isValidAlpha2CountryCode, isValidSearchName, isValueEmpty, notify, parseNumberExpression, releaseStaleOverlayBodyLock, renderBadge, resolveCountryCode, resolveDatePreset, resolveDateRange, richTextChangeText, splitIdList, toAddressFormValues, toBoolValue, toContainsValue, toDateValue, toIdsValue, toListValue, toNumberValue, toScaleValue, useAuditShowMore, useBadge, useButton, useDropdownMenu, useInAppNotificationsPanel, useNavbar, useSidebar, valueOfType, videoThumbnailSrc, watchOverlayBodyLock };
|
|
81090
|
+
export { ACTIVITY_CATEGORIES, ACTIVITY_CATEGORY_META, ActionBadge, ActionButtonWithTooltip, ActiveFilterChips, ActivityFeed, AdvancedSearchDrawer, Alert, ApiComboBox, AppSidebar, AuditEntryCard, AuditHistoryPanel, AuditTimeline, AuditTimelineShimmer, Badge, BadgeType, BusinessContactStatusFilter, Button, CUSTOMER_AUDIT_CONFIG, CertificateRowList, ChangePill, Collapsible, CollapsibleCard, CollapsibleContent, CollapsibleTrigger, CompanyCard, ConfirmDialog, ContactTypeFilter, ContainsFilter, CopyButton, CountrySelect, CreateFormPageHeader, CreateFormPageShell, CurrencyDisplayTabs, CurrencyInput, CurrencyToggle, CustomCombobox, CustomFieldInput, CustomFieldValue, CustomTable, CustomizeColumnsDrawer, DATE_PRESET_OPTIONS, DIAMOND_AUDIT_CONFIG, DashboardShell, DataEditableTable, DataTable, DateInput, DateRangeFilter, DetailChip, DetailPageLayout, DetailPageSkeleton, DetailSection, DocumentDeleteDialog, DocumentDetailSkeleton, DocumentHero, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyValue, EntityHeader, FILTER_COUNT_BADGE_CLASS_NAME, Field, FieldSkeleton, FileUploader, FilterCardSkeleton, FilterCellPopover, FilterEmptyState, FilterField, FilterFieldCard, FilterFieldCell, FilterFieldControl, FilterMultiSelect, FilterPanel, FilterSelect, FilterSurface, FilterSurfaceGroup, FilterSurfaceMore, FilterSurfaceSortable, FloatingSlideOver, FormSectionCard, FormSectionCardSkeleton, GEM_AUDIT_CONFIG, HistoryEntryCard, HistoryTimeline, HistoryTimelineShimmer, INVOICE_AUDIT_CONFIG, IconButton, IdHyperlinkText, IdListInput, InAppNotificationCard, InAppNotificationsPanel, InfoBanner, InventoryComboBox, InventoryItemCard, InventoryItemRow, InvoiceComboBox, KYCStatusFilter, KeyValueGrid, LAYOUT_AUDIT_CONFIG, LabeledToggle, LineItemsCard, LineProductCell, LineProductThumb, LineProductTypeChip, LineRowActionsMenu, LineTable, LineTableEmpty, MEMO_IN_AUDIT_CONFIG, MEMO_OUT_AUDIT_CONFIG, MediaGallery, MemoInComboBox, MetricCard, MetricRow, MetricTile, Modal, MoreInfoPanel, MoreInfoTrigger, NOT_CAPTURED, Navbar, NavbarActions, NavbarAvatar, NavbarIconButton, NavbarSearch, NavbarTitle, NumberExpressionFilter, NumberInput, NumberRangeInputs, NumberedStepCard, OtpInput, OwnershipFilter, OwnershipSplitCard, PROFORMA_AUDIT_CONFIG, PageHeader, PageTabs, Pagination, PaginationSelect, PartnerShareCard, PickListDropdown, PickListFilter, PriceInput, Protected, PurchaseOrderComboBox, QUOTATION_AUDIT_CONFIG, RadioCardGroup, ReadMoreText, RefreshButton, RichTextarea$1 as RichTextarea, SAVED_SEARCH_NAME_MAX_LENGTH, SEARCHABLE_SELECT_PAGE_SIZE, SafeImage, SaveSearchDialog, SavedSearchChipList, SavedSearchDetail, SavedSearchesMenu, ScaleRangeFilter, ScrollFade, SearchBox, SearchInput, SearchableSelect, SectionCard, SectionIcon, SegmentedControl, ShareDialog, ShareMenu, ShimmerTable, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupLabel, SidebarHeader, SidebarInset, SidebarMenu, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SlideOut, SlideOutClose, SlideOutContent, SlideOutDescription, SlideOutHeader, SlideOutOverlay, SlideOutPortal, SlideOutTitle, SlideOutTrigger, Slider, SpecList, Spinner, SquareSkeleton, StateSelect, StatusBadge$1 as StatusBadge, StatusFilter, Stepper, StockTypeFilter, TablePagination, TableRowsSkeleton, TableSkeleton, Tabs, TabsContent, TabsList, TabsTrigger, TagsInput, TextHyperlink, TimePicker, ToggleSwitch, TriStateFilter, TruncateTooltip, TruncatedLabel, WarehouseComboBox, WarehouseFilter, ZoomSplitViewer, asList, asText, badgeVariants, buildBulkShareMessage, buildBulkShareTitle, buildInventoryPublicUrl, buildInventoryRowProps, buildInventoryShareTitle, buildNumberRuleHelp, buildWhatsappUrl, buttonVariants, cn, countries, countryByCode, createVideoMediaItem, describeFilterValue, dropdownMenuItemDestructiveClass, expandScaleRange, fieldTypeIcon, filterSavedSearches, findRegion, flagEmoji, formatAddressLocation, formatDateRange, formatFileSize, formatNumberRange, formatScaleRange, formatSelectedCount, generateActionDescription, generateTitle, getBadgeTypeForStatus, getChangePills, getCountryName, getInitials, getStatesOfCountry, iconButtonVariants, inAppNotificationCardA11y, inAppNotificationsPanelA11y, isBlank, isDuplicateSearchName, isFilterValueActive, isIndiaCountry, isKnownRegion, isPathActive, isValidAlpha2CountryCode, isValidSearchName, isValueEmpty, notify, parseNumberExpression, releaseStaleOverlayBodyLock, renderBadge, resolveCountryCode, resolveDatePreset, resolveDateRange, richTextChangeText, splitIdList, toAddressFormValues, toBoolValue, toContainsValue, toDateValue, toIdsValue, toListValue, toNumberValue, toScaleValue, useAuditShowMore, useBadge, useButton, useDropdownMenu, useInAppNotificationsPanel, useNavbar, useSidebar, valueOfType, videoThumbnailSrc, watchOverlayBodyLock };
|
|
80116
81091
|
//# sourceMappingURL=index.esm.js.map
|