@lumx/react 4.5.1 → 4.5.2-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/index.d.ts +48 -19
  2. package/index.js +317 -331
  3. package/index.js.map +1 -1
  4. package/package.json +4 -3
package/index.js CHANGED
@@ -7,7 +7,7 @@ import { mdiAlert } from '@lumx/icons/esm/alert.js';
7
7
  import { mdiAlertCircle } from '@lumx/icons/esm/alert-circle.js';
8
8
  import { mdiCheckCircle } from '@lumx/icons/esm/check-circle.js';
9
9
  import { mdiInformation } from '@lumx/icons/esm/information.js';
10
- import { classNames, onEnterPressed, onEscapePressed, onButtonPressed, detectHorizontalSwipe } from '@lumx/core/js/utils';
10
+ import { classNames, onEnterPressed, onEscapePressed, detectHorizontalSwipe } from '@lumx/core/js/utils';
11
11
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
12
12
  import last from 'lodash/last.js';
13
13
  import pull from 'lodash/pull.js';
@@ -4042,6 +4042,148 @@ const skipRender = (predicate, Component) => {
4042
4042
  return Wrapper;
4043
4043
  };
4044
4044
 
4045
+ /**
4046
+ * Different possible placements for the popover.
4047
+ */
4048
+ const Placement = {
4049
+ AUTO: 'auto',
4050
+ AUTO_END: 'auto-end',
4051
+ AUTO_START: 'auto-start',
4052
+ TOP: 'top',
4053
+ TOP_END: 'top-end',
4054
+ TOP_START: 'top-start',
4055
+ RIGHT: 'right',
4056
+ RIGHT_END: 'right-end',
4057
+ RIGHT_START: 'right-start',
4058
+ BOTTOM: 'bottom',
4059
+ BOTTOM_END: 'bottom-end',
4060
+ BOTTOM_START: 'bottom-start',
4061
+ LEFT: 'left',
4062
+ LEFT_END: 'left-end',
4063
+ LEFT_START: 'left-start'
4064
+ };
4065
+
4066
+ /**
4067
+ * Offset of the popover.
4068
+ */
4069
+
4070
+ /**
4071
+ * Popover elevation index.
4072
+ */
4073
+
4074
+ /**
4075
+ * Popover fit anchor width options.
4076
+ */
4077
+ const FitAnchorWidth = {
4078
+ MIN_WIDTH: 'minWidth'};
4079
+ /**
4080
+ * Arrow size (in pixel).
4081
+ */
4082
+ const ARROW_SIZE$1 = 14;
4083
+
4084
+ /**
4085
+ * Popover default z-index
4086
+ */
4087
+ const POPOVER_ZINDEX = 9999;
4088
+
4089
+ /**
4090
+ * Component display name.
4091
+ */
4092
+ const COMPONENT_NAME$Y = 'Popover';
4093
+
4094
+ /**
4095
+ * Component default class name and class prefix.
4096
+ */
4097
+ const CLASSNAME$Z = 'lumx-popover';
4098
+ const {
4099
+ block: block$Q,
4100
+ element: element$E
4101
+ } = bem(CLASSNAME$Z);
4102
+
4103
+ /**
4104
+ * Component default props (used by framework wrappers).
4105
+ */
4106
+ const DEFAULT_PROPS$U = {
4107
+ elevation: 3,
4108
+ placement: Placement.AUTO,
4109
+ focusAnchorOnClose: true,
4110
+ usePortal: true,
4111
+ zIndex: POPOVER_ZINDEX
4112
+ };
4113
+
4114
+ /**
4115
+ * Popover core UI component.
4116
+ *
4117
+ * Framework-specific components (Portal, ClickAwayProvider, ThemeProvider) are passed
4118
+ * as a second argument by the React/Vue wrappers.
4119
+ */
4120
+ const Popover$1 = (props, {
4121
+ Portal,
4122
+ ClickAwayProvider,
4123
+ ThemeProvider
4124
+ }) => {
4125
+ const {
4126
+ as: asTag = 'div',
4127
+ children,
4128
+ className,
4129
+ elevation = DEFAULT_PROPS$U.elevation,
4130
+ hasArrow,
4131
+ isOpen,
4132
+ position,
4133
+ popoverStyle,
4134
+ arrowStyle,
4135
+ theme,
4136
+ // Framework-specific
4137
+ ref,
4138
+ arrowRef,
4139
+ usePortal = DEFAULT_PROPS$U.usePortal,
4140
+ clickAwayCallback,
4141
+ clickAwayRefs,
4142
+ unmountSentinel,
4143
+ // Forwarded props
4144
+ ...forwardedProps
4145
+ } = props;
4146
+
4147
+ // Cast to `any` to avoid "union type too complex" error when using a dynamic tag name in JSX.
4148
+ // This is safe because `asTag` is always a valid HTML element tag (e.g. 'div').
4149
+ const Component = asTag;
4150
+ const adjustedElevation = Math.min(elevation || 0, 5);
4151
+ if (!isOpen) return null;
4152
+ return /*#__PURE__*/jsx(Portal, {
4153
+ enabled: usePortal,
4154
+ children: /*#__PURE__*/jsxs(Component, {
4155
+ ...forwardedProps,
4156
+ ref: ref,
4157
+ className: classnames(className, block$Q({
4158
+ [`theme-${theme}`]: Boolean(theme),
4159
+ [`elevation-${adjustedElevation}`]: Boolean(adjustedElevation),
4160
+ [`position-${position}`]: Boolean(position)
4161
+ })),
4162
+ style: popoverStyle,
4163
+ "data-popper-placement": position,
4164
+ children: [unmountSentinel, /*#__PURE__*/jsxs(ClickAwayProvider, {
4165
+ callback: clickAwayCallback,
4166
+ childrenRefs: clickAwayRefs,
4167
+ children: [hasArrow && /*#__PURE__*/jsx("div", {
4168
+ ref: arrowRef,
4169
+ className: element$E('arrow'),
4170
+ style: arrowStyle,
4171
+ children: /*#__PURE__*/jsx("svg", {
4172
+ viewBox: "0 0 14 14",
4173
+ "aria-hidden": true,
4174
+ children: /*#__PURE__*/jsx("path", {
4175
+ d: "M8 3.49C7.62 2.82 6.66 2.82 6.27 3.48L.04 14 14.04 14 8 3.49Z"
4176
+ })
4177
+ })
4178
+ }), /*#__PURE__*/jsx(ThemeProvider, {
4179
+ value: theme,
4180
+ children: children
4181
+ })]
4182
+ })]
4183
+ })
4184
+ });
4185
+ };
4186
+
4045
4187
  /**
4046
4188
  * Helper component using useLayoutEffect to trigger a callback on before unmount.
4047
4189
  *
@@ -4461,7 +4603,7 @@ const computePosition$1 = async (reference, floating, config) => {
4461
4603
  * appears centered to the reference element.
4462
4604
  * @see https://floating-ui.com/docs/arrow
4463
4605
  */
4464
- const arrow$3 = options => ({
4606
+ const arrow$1 = options => ({
4465
4607
  name: 'arrow',
4466
4608
  options,
4467
4609
  async fn(state) {
@@ -4553,7 +4695,7 @@ function getPlacementList(alignment, autoAlignment, allowedPlacements) {
4553
4695
  * preferred placement. Alternative to `flip`.
4554
4696
  * @see https://floating-ui.com/docs/autoPlacement
4555
4697
  */
4556
- const autoPlacement$2 = function (options) {
4698
+ const autoPlacement$1 = function (options) {
4557
4699
  if (options === void 0) {
4558
4700
  options = {};
4559
4701
  }
@@ -4647,7 +4789,7 @@ const autoPlacement$2 = function (options) {
4647
4789
  * clipping boundary. Alternative to `autoPlacement`.
4648
4790
  * @see https://floating-ui.com/docs/flip
4649
4791
  */
4650
- const flip$2 = function (options) {
4792
+ const flip$1 = function (options) {
4651
4793
  if (options === void 0) {
4652
4794
  options = {};
4653
4795
  }
@@ -4864,7 +5006,7 @@ const offset$2 = function (options) {
4864
5006
  * keep it in view when it will overflow the clipping boundary.
4865
5007
  * @see https://floating-ui.com/docs/shift
4866
5008
  */
4867
- const shift$2 = function (options) {
5009
+ const shift$1 = function (options) {
4868
5010
  if (options === void 0) {
4869
5011
  options = {};
4870
5012
  }
@@ -4944,7 +5086,7 @@ const shift$2 = function (options) {
4944
5086
  * width of the reference element.
4945
5087
  * @see https://floating-ui.com/docs/size
4946
5088
  */
4947
- const size$2 = function (options) {
5089
+ const size$1 = function (options) {
4948
5090
  if (options === void 0) {
4949
5091
  options = {};
4950
5092
  }
@@ -5869,14 +6011,14 @@ const offset$1 = offset$2;
5869
6011
  * preferred placement. Alternative to `flip`.
5870
6012
  * @see https://floating-ui.com/docs/autoPlacement
5871
6013
  */
5872
- const autoPlacement$1 = autoPlacement$2;
6014
+ const autoPlacement = autoPlacement$1;
5873
6015
 
5874
6016
  /**
5875
6017
  * Optimizes the visibility of the floating element by shifting it in order to
5876
6018
  * keep it in view when it will overflow the clipping boundary.
5877
6019
  * @see https://floating-ui.com/docs/shift
5878
6020
  */
5879
- const shift$1 = shift$2;
6021
+ const shift = shift$1;
5880
6022
 
5881
6023
  /**
5882
6024
  * Optimizes the visibility of the floating element by flipping the `placement`
@@ -5884,7 +6026,7 @@ const shift$1 = shift$2;
5884
6026
  * clipping boundary. Alternative to `autoPlacement`.
5885
6027
  * @see https://floating-ui.com/docs/flip
5886
6028
  */
5887
- const flip$1 = flip$2;
6029
+ const flip = flip$1;
5888
6030
 
5889
6031
  /**
5890
6032
  * Provides data that allows you to change the size of the floating element —
@@ -5892,14 +6034,14 @@ const flip$1 = flip$2;
5892
6034
  * width of the reference element.
5893
6035
  * @see https://floating-ui.com/docs/size
5894
6036
  */
5895
- const size$1 = size$2;
6037
+ const size = size$1;
5896
6038
 
5897
6039
  /**
5898
6040
  * Provides data to position an inner element of the floating element so that it
5899
6041
  * appears centered to the reference element.
5900
6042
  * @see https://floating-ui.com/docs/arrow
5901
6043
  */
5902
- const arrow$2 = arrow$3;
6044
+ const arrow = arrow$1;
5903
6045
 
5904
6046
  /**
5905
6047
  * Computes the `x` and `y` coordinates that will place the floating element
@@ -6156,44 +6298,6 @@ function useFloating(options) {
6156
6298
  }), [data, update, refs, elements, floatingStyles]);
6157
6299
  }
6158
6300
 
6159
- /**
6160
- * Provides data to position an inner element of the floating element so that it
6161
- * appears centered to the reference element.
6162
- * This wraps the core `arrow` middleware to allow React refs as the element.
6163
- * @see https://floating-ui.com/docs/arrow
6164
- */
6165
- const arrow$1 = options => {
6166
- function isRef(value) {
6167
- return {}.hasOwnProperty.call(value, 'current');
6168
- }
6169
- return {
6170
- name: 'arrow',
6171
- options,
6172
- fn(state) {
6173
- const {
6174
- element,
6175
- padding
6176
- } = typeof options === 'function' ? options(state) : options;
6177
- if (element && isRef(element)) {
6178
- if (element.current != null) {
6179
- return arrow$2({
6180
- element: element.current,
6181
- padding
6182
- }).fn(state);
6183
- }
6184
- return {};
6185
- }
6186
- if (element) {
6187
- return arrow$2({
6188
- element,
6189
- padding
6190
- }).fn(state);
6191
- }
6192
- return {};
6193
- }
6194
- };
6195
- };
6196
-
6197
6301
  /**
6198
6302
  * Modifies the placement by translating the floating element along the
6199
6303
  * specified axes.
@@ -6206,104 +6310,11 @@ const offset = (options, deps) => ({
6206
6310
  options: [options, deps]
6207
6311
  });
6208
6312
 
6209
- /**
6210
- * Optimizes the visibility of the floating element by shifting it in order to
6211
- * keep it in view when it will overflow the clipping boundary.
6212
- * @see https://floating-ui.com/docs/shift
6213
- */
6214
- const shift = (options, deps) => ({
6215
- ...shift$1(options),
6216
- options: [options, deps]
6217
- });
6313
+ /* eslint-disable no-param-reassign */
6218
6314
 
6219
6315
  /**
6220
- * Optimizes the visibility of the floating element by flipping the `placement`
6221
- * in order to keep it in view when the preferred placement(s) will overflow the
6222
- * clipping boundary. Alternative to `autoPlacement`.
6223
- * @see https://floating-ui.com/docs/flip
6224
- */
6225
- const flip = (options, deps) => ({
6226
- ...flip$1(options),
6227
- options: [options, deps]
6228
- });
6229
-
6230
- /**
6231
- * Provides data that allows you to change the size of the floating element —
6232
- * for instance, prevent it from overflowing the clipping boundary or match the
6233
- * width of the reference element.
6234
- * @see https://floating-ui.com/docs/size
6235
- */
6236
- const size = (options, deps) => ({
6237
- ...size$1(options),
6238
- options: [options, deps]
6239
- });
6240
-
6241
- /**
6242
- * Optimizes the visibility of the floating element by choosing the placement
6243
- * that has the most space available automatically, without needing to specify a
6244
- * preferred placement. Alternative to `flip`.
6245
- * @see https://floating-ui.com/docs/autoPlacement
6246
- */
6247
- const autoPlacement = (options, deps) => ({
6248
- ...autoPlacement$1(options),
6249
- options: [options, deps]
6250
- });
6251
-
6252
- /**
6253
- * Provides data to position an inner element of the floating element so that it
6254
- * appears centered to the reference element.
6255
- * This wraps the core `arrow` middleware to allow React refs as the element.
6256
- * @see https://floating-ui.com/docs/arrow
6316
+ * Parse a Popover placement into floating-ui placement or auto-placement config.
6257
6317
  */
6258
- const arrow = (options, deps) => ({
6259
- ...arrow$1(options),
6260
- options: [options, deps]
6261
- });
6262
-
6263
- /**
6264
- * Different possible placements for the popover.
6265
- */
6266
- const Placement = {
6267
- AUTO: 'auto',
6268
- AUTO_END: 'auto-end',
6269
- AUTO_START: 'auto-start',
6270
- TOP: 'top',
6271
- TOP_END: 'top-end',
6272
- TOP_START: 'top-start',
6273
- RIGHT: 'right',
6274
- RIGHT_END: 'right-end',
6275
- RIGHT_START: 'right-start',
6276
- BOTTOM: 'bottom',
6277
- BOTTOM_END: 'bottom-end',
6278
- BOTTOM_START: 'bottom-start',
6279
- LEFT: 'left',
6280
- LEFT_END: 'left-end',
6281
- LEFT_START: 'left-start'
6282
- };
6283
-
6284
- /**
6285
- * Offset of the popover.
6286
- */
6287
-
6288
- /**
6289
- * Popover elevation index.
6290
- */
6291
-
6292
- /**
6293
- * Popover fit anchor width options.
6294
- */
6295
- const FitAnchorWidth = {
6296
- MIN_WIDTH: 'minWidth'};
6297
- /**
6298
- * Arrow size (in pixel).
6299
- */
6300
- const ARROW_SIZE$1 = 14;
6301
-
6302
- /**
6303
- * Popover default z-index
6304
- */
6305
- const POPOVER_ZINDEX = 9999;
6306
-
6307
6318
  function parseAutoPlacement(placement) {
6308
6319
  if (placement === 'auto') return {
6309
6320
  isAuto: true
@@ -6321,13 +6332,111 @@ function parseAutoPlacement(placement) {
6321
6332
  isAuto: false
6322
6333
  };
6323
6334
  }
6335
+
6336
+ /**
6337
+ * Parse the fitToAnchorWidth option into the CSS property name to apply.
6338
+ */
6324
6339
  function parseFitWidth(fitToAnchorWidth) {
6325
6340
  if (!fitToAnchorWidth) return undefined;
6326
6341
  if (typeof fitToAnchorWidth === 'string') return fitToAnchorWidth;
6327
6342
  return FitAnchorWidth.MIN_WIDTH;
6328
6343
  }
6344
+ /**
6345
+ * Build the floating-ui middleware array for popover positioning.
6346
+ *
6347
+ * Middleware order: offset → flip/autoPlacement → shift → size → arrow
6348
+ */
6349
+ function buildPopoverMiddleware(options) {
6350
+ const {
6351
+ offset,
6352
+ hasArrow,
6353
+ fitWidth,
6354
+ fitWithinViewportHeight,
6355
+ boundary,
6356
+ parsedPlacement,
6357
+ arrowElement
6358
+ } = options;
6359
+ const middlewares = [];
6360
+
6361
+ // Offset middleware
6362
+ const awayOffset = (offset?.away ?? 0) + (hasArrow ? ARROW_SIZE$1 : 0);
6363
+ const alongOffset = offset?.along ?? 0;
6364
+ middlewares.push(offset$1({
6365
+ mainAxis: awayOffset,
6366
+ crossAxis: alongOffset
6367
+ }));
6368
+
6369
+ // Positioning middlewares
6370
+ if (parsedPlacement.isAuto) {
6371
+ middlewares.push(autoPlacement({
6372
+ ...(boundary ? {
6373
+ boundary
6374
+ } : {}),
6375
+ alignment: parsedPlacement.autoAlignment
6376
+ }));
6377
+ } else {
6378
+ middlewares.push(flip(boundary ? {
6379
+ boundary
6380
+ } : {}));
6381
+ middlewares.push(shift(boundary ? {
6382
+ boundary
6383
+ } : {}));
6384
+ }
6385
+
6386
+ // Size middleware
6387
+ if (fitWidth || fitWithinViewportHeight) {
6388
+ middlewares.push(size({
6389
+ ...(boundary ? {
6390
+ boundary
6391
+ } : {}),
6392
+ apply({
6393
+ availableHeight,
6394
+ rects,
6395
+ elements
6396
+ }) {
6397
+ if (fitWidth) {
6398
+ Object.assign(elements.floating.style, {
6399
+ [fitWidth]: `${rects.reference.width}px`
6400
+ });
6401
+ }
6402
+ if (fitWithinViewportHeight) {
6403
+ elements.floating.style.maxHeight = `${Math.max(0, availableHeight - ARROW_SIZE$1)}px`;
6404
+ }
6405
+ }
6406
+ }));
6407
+ }
6408
+
6409
+ // Arrow middleware
6410
+ if (hasArrow && arrowElement) {
6411
+ middlewares.push(arrow({
6412
+ element: arrowElement,
6413
+ padding: ARROW_SIZE$1 / 2
6414
+ }));
6415
+ }
6416
+ return middlewares;
6417
+ }
6418
+
6419
+ /**
6420
+ * Compute arrow CSS styles from floating-ui middleware data.
6421
+ */
6422
+ function computeArrowStyles(arrowData) {
6423
+ if (!arrowData) return undefined;
6424
+ return {
6425
+ left: arrowData.x != null ? `${arrowData.x}px` : '',
6426
+ top: arrowData.y != null ? `${arrowData.y}px` : ''
6427
+ };
6428
+ }
6429
+
6430
+ /**
6431
+ * Get the floating-ui placement from the parsed placement config.
6432
+ * Returns undefined for auto-placement (floating-ui handles it via autoPlacement middleware).
6433
+ */
6434
+ function getFloatingPlacement(parsedPlacement) {
6435
+ return parsedPlacement.isAuto ? undefined : parsedPlacement.floatingPlacement;
6436
+ }
6437
+
6329
6438
  function usePopoverStyle({
6330
- offset: offset$1,
6439
+ offset,
6331
6440
  hasArrow,
6332
6441
  fitToAnchorWidth,
6333
6442
  fitWithinViewportHeight,
@@ -6339,76 +6448,18 @@ function usePopoverStyle({
6339
6448
  }) {
6340
6449
  const [popperElement, setPopperElement] = useState(null);
6341
6450
  const [arrowElement, setArrowElement] = useState(null);
6342
- const {
6343
- floatingPlacement,
6344
- isAuto,
6345
- autoAlignment
6346
- } = parseAutoPlacement(placement);
6451
+ const parsedPlacement = parseAutoPlacement(placement);
6347
6452
  const fitWidth = parseFitWidth(fitToAnchorWidth);
6348
6453
  const boundary = boundaryRef?.current ?? undefined;
6349
-
6350
- // Build middleware array (order matters: offset → flip/autoPlacement → shift → size → arrow)
6351
- const middleware = useMemo(() => {
6352
- const mw = [];
6353
-
6354
- // Offset middleware
6355
- const awayOffset = (offset$1?.away ?? 0) + (hasArrow ? ARROW_SIZE$1 : 0);
6356
- const alongOffset = offset$1?.along ?? 0;
6357
- mw.push(offset({
6358
- mainAxis: awayOffset,
6359
- crossAxis: alongOffset
6360
- }));
6361
-
6362
- // Positioning middlewares
6363
- if (isAuto) {
6364
- mw.push(autoPlacement({
6365
- ...(boundary ? {
6366
- boundary
6367
- } : {}),
6368
- alignment: autoAlignment
6369
- }));
6370
- } else {
6371
- mw.push(flip(boundary ? {
6372
- boundary
6373
- } : {}));
6374
- mw.push(shift(boundary ? {
6375
- boundary
6376
- } : {}));
6377
- }
6378
-
6379
- // Size middleware
6380
- if (fitWidth || fitWithinViewportHeight) {
6381
- mw.push(size({
6382
- ...(boundary ? {
6383
- boundary
6384
- } : {}),
6385
- apply({
6386
- availableHeight,
6387
- rects,
6388
- elements
6389
- }) {
6390
- if (fitWidth) {
6391
- Object.assign(elements.floating.style, {
6392
- [fitWidth]: `${rects.reference.width}px`
6393
- });
6394
- }
6395
- if (fitWithinViewportHeight) {
6396
- // eslint-disable-next-line no-param-reassign
6397
- elements.floating.style.maxHeight = `${Math.max(0, availableHeight - ARROW_SIZE$1)}px`;
6398
- }
6399
- }
6400
- }));
6401
- }
6402
-
6403
- // Arrow middleware
6404
- if (hasArrow && arrowElement) {
6405
- mw.push(arrow({
6406
- element: arrowElement,
6407
- padding: ARROW_SIZE$1 / 2
6408
- }));
6409
- }
6410
- return mw;
6411
- }, [offset$1?.away, offset$1?.along, hasArrow, isAuto, autoAlignment, boundary, fitWidth, fitWithinViewportHeight, arrowElement]);
6454
+ const middleware = useMemo(() => buildPopoverMiddleware({
6455
+ offset,
6456
+ hasArrow,
6457
+ fitWidth,
6458
+ fitWithinViewportHeight,
6459
+ boundary,
6460
+ parsedPlacement,
6461
+ arrowElement
6462
+ }), [offset, hasArrow, fitWidth, fitWithinViewportHeight, boundary, parsedPlacement, arrowElement]);
6412
6463
  const anchorElement = anchorRef.current;
6413
6464
  const {
6414
6465
  floatingStyles,
@@ -6416,7 +6467,7 @@ function usePopoverStyle({
6416
6467
  isPositioned,
6417
6468
  middlewareData
6418
6469
  } = useFloating({
6419
- placement: floatingPlacement,
6470
+ placement: getFloatingPlacement(parsedPlacement),
6420
6471
  // Disable autoUpdate and element refs in non-browser environments (e.g. jsdom) to avoid
6421
6472
  // flushSync act() warnings from @floating-ui/react-dom (positioning is not meaningful in jsdom anyway).
6422
6473
  ...(IS_BROWSER$1 ? {
@@ -6431,14 +6482,7 @@ function usePopoverStyle({
6431
6482
  const position = resolvedPlacement ?? placement;
6432
6483
 
6433
6484
  // Compute arrow styles from middleware data
6434
- const arrowStyles = useMemo(() => {
6435
- const arrowData = middlewareData.arrow;
6436
- if (!arrowData) return undefined;
6437
- return {
6438
- left: arrowData.x != null ? `${arrowData.x}px` : '',
6439
- top: arrowData.y != null ? `${arrowData.y}px` : ''
6440
- };
6441
- }, [middlewareData.arrow]);
6485
+ const arrowStyles = useMemo(() => computeArrowStyles(middlewareData.arrow), [middlewareData.arrow]);
6442
6486
 
6443
6487
  // Merge floating styles with user-provided styles and zIndex
6444
6488
  const popoverStyle = useMemo(() => {
@@ -6462,35 +6506,16 @@ function usePopoverStyle({
6462
6506
  }
6463
6507
 
6464
6508
  /**
6465
- * Component display name.
6466
- */
6467
- const COMPONENT_NAME$Y = 'Popover';
6468
-
6469
- /**
6470
- * Component default class name and class prefix.
6509
+ * Defines the props of the component.
6510
+ * Extends core PopoverProps, overriding ref-typed props with React-specific `RefObject` types
6511
+ * and replacing `handleClose` with the React-idiomatic `onClose` callback.
6471
6512
  */
6472
- const CLASSNAME$Z = 'lumx-popover';
6473
- const {
6474
- block: block$Q,
6475
- element: element$E
6476
- } = classNames.bem(CLASSNAME$Z);
6477
-
6478
- /**
6479
- * Component default props.
6480
- */
6481
- const DEFAULT_PROPS$U = {
6482
- elevation: 3,
6483
- placement: Placement.AUTO,
6484
- focusAnchorOnClose: true,
6485
- usePortal: true,
6486
- zIndex: POPOVER_ZINDEX
6487
- };
6488
6513
 
6489
6514
  // Inner component (must be wrapped before export)
6490
6515
  const _InnerPopover = forwardRef((props, ref) => {
6491
6516
  const {
6492
6517
  anchorRef,
6493
- as: Component = 'div',
6518
+ as,
6494
6519
  children,
6495
6520
  className,
6496
6521
  closeOnClickAway,
@@ -6547,40 +6572,29 @@ const _InnerPopover = forwardRef((props, ref) => {
6547
6572
  useFocusTrap(withFocusTrap && isOpen && focusZoneElement, focusElement?.current);
6548
6573
  const clickAwayRefs = useRef([popoverRef, anchorRef]);
6549
6574
  const mergedRefs = useMergeRefs(setPopperElement, ref, popoverRef);
6550
- const adjustedElevation = Math.min(elevation || 0, 5);
6551
- return isOpen ? /*#__PURE__*/jsx(Portal, {
6552
- enabled: usePortal,
6553
- children: /*#__PURE__*/jsxs(Component, {
6554
- ...forwardedProps,
6555
- ref: mergedRefs,
6556
- className: classNames.join(className, block$Q({
6557
- [`theme-${theme}`]: Boolean(theme),
6558
- [`elevation-${adjustedElevation}`]: Boolean(adjustedElevation),
6559
- [`position-${position}`]: Boolean(position)
6560
- })),
6561
- style: styles.popover,
6562
- "data-popper-placement": position,
6563
- children: [unmountSentinel, /*#__PURE__*/jsxs(ClickAwayProvider, {
6564
- callback: closeOnClickAway && onClose,
6565
- childrenRefs: clickAwayRefs,
6566
- children: [hasArrow && /*#__PURE__*/jsx("div", {
6567
- ref: setArrowElement,
6568
- className: element$E('arrow'),
6569
- style: styles.arrow,
6570
- children: /*#__PURE__*/jsx("svg", {
6571
- viewBox: "0 0 14 14",
6572
- "aria-hidden": true,
6573
- children: /*#__PURE__*/jsx("path", {
6574
- d: "M8 3.49C7.62 2.82 6.66 2.82 6.27 3.48L.04 14 14.04 14 8 3.49Z"
6575
- })
6576
- })
6577
- }), /*#__PURE__*/jsx(ThemeProvider, {
6578
- value: theme,
6579
- children: children
6580
- })]
6581
- })]
6582
- })
6583
- }) : null;
6575
+ return Popover$1({
6576
+ ...forwardedProps,
6577
+ as: as,
6578
+ children,
6579
+ className,
6580
+ elevation,
6581
+ hasArrow,
6582
+ isOpen,
6583
+ position,
6584
+ popoverStyle: styles.popover,
6585
+ arrowStyle: styles.arrow,
6586
+ theme,
6587
+ ref: mergedRefs,
6588
+ arrowRef: setArrowElement,
6589
+ usePortal,
6590
+ clickAwayCallback: closeOnClickAway && onClose,
6591
+ clickAwayRefs,
6592
+ unmountSentinel
6593
+ }, {
6594
+ Portal,
6595
+ ClickAwayProvider,
6596
+ ThemeProvider
6597
+ });
6584
6598
  });
6585
6599
  _InnerPopover.displayName = COMPONENT_NAME$Y;
6586
6600
 
@@ -9018,20 +9032,6 @@ LinkPreview.displayName = COMPONENT_NAME$I;
9018
9032
  LinkPreview.className = CLASSNAME$J;
9019
9033
  LinkPreview.defaultProps = DEFAULT_PROPS$I;
9020
9034
 
9021
- /**
9022
- * Render link with default <a> HTML component or a custom one provided by `linkAs`.
9023
- *
9024
- * Can be used to inject the `Link` component from `react-router` and provide better a11y on LumX components.
9025
- *
9026
- * @param linkAs Custom link component.
9027
- * @param children Link children.
9028
- * @return A link.
9029
- */
9030
- const renderLink = ({
9031
- linkAs,
9032
- ...forwardedProps
9033
- }, ...children) => /*#__PURE__*/React__default.createElement(linkAs || 'a', forwardedProps, ...children);
9034
-
9035
9035
  /**
9036
9036
  * Component display name.
9037
9037
  */
@@ -9058,10 +9058,11 @@ const DEFAULT_PROPS$H = {
9058
9058
  * @return `true` if the list item is clickable; `false` otherwise.
9059
9059
  */
9060
9060
  function isClickable({
9061
+ linkAs,
9061
9062
  linkProps,
9062
9063
  onItemSelected
9063
9064
  }) {
9064
- return !isEmpty(linkProps?.href) || !!onItemSelected;
9065
+ return !!linkAs || !isEmpty(linkProps?.href) || !!onItemSelected;
9065
9066
  }
9066
9067
 
9067
9068
  /**
@@ -9091,23 +9092,10 @@ const ListItem = forwardRef((props, ref) => {
9091
9092
  size = DEFAULT_PROPS$H.size,
9092
9093
  ...forwardedProps
9093
9094
  } = otherProps;
9094
- const role = linkAs || linkProps.href ? 'link' : 'button';
9095
- const onKeyDown = useMemo(() => {
9096
- if (onItemSelected && role === 'link') return onEnterPressed(onItemSelected);
9097
- if (onItemSelected && role === 'button') return onButtonPressed(onItemSelected);
9098
- return undefined;
9099
- }, [role, onItemSelected]);
9100
- const content = /*#__PURE__*/jsxs(Fragment, {
9101
- children: [before && /*#__PURE__*/jsx("div", {
9102
- className: element$s('before'),
9103
- children: before
9104
- }), /*#__PURE__*/jsx("div", {
9105
- className: element$s('content'),
9106
- children: children
9107
- }), after && /*#__PURE__*/jsx("div", {
9108
- className: element$s('after'),
9109
- children: after
9110
- })]
9095
+ const clickable = isClickable({
9096
+ linkAs,
9097
+ linkProps,
9098
+ onItemSelected
9111
9099
  });
9112
9100
  return /*#__PURE__*/jsx("li", {
9113
9101
  ref: ref,
@@ -9115,31 +9103,29 @@ const ListItem = forwardRef((props, ref) => {
9115
9103
  className: classNames.join(className, block$C({
9116
9104
  [`size-${size}`]: Boolean(size)
9117
9105
  })),
9118
- children: isClickable({
9119
- linkProps,
9120
- onItemSelected
9121
- }) ? (/* Clickable list item */
9122
- renderLink({
9123
- linkAs,
9124
- tabIndex: !disabledStateProps.disabled ? 0 : undefined,
9125
- role,
9126
- 'aria-disabled': isAnyDisabled,
9106
+ children: RawClickable({
9107
+ as: clickable ? linkAs || (linkProps.href ? 'a' : 'button') : 'div',
9108
+ ...disabledStateProps,
9127
9109
  ...linkProps,
9128
- href: isAnyDisabled ? undefined : linkProps.href,
9129
- className: classNames.join(element$s('link', {
9110
+ className: classNames.join(element$s(clickable ? 'link' : 'wrapper', {
9130
9111
  'is-highlighted': isHighlighted,
9131
9112
  'is-selected': isSelected,
9132
9113
  'is-disabled': isAnyDisabled
9133
9114
  })),
9134
- onClick: isAnyDisabled ? undefined : onItemSelected,
9135
- onKeyDown: isAnyDisabled ? undefined : onKeyDown,
9136
- ref: linkRef
9137
- }, content)) :
9138
- /*#__PURE__*/
9139
- /* Non clickable list item */
9140
- jsx("div", {
9141
- className: element$s('wrapper'),
9142
- children: content
9115
+ handleClick: onItemSelected,
9116
+ ref: linkRef,
9117
+ children: /*#__PURE__*/jsxs(Fragment, {
9118
+ children: [before && /*#__PURE__*/jsx("div", {
9119
+ className: element$s('before'),
9120
+ children: before
9121
+ }), /*#__PURE__*/jsx("div", {
9122
+ className: element$s('content'),
9123
+ children: children
9124
+ }), after && /*#__PURE__*/jsx("div", {
9125
+ className: element$s('after'),
9126
+ children: after
9127
+ })]
9128
+ })
9143
9129
  })
9144
9130
  });
9145
9131
  });