@sprinklrjs/spaceweb 14.14.1 → 14.14.3

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 (42) hide show
  1. package/asyncSelect/hooks/useAsyncSelect.d.ts +3 -3
  2. package/asyncSelect/hooks/useGroupedAsyncSelect.d.ts +3 -3
  3. package/baseui/layer/tether.js +6 -3
  4. package/baseui/layer/types.d.ts +5 -0
  5. package/baseui/layer/utils.d.ts +25 -0
  6. package/baseui/layer/utils.js +74 -1
  7. package/baseui/popover/popover.js +61 -13
  8. package/baseui/popover/stateful-container.js +2 -1
  9. package/baseui/popover/styled-components.js +5 -0
  10. package/baseui/popover/types.d.ts +7 -0
  11. package/color-picker/CustomColorSelector.js +25 -15
  12. package/color-picker/constants.d.ts +3 -0
  13. package/color-picker/constants.js +3 -1
  14. package/date-picker/StatelessDatePicker.js +10 -8
  15. package/esm/asyncSelect/hooks/useAsyncSelect.d.ts +3 -3
  16. package/esm/asyncSelect/hooks/useGroupedAsyncSelect.d.ts +3 -3
  17. package/esm/baseui/layer/tether.js +7 -4
  18. package/esm/baseui/layer/types.d.ts +5 -0
  19. package/esm/baseui/layer/utils.d.ts +25 -0
  20. package/esm/baseui/layer/utils.js +71 -0
  21. package/esm/baseui/popover/popover.js +61 -13
  22. package/esm/baseui/popover/stateful-container.js +2 -1
  23. package/esm/baseui/popover/styled-components.js +5 -0
  24. package/esm/baseui/popover/types.d.ts +7 -0
  25. package/esm/color-picker/CustomColorSelector.js +26 -16
  26. package/esm/color-picker/constants.d.ts +3 -0
  27. package/esm/color-picker/constants.js +2 -0
  28. package/esm/date-picker/StatelessDatePicker.js +10 -8
  29. package/esm/helpers/colors.d.ts +1 -0
  30. package/esm/helpers/colors.js +14 -2
  31. package/esm/popover/popover.js +2 -2
  32. package/esm/tooltip/disabled-tooltip-container.d.ts +1 -0
  33. package/esm/tooltip/stateful-tooltip-container.d.ts +1 -0
  34. package/esm/tooltip/stateful-tooltip.d.ts +1 -0
  35. package/helpers/colors.d.ts +1 -0
  36. package/helpers/colors.js +16 -3
  37. package/package.json +2 -2
  38. package/popover/popover.js +2 -2
  39. package/tooltip/disabled-tooltip-container.d.ts +1 -0
  40. package/tooltip/stateful-tooltip-container.d.ts +1 -0
  41. package/tooltip/stateful-tooltip.d.ts +1 -0
  42. package/tsconfig.build.tsbuildinfo +1 -1
@@ -58,6 +58,7 @@ export declare const useAsyncSelect: ({ loadOptions, initialOptions, resolveSele
58
58
  OverlayContentContainer?: import("../../overrides").Override<any> | undefined;
59
59
  } | undefined;
60
60
  mountNode?: HTMLElement | null | undefined;
61
+ options?: import("../../select").Options;
61
62
  placement?: "auto" | "bottom" | "left" | "right" | "top" | "topLeft" | "topRight" | "rightTop" | "rightBottom" | "bottomRight" | "bottomLeft" | "leftBottom" | "leftTop" | undefined;
62
63
  noResultsMsg?: import("react").ReactNode;
63
64
  ownerDocument?: Document | undefined;
@@ -156,7 +157,6 @@ export declare const useAsyncSelect: ({ loadOptions, initialOptions, resolveSele
156
157
  onSelectResetsInput?: boolean | undefined;
157
158
  openOnClick?: boolean | undefined;
158
159
  startOpen?: boolean | undefined;
159
- options?: import("../../select").Options;
160
160
  searchable?: boolean | undefined;
161
161
  valueComponent?: import("react").ComponentType<any> | undefined;
162
162
  valueKey?: string | undefined;
@@ -254,6 +254,7 @@ export declare const useAsyncSelect: ({ loadOptions, initialOptions, resolveSele
254
254
  OverlayContentContainer?: import("../../overrides").Override<any> | undefined;
255
255
  } | undefined;
256
256
  mountNode?: HTMLElement | null | undefined;
257
+ options?: import("../../select").Options;
257
258
  placement?: "auto" | "bottom" | "left" | "right" | "top" | "topLeft" | "topRight" | "rightTop" | "rightBottom" | "bottomRight" | "bottomLeft" | "leftBottom" | "leftTop" | undefined;
258
259
  noResultsMsg?: import("react").ReactNode;
259
260
  ownerDocument?: Document | undefined;
@@ -352,7 +353,6 @@ export declare const useAsyncSelect: ({ loadOptions, initialOptions, resolveSele
352
353
  onSelectResetsInput?: boolean | undefined;
353
354
  openOnClick?: boolean | undefined;
354
355
  startOpen?: boolean | undefined;
355
- options?: import("../../select").Options;
356
356
  searchable?: boolean | undefined;
357
357
  valueComponent?: import("react").ComponentType<any> | undefined;
358
358
  valueKey?: string | undefined;
@@ -453,6 +453,7 @@ export declare const useAsyncSelect: ({ loadOptions, initialOptions, resolveSele
453
453
  OverlayContentContainer?: import("../../overrides").Override<any> | undefined;
454
454
  } | undefined;
455
455
  mountNode?: HTMLElement | null | undefined;
456
+ options?: import("../../select").Options;
456
457
  placement?: "auto" | "bottom" | "left" | "right" | "top" | "topLeft" | "topRight" | "rightTop" | "rightBottom" | "bottomRight" | "bottomLeft" | "leftBottom" | "leftTop" | undefined;
457
458
  noResultsMsg?: import("react").ReactNode;
458
459
  ownerDocument?: Document | undefined;
@@ -551,7 +552,6 @@ export declare const useAsyncSelect: ({ loadOptions, initialOptions, resolveSele
551
552
  onSelectResetsInput?: boolean | undefined;
552
553
  openOnClick?: boolean | undefined;
553
554
  startOpen?: boolean | undefined;
554
- options?: import("../../select").Options;
555
555
  searchable?: boolean | undefined;
556
556
  valueComponent?: import("react").ComponentType<any> | undefined;
557
557
  valueKey?: string | undefined;
@@ -28,6 +28,7 @@ export declare const useGroupedAsyncSelect: ({ onChange, showSelectAll, selectAl
28
28
  onChange?: ((params: import("../../select").OnChangeParams) => unknown) | undefined;
29
29
  $as?: import("react").ElementType | undefined;
30
30
  mountNode?: HTMLElement | null | undefined;
31
+ options?: import("../../select").Options;
31
32
  placement?: "auto" | "bottom" | "left" | "right" | "top" | "topLeft" | "topRight" | "rightTop" | "rightBottom" | "bottomRight" | "bottomLeft" | "leftBottom" | "leftTop" | undefined;
32
33
  noResultsMsg?: import("react").ReactNode;
33
34
  ownerDocument?: Document | undefined;
@@ -124,7 +125,6 @@ export declare const useGroupedAsyncSelect: ({ onChange, showSelectAll, selectAl
124
125
  onSelectResetsInput?: boolean | undefined;
125
126
  openOnClick?: boolean | undefined;
126
127
  startOpen?: boolean | undefined;
127
- options?: import("../../select").Options;
128
128
  searchable?: boolean | undefined;
129
129
  valueComponent?: import("react").ComponentType<any> | undefined;
130
130
  valueKey?: string | undefined;
@@ -192,6 +192,7 @@ export declare const useGroupedAsyncSelect: ({ onChange, showSelectAll, selectAl
192
192
  onChange?: ((params: import("../../select").OnChangeParams) => unknown) | undefined;
193
193
  $as?: import("react").ElementType | undefined;
194
194
  mountNode?: HTMLElement | null | undefined;
195
+ options?: import("../../select").Options;
195
196
  placement?: "auto" | "bottom" | "left" | "right" | "top" | "topLeft" | "topRight" | "rightTop" | "rightBottom" | "bottomRight" | "bottomLeft" | "leftBottom" | "leftTop" | undefined;
196
197
  noResultsMsg?: import("react").ReactNode;
197
198
  ownerDocument?: Document | undefined;
@@ -288,7 +289,6 @@ export declare const useGroupedAsyncSelect: ({ onChange, showSelectAll, selectAl
288
289
  onSelectResetsInput?: boolean | undefined;
289
290
  openOnClick?: boolean | undefined;
290
291
  startOpen?: boolean | undefined;
291
- options?: import("../../select").Options;
292
292
  searchable?: boolean | undefined;
293
293
  valueComponent?: import("react").ComponentType<any> | undefined;
294
294
  valueKey?: string | undefined;
@@ -358,6 +358,7 @@ export declare const useGroupedAsyncSelect: ({ onChange, showSelectAll, selectAl
358
358
  onChange?: ((params: import("../../select").OnChangeParams) => unknown) | undefined;
359
359
  $as?: import("react").ElementType | undefined;
360
360
  mountNode?: HTMLElement | null | undefined;
361
+ options?: import("../../select").Options;
361
362
  placement?: "auto" | "bottom" | "left" | "right" | "top" | "topLeft" | "topRight" | "rightTop" | "rightBottom" | "bottomRight" | "bottomLeft" | "leftBottom" | "leftTop" | undefined;
362
363
  noResultsMsg?: import("react").ReactNode;
363
364
  ownerDocument?: Document | undefined;
@@ -454,7 +455,6 @@ export declare const useGroupedAsyncSelect: ({ onChange, showSelectAll, selectAl
454
455
  onSelectResetsInput?: boolean | undefined;
455
456
  openOnClick?: boolean | undefined;
456
457
  startOpen?: boolean | undefined;
457
- options?: import("../../select").Options;
458
458
  searchable?: boolean | undefined;
459
459
  valueComponent?: import("react").ComponentType<any> | undefined;
460
460
  valueKey?: string | undefined;
@@ -100,7 +100,8 @@ var Tether = /** @class */ (function (_super) {
100
100
  if (this.props.popperRef &&
101
101
  (this.state.isMounted !== prevState.isMounted ||
102
102
  (prevProps === null || prevProps === void 0 ? void 0 : prevProps.placement) !== this.props.placement ||
103
- (prevProps === null || prevProps === void 0 ? void 0 : prevProps.positionFixed) !== this.props.positionFixed)) {
103
+ (prevProps === null || prevProps === void 0 ? void 0 : prevProps.positionFixed) !== this.props.positionFixed ||
104
+ (prevProps === null || prevProps === void 0 ? void 0 : prevProps.hideWhenTargetClipped) !== this.props.hideWhenTargetClipped)) {
104
105
  if (!this.props.anchorRef) {
105
106
  if (process.env.NODE_ENV !== 'production') {
106
107
  // eslint-disable-next-line no-console -- debug logging
@@ -124,7 +125,7 @@ var Tether = /** @class */ (function (_super) {
124
125
  return;
125
126
  var popperInitOptions = tslib_1.__assign({
126
127
  // Recommended placement (popper may ignore if it causes a viewport overflow, etc)
127
- placement: (0, utils_1.toPopperPlacement)(placement), modifiers: tslib_1.__assign({
128
+ placement: (0, utils_1.toPopperPlacement)(placement), modifiers: tslib_1.__assign(tslib_1.__assign({
128
129
  // Passing the arrow ref will measure the arrow when calculating styles
129
130
  arrow: {
130
131
  element: this.props.arrowRef,
@@ -140,7 +141,9 @@ var Tether = /** @class */ (function (_super) {
140
141
  enabled: true,
141
142
  fn: this.onPopperUpdate,
142
143
  order: 900,
143
- }, preventOverflow: { enabled: true } }, modifiers), positionFixed: this.props.positionFixed }, restOptions);
144
+ }, preventOverflow: { enabled: true } }, modifiers), (this.props.hideWhenTargetClipped && {
145
+ hide: tslib_1.__assign(tslib_1.__assign({}, modifiers === null || modifiers === void 0 ? void 0 : modifiers.hide), { enabled: true, fn: utils_1.hideWhenReferenceClipped }),
146
+ })), positionFixed: this.props.positionFixed }, restOptions);
144
147
  this.popper = new popper_js_1.default(this.props.anchorRef, this.props.popperRef, popperInitOptions);
145
148
  };
146
149
  Tether.prototype.destroyPopover = function () {
@@ -112,6 +112,8 @@ export type PopperDataObject = {
112
112
  popper: PopperOffset;
113
113
  };
114
114
  placement: string;
115
+ /** Set by popper.js `hide` modifier when the reference element is out of bounds. */
116
+ hide?: boolean;
115
117
  };
116
118
  export type PopperOptions = {
117
119
  placement: string;
@@ -146,6 +148,9 @@ export type TetherProps = {
146
148
  repositionOnResize?: boolean;
147
149
  /** When true, Popper.js uses fixed positioning math (must match CSS `position: fixed` on the popper). */
148
150
  positionFixed?: boolean;
151
+ /** When true, popper's `hide` modifier checks whether the anchor is clipped by any of its scroll parents
152
+ or the viewport, and reports it as `data.hide` in `onPopperUpdate`. */
153
+ hideWhenTargetClipped?: boolean;
149
154
  };
150
155
  export type TetherState = {
151
156
  isMounted: boolean;
@@ -4,3 +4,28 @@ export declare function toPopperPlacement(placement: TetherPlacement): string;
4
4
  * Takes the offset passed from popper.js and normalizes it
5
5
  */
6
6
  export declare function parsePopperOffset(offset: PopperOffset): NormalizedOffset;
7
+ /**
8
+ * Returns true when no part of the reference is visible after clipping it by every
9
+ * scroll parent (nested scroll containers) and the viewport.
10
+ */
11
+ export declare function isReferenceClipped(reference: Element, scrollParents?: Array<Element | Window>): boolean;
12
+ type HideModifierData = {
13
+ hide?: boolean;
14
+ instance: {
15
+ reference: Element;
16
+ scheduleUpdate: () => void;
17
+ state: {
18
+ scrollParents?: Array<Element | Window>;
19
+ };
20
+ options?: {
21
+ eventsEnabled?: boolean;
22
+ };
23
+ };
24
+ };
25
+ /**
26
+ * Replacement for popper.js v1 `hide` modifier. The default one only checks the `preventOverflow`
27
+ * boundary (viewport by default), this one checks all clipping parents.
28
+ * Popper re-runs modifiers on scroll of any registered parent, including parents with overflow hidden.
29
+ */
30
+ export declare function hideWhenReferenceClipped<T extends HideModifierData>(data: T): T;
31
+ export {};
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parsePopperOffset = exports.toPopperPlacement = void 0;
3
+ exports.hideWhenReferenceClipped = exports.isReferenceClipped = exports.parsePopperOffset = exports.toPopperPlacement = void 0;
4
+ var tslib_1 = require("tslib");
4
5
  function toPopperPlacement(placement) {
5
6
  return placement.replace(/(Top|Left)$/, '-start').replace(/(Right|Bottom)$/, '-end');
6
7
  }
@@ -15,3 +16,75 @@ function parsePopperOffset(offset) {
15
16
  };
16
17
  }
17
18
  exports.parsePopperOffset = parsePopperOffset;
19
+ // Visible (padding-box) area of a scroll parent, excluding borders and scrollbars
20
+ function getClipRect(scrollParent) {
21
+ if ('document' in scrollParent) {
22
+ var _a = scrollParent.document.documentElement, clientWidth = _a.clientWidth, clientHeight = _a.clientHeight;
23
+ return { top: 0, left: 0, bottom: clientHeight, right: clientWidth };
24
+ }
25
+ var _b = scrollParent.getBoundingClientRect(), top = _b.top, left = _b.left;
26
+ var clipTop = top + scrollParent.clientTop;
27
+ var clipLeft = left + scrollParent.clientLeft;
28
+ return {
29
+ top: clipTop,
30
+ left: clipLeft,
31
+ bottom: clipTop + scrollParent.clientHeight,
32
+ right: clipLeft + scrollParent.clientWidth,
33
+ };
34
+ }
35
+ function getClippingParents(reference) {
36
+ var _a;
37
+ var clippingParents = [];
38
+ var ownerWindow = (_a = reference.ownerDocument.defaultView) !== null && _a !== void 0 ? _a : window;
39
+ var parent = reference.parentElement;
40
+ while (parent) {
41
+ var _b = ownerWindow.getComputedStyle(parent), overflow = _b.overflow, overflowX = _b.overflowX, overflowY = _b.overflowY;
42
+ if (/(auto|scroll|overlay|hidden|clip)/.test("".concat(overflow, " ").concat(overflowX, " ").concat(overflowY))) {
43
+ clippingParents.push(parent);
44
+ }
45
+ parent = parent.parentElement;
46
+ }
47
+ return clippingParents;
48
+ }
49
+ /**
50
+ * Returns true when no part of the reference is visible after clipping it by every
51
+ * scroll parent (nested scroll containers) and the viewport.
52
+ */
53
+ function isReferenceClipped(reference, scrollParents) {
54
+ var _a;
55
+ if (scrollParents === void 0) { scrollParents = []; }
56
+ var _b = reference.getBoundingClientRect(), top = _b.top, left = _b.left, bottom = _b.bottom, right = _b.right;
57
+ var viewport = (_a = reference.ownerDocument.defaultView) !== null && _a !== void 0 ? _a : window;
58
+ // viewport is always a clipping boundary, even when popper event listeners are disabled
59
+ tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(scrollParents), false), [viewport], false).forEach(function (scrollParent) {
60
+ var clip = getClipRect(scrollParent);
61
+ top = Math.max(top, clip.top);
62
+ left = Math.max(left, clip.left);
63
+ bottom = Math.min(bottom, clip.bottom);
64
+ right = Math.min(right, clip.right);
65
+ });
66
+ // strict comparison so zero-sized references (e.g. collapsed text anchors) are not treated as clipped
67
+ return bottom < top || right < left;
68
+ }
69
+ exports.isReferenceClipped = isReferenceClipped;
70
+ /**
71
+ * Replacement for popper.js v1 `hide` modifier. The default one only checks the `preventOverflow`
72
+ * boundary (viewport by default), this one checks all clipping parents.
73
+ * Popper re-runs modifiers on scroll of any registered parent, including parents with overflow hidden.
74
+ */
75
+ function hideWhenReferenceClipped(data) {
76
+ var _a;
77
+ var _b = data.instance, reference = _b.reference, scheduleUpdate = _b.scheduleUpdate, state = _b.state, options = _b.options;
78
+ var scrollParents = (_a = state.scrollParents) !== null && _a !== void 0 ? _a : (state.scrollParents = []);
79
+ if ((options === null || options === void 0 ? void 0 : options.eventsEnabled) !== false) {
80
+ getClippingParents(reference).forEach(function (parent) {
81
+ if (!scrollParents.includes(parent)) {
82
+ scrollParents.push(parent);
83
+ parent.addEventListener('scroll', scheduleUpdate, { passive: true });
84
+ }
85
+ });
86
+ }
87
+ data.hide = isReferenceClipped(reference, scrollParents);
88
+ return data;
89
+ }
90
+ exports.hideWhenReferenceClipped = hideWhenReferenceClipped;
@@ -33,6 +33,7 @@ function getDefaultState(props) {
33
33
  isLayerMounted: false,
34
34
  autoFocusAfterPositioning: false,
35
35
  contentHost: null,
36
+ isTargetClipped: false,
36
37
  };
37
38
  }
38
39
  var PopoverInner = /** @class */ (function (_super) {
@@ -42,13 +43,23 @@ var PopoverInner = /** @class */ (function (_super) {
42
43
  _this.anchorRef = React.createRef();
43
44
  _this.popperRef = React.createRef();
44
45
  _this.arrowRef = React.createRef();
46
+ _this.focusedBeforeTargetClipped = null;
47
+ _this.focusMovedWhileTargetClipped = false;
45
48
  /**
46
49
  * Yes our "Stateless" popover still has state. This is private state that
47
50
  * customers shouldn't have to manage themselves, such as positioning and
48
51
  * other internal flags for managing animation states.
49
52
  */
50
- // @ts-ignore
53
+ // @ts-ignore -- Popover types are a mess
51
54
  _this.state = getDefaultState(_this.props);
55
+ _this.onFocusInWhileTargetClipped = function (event) {
56
+ if (event.target !== document.body && event.target !== document.documentElement) {
57
+ _this.focusMovedWhileTargetClipped = true;
58
+ }
59
+ };
60
+ _this.onMouseDownWhileTargetClipped = function () {
61
+ _this.focusMovedWhileTargetClipped = true;
62
+ };
52
63
  _this.animateIn = function () {
53
64
  if (_this.props.isOpen) {
54
65
  _this.setState({ isAnimating: true });
@@ -62,8 +73,9 @@ var PopoverInner = /** @class */ (function (_super) {
62
73
  _this.setState({
63
74
  isAnimating: false,
64
75
  // Reset to ideal placement specified in props
65
- // @ts-ignore
76
+ // @ts-ignore -- Popover types are a mess
66
77
  placement: _this.props.placement,
78
+ isTargetClipped: false,
67
79
  });
68
80
  }, _this.props.animateOutTime || constants_1.ANIMATE_OUT_TIME);
69
81
  }
@@ -99,10 +111,11 @@ var PopoverInner = /** @class */ (function (_super) {
99
111
  _this.onPopperUpdate = function (normalizedOffsets, data) {
100
112
  var placement = (0, utils_1.fromPopperPlacement)(data.placement) || constants_1.PLACEMENT.top;
101
113
  _this.setState({
102
- // @ts-ignore
114
+ // @ts-ignore -- Popover types are a mess
103
115
  arrowOffset: normalizedOffsets.arrow,
104
116
  popoverOffset: normalizedOffsets.popper,
105
117
  placement: placement,
118
+ isTargetClipped: Boolean(_this.props.hideWhenTargetClipped && data.hide),
106
119
  });
107
120
  // Now that element has been positioned, we can animate it in
108
121
  _this.animateInTimer = setTimeout(_this.animateIn, constants_1.ANIMATE_IN_TIME);
@@ -161,6 +174,9 @@ var PopoverInner = /** @class */ (function (_super) {
161
174
  if (prevProps.placement !== this.props.placement) {
162
175
  this.setState({ placement: (_a = this.props.placement) !== null && _a !== void 0 ? _a : constants_1.PLACEMENT.auto });
163
176
  }
177
+ if (prevState.isTargetClipped !== this.state.isTargetClipped) {
178
+ this.onTargetClippedChange();
179
+ }
164
180
  if (__DEV__) {
165
181
  if (!this.anchorRef.current) {
166
182
  // eslint-disable-next-line no-console -- logging error in dev mode
@@ -186,6 +202,40 @@ var PopoverInner = /** @class */ (function (_super) {
186
202
  };
187
203
  PopoverInner.prototype.componentWillUnmount = function () {
188
204
  this.clearTimers();
205
+ this.stopTrackingFocusWhileTargetClipped();
206
+ };
207
+ PopoverInner.prototype.stopTrackingFocusWhileTargetClipped = function () {
208
+ document.removeEventListener('focusin', this.onFocusInWhileTargetClipped);
209
+ document.removeEventListener('mousedown', this.onMouseDownWhileTargetClipped);
210
+ };
211
+ /**
212
+ * Browsers blur the focused element when it becomes `visibility: hidden`.
213
+ * Restore that focus when the popover is shown again, unless the user has moved focus elsewhere meanwhile.
214
+ */
215
+ PopoverInner.prototype.onTargetClippedChange = function () {
216
+ var activeElement = document.activeElement;
217
+ if (this.state.isTargetClipped) {
218
+ var popper = this.popperRef.current;
219
+ this.focusedBeforeTargetClipped =
220
+ popper && activeElement && popper.contains(activeElement) ? activeElement : null;
221
+ this.focusMovedWhileTargetClipped = false;
222
+ if (this.focusedBeforeTargetClipped) {
223
+ document.addEventListener('focusin', this.onFocusInWhileTargetClipped);
224
+ document.addEventListener('mousedown', this.onMouseDownWhileTargetClipped);
225
+ }
226
+ return;
227
+ }
228
+ var elementToFocus = this.focusedBeforeTargetClipped;
229
+ var shouldRestoreFocus = this.props.isOpen &&
230
+ !this.focusMovedWhileTargetClipped &&
231
+ (elementToFocus === null || elementToFocus === void 0 ? void 0 : elementToFocus.isConnected) &&
232
+ (!activeElement || activeElement === document.body || activeElement === document.documentElement);
233
+ this.stopTrackingFocusWhileTargetClipped();
234
+ this.focusedBeforeTargetClipped = null;
235
+ this.focusMovedWhileTargetClipped = false;
236
+ if (shouldRestoreFocus && elementToFocus) {
237
+ elementToFocus.focus({ preventScroll: true });
238
+ }
189
239
  };
190
240
  PopoverInner.prototype.clearTimers = function () {
191
241
  [
@@ -270,14 +320,13 @@ var PopoverInner = /** @class */ (function (_super) {
270
320
  return anchorProps;
271
321
  };
272
322
  PopoverInner.prototype.getPopoverBodyProps = function () {
323
+ var _a;
273
324
  var bodyProps = {};
274
- var popoverId = this.getPopoverIdAttr();
325
+ var popoverId = (_a = this.getPopoverIdAttr()) !== null && _a !== void 0 ? _a : undefined;
275
326
  if (this.isAccessibilityTypeMenu()) {
276
- // @ts-ignore
277
327
  bodyProps.id = popoverId;
278
328
  }
279
329
  else if (this.isAccessibilityTypeTooltip()) {
280
- // @ts-ignore
281
330
  bodyProps.id = popoverId;
282
331
  bodyProps.role = 'tooltip';
283
332
  }
@@ -289,12 +338,11 @@ var PopoverInner = /** @class */ (function (_super) {
289
338
  };
290
339
  PopoverInner.prototype.getSharedProps = function () {
291
340
  var _a = this.props, isOpen = _a.isOpen, showArrow = _a.showArrow, _b = _a.popoverMargin, popoverMargin = _b === void 0 ? constants_1.POPOVER_MARGIN : _b, _c = _a.positionFixed, positionFixed = _c === void 0 ? false : _c;
292
- var _d = this.state, isAnimating = _d.isAnimating, arrowOffset = _d.arrowOffset, popoverOffset = _d.popoverOffset, placement = _d.placement;
341
+ var _d = this.state, isAnimating = _d.isAnimating, arrowOffset = _d.arrowOffset, popoverOffset = _d.popoverOffset, placement = _d.placement, isTargetClipped = _d.isTargetClipped;
293
342
  return {
294
343
  $showArrow: !!showArrow,
295
344
  $arrowOffset: arrowOffset,
296
345
  $popoverOffset: popoverOffset,
297
- // @ts-ignore
298
346
  $placement: placement,
299
347
  $isAnimating: isAnimating,
300
348
  $animationDuration: this.props.animateOutTime || constants_1.ANIMATE_OUT_TIME,
@@ -302,6 +350,7 @@ var PopoverInner = /** @class */ (function (_super) {
302
350
  $popoverMargin: popoverMargin,
303
351
  $isHoverTrigger: this.isHoverTrigger(),
304
352
  $positionFixed: positionFixed,
353
+ $isTargetClipped: isTargetClipped,
305
354
  };
306
355
  };
307
356
  PopoverInner.prototype.getAnchorFromChildren = function () {
@@ -326,7 +375,7 @@ var PopoverInner = /** @class */ (function (_super) {
326
375
  return React.cloneElement(anchor, anchorProps);
327
376
  }
328
377
  return (
329
- // @ts-ignore
378
+ // @ts-expect-error - there's a null in anchorProps.id
330
379
  (0, jsx_runtime_1.jsx)(box_1.Box, tslib_1.__assign({ "$as": "span" }, anchorProps, { children: anchor }), "popover-anchor"));
331
380
  };
332
381
  PopoverInner.prototype.renderPopover = function (renderedContent) {
@@ -370,7 +419,7 @@ var PopoverInner = /** @class */ (function (_super) {
370
419
  // and have it replaced with the TetherBehavior props overrides
371
420
  popperOptions: tslib_1.__assign(tslib_1.__assign({}, defaultPopperOptions), this.props.popperOptions), onPopperUpdate: this.onPopperUpdate,
372
421
  // Placement is passed via props instead of state and used only for Popper.js configuration
373
- placement: this.props.placement, repositionOnResize: this.props.repositionOnResize, positionFixed: this.props.positionFixed }, { children: this.props.focusLock && this.props.accessibilityType !== constants_1.ACCESSIBILITY_TYPE.tooltip ? ((0, jsx_runtime_1.jsx)(react_focus_lock_1.default, tslib_1.__assign({ disabled: !this.props.focusLock, noFocusGuards: false,
422
+ placement: this.props.placement, repositionOnResize: this.props.repositionOnResize, positionFixed: this.props.positionFixed, hideWhenTargetClipped: this.props.hideWhenTargetClipped }, { children: this.props.focusLock && this.props.accessibilityType !== constants_1.ACCESSIBILITY_TYPE.tooltip ? ((0, jsx_runtime_1.jsx)(react_focus_lock_1.default, tslib_1.__assign({ disabled: !this.props.focusLock, noFocusGuards: false,
374
423
  // see popover-focus-loop.scenario.js for why hover cannot return focus
375
424
  returnFocus: !this.isHoverTrigger() && this.props.returnFocus, autoFocus: this.state.autoFocusAfterPositioning,
376
425
  // Allow focus to escape when UI is within an iframe
@@ -389,9 +438,8 @@ var PopoverInner = /** @class */ (function (_super) {
389
438
  var Popover = function (props) {
390
439
  var innerRef = props.innerRef;
391
440
  var gID = (0, react_uid_1.useUID)();
392
- return ((0, jsx_runtime_1.jsx)(PopoverInner, tslib_1.__assign({ id: props.id || gID,
393
- // @ts-expect-error
394
- ref: innerRef }, props)));
441
+ // @ts-expect-error - ref type mismatch
442
+ return (0, jsx_runtime_1.jsx)(PopoverInner, tslib_1.__assign({ id: props.id || gID, ref: innerRef }, props));
395
443
  };
396
444
  Popover.defaultProps = default_props_1.default;
397
445
  exports.default = Popover;
@@ -119,7 +119,7 @@ var StatefulContainer = /** @class */ (function (_super) {
119
119
  };
120
120
  StatefulContainer.prototype.render = function () {
121
121
  var _this = this;
122
- var _a = this.props, accessibilityType = _a.accessibilityType, autoFocus = _a.autoFocus, animateOutTime = _a.animateOutTime, dismissOnClickOutside = _a.dismissOnClickOutside, focusLock = _a.focusLock, ignoreBoundary = _a.ignoreBoundary, mountNode = _a.mountNode, onBlur = _a.onBlur, onClick = _a.onClick, onFocus = _a.onFocus, onMouseEnter = _a.onMouseEnter, onMouseLeave = _a.onMouseLeave, onMouseEnterDelay = _a.onMouseEnterDelay, onMouseLeaveDelay = _a.onMouseLeaveDelay, overrides = _a.overrides, placement = _a.placement, popperOptions = _a.popperOptions, renderAll = _a.renderAll, returnFocus = _a.returnFocus, showArrow = _a.showArrow, triggerType = _a.triggerType, popoverMargin = _a.popoverMargin, focusOptions = _a.focusOptions, repositionOnResize = _a.repositionOnResize, positionFixed = _a.positionFixed;
122
+ var _a = this.props, accessibilityType = _a.accessibilityType, autoFocus = _a.autoFocus, animateOutTime = _a.animateOutTime, dismissOnClickOutside = _a.dismissOnClickOutside, focusLock = _a.focusLock, ignoreBoundary = _a.ignoreBoundary, mountNode = _a.mountNode, onBlur = _a.onBlur, onClick = _a.onClick, onFocus = _a.onFocus, onMouseEnter = _a.onMouseEnter, onMouseLeave = _a.onMouseLeave, onMouseEnterDelay = _a.onMouseEnterDelay, onMouseLeaveDelay = _a.onMouseLeaveDelay, overrides = _a.overrides, placement = _a.placement, popperOptions = _a.popperOptions, renderAll = _a.renderAll, returnFocus = _a.returnFocus, showArrow = _a.showArrow, triggerType = _a.triggerType, popoverMargin = _a.popoverMargin, focusOptions = _a.focusOptions, repositionOnResize = _a.repositionOnResize, positionFixed = _a.positionFixed, hideWhenTargetClipped = _a.hideWhenTargetClipped;
123
123
  var popoverProps = {
124
124
  accessibilityType: accessibilityType,
125
125
  animateOutTime: animateOutTime,
@@ -160,6 +160,7 @@ var StatefulContainer = /** @class */ (function (_super) {
160
160
  focusOptions: focusOptions,
161
161
  repositionOnResize: repositionOnResize,
162
162
  positionFixed: positionFixed,
163
+ hideWhenTargetClipped: hideWhenTargetClipped,
163
164
  };
164
165
  popoverProps.onEsc = this.onEsc;
165
166
  if (dismissOnClickOutside) {
@@ -33,6 +33,7 @@ var popoverBodyStyle = function (_, props) {
33
33
  opposite = 'block-end';
34
34
  var marginStyles = {};
35
35
  if (opposite) {
36
+ // eslint-disable-next-line @sprinklrjs/hds-no-dynamic-classes -- all of these have been explicitly handled
36
37
  var property = "--sw-margin-".concat(opposite);
37
38
  marginStyles[property] = "".concat(($showArrow ? constants_1.ARROW_SIZE : 0) + $popoverMargin, "px");
38
39
  }
@@ -50,6 +51,7 @@ exports.Body = (0, style_1.styled)('div', 'absolute top-0 left-[--sw-left-direct
50
51
  if (opposite === 'bottom')
51
52
  opposite = 'block-end';
52
53
  // only one of the ml-[--sw-margin-left] mr-[--sw-margin-right] mt-[--sw-margin-block-start] mb-[--sw-margin-block-end] class should be applied
54
+ // eslint-disable-next-line @sprinklrjs/hds-no-dynamic-classes -- all of these have been explicitly handled
53
55
  return _opposite ? "m".concat(_opposite[0], "-[--sw-margin-").concat(opposite, "]") : '';
54
56
  }, function (_, _a) {
55
57
  var $isOpen = _a.$isOpen;
@@ -63,6 +65,9 @@ exports.Body = (0, style_1.styled)('div', 'absolute top-0 left-[--sw-left-direct
63
65
  }, function (_, _a) {
64
66
  var $positionFixed = _a.$positionFixed;
65
67
  return ($positionFixed ? 'transform-none fixed top-[--sw-top]' : '');
68
+ }, function (_, _a) {
69
+ var $isTargetClipped = _a.$isTargetClipped;
70
+ return ($isTargetClipped ? 'invisible pointer-events-none' : '');
66
71
  });
67
72
  exports.Body.displayName = 'Body';
68
73
  exports.Arrow = (0, style_1.styled)('div', 'h-[--sw-height] w-[--sw-width] absolute forced-colors:border-1');
@@ -84,6 +84,10 @@ export type BasePopoverProps = {
84
84
  repositionOnResize?: boolean;
85
85
  /** Uses the position, left and top properties instead of transform to adjust the popover **/
86
86
  positionFixed?: boolean;
87
+ /** Hides (without unmounting) the popover while its target is fully clipped by any scroll container
88
+ * or the viewport, and shows it again once the target scrolls back into view.
89
+ */
90
+ hideWhenTargetClipped?: boolean;
87
91
  };
88
92
  export type PopoverProps = BasePopoverProps & {
89
93
  /** Content that should trigger the popover to be shown (also acts as the anchor against
@@ -138,6 +142,7 @@ export type PopoverPrivateState = {
138
142
  isMounted: boolean;
139
143
  autoFocusAfterPositioning: boolean;
140
144
  contentHost: HTMLElement | null;
145
+ isTargetClipped: boolean;
141
146
  };
142
147
  export type ArrowStylePropsArg = {
143
148
  $arrowOffset: Offset;
@@ -152,6 +157,8 @@ export type BodyStylePropsArg = {
152
157
  $placement: TetherPlacement;
153
158
  $showArrow: boolean;
154
159
  $popoverMargin: number;
160
+ $positionFixed: boolean;
161
+ $isTargetClipped: boolean;
155
162
  };
156
163
  export type InnerStylePropsArg = {};
157
164
  export type SharedStylePropsArg = {} & ArrowStylePropsArg & BodyStylePropsArg;
@@ -10,6 +10,7 @@ var stack_1 = require("../stack");
10
10
  var box_1 = require("../box");
11
11
  var colors_1 = require("../helpers/colors");
12
12
  var transparentBackground_1 = tslib_1.__importDefault(require("../icon/components/transparentBackground"));
13
+ var constants_1 = require("./constants");
13
14
  var CustomPointer = function () { return ((0, jsx_runtime_1.jsx)(box_1.Box, { style: function (_a) {
14
15
  var rtlCompatible = _a.rtlCompatible;
15
16
  return rtlCompatible({ transform: 'translate(-50%, -2px)' });
@@ -64,6 +65,11 @@ var CustomEditableInput = function (_a) {
64
65
  // @ts-ignore -- @types/react-color doesn't properly include types for input
65
66
  var input = editableInput.input;
66
67
  var fireChange = function () {
68
+ var inputValue = input.value;
69
+ if (inputValue === String(value))
70
+ return;
71
+ if (label === 'Hex' && (0, colors_1.normalizeHex)(inputValue) === (0, colors_1.normalizeHex)(String(value)))
72
+ return;
67
73
  onChange(typedValue.current);
68
74
  };
69
75
  var keydownHandler = function (event) {
@@ -76,16 +82,15 @@ var CustomEditableInput = function (_a) {
76
82
  input.removeEventListener('blur', fireChange);
77
83
  input.removeEventListener('keydown', keydownHandler);
78
84
  };
79
- }, [editableInput, label, onChange]);
85
+ }, [editableInput, label, onChange, value]);
80
86
  return ((0, jsx_runtime_1.jsx)(common_1.EditableInput, { style: EDITABLE_INPUT_STYLES, label: label, value: value, onChange: handleChange, ref: setInput }));
81
87
  };
82
88
  function getNumberWithFallback(input, fallback) {
83
- var _fallback = fallback !== null && fallback !== void 0 ? fallback : 0;
84
- if (!input)
85
- return _fallback;
86
- if (Number.isNaN(+input))
87
- return _fallback;
88
- return parseInt(input);
89
+ if (fallback === void 0) { fallback = 0; }
90
+ var trimmedInput = input === null || input === void 0 ? void 0 : input.trim();
91
+ if (!trimmedInput || Number.isNaN(+trimmedInput))
92
+ return fallback;
93
+ return parseInt(trimmedInput);
89
94
  }
90
95
  var ColorPickerComponent = function (_props) {
91
96
  // react-color intercepts the onChange function, wraps the data, and forwards it accordingly
@@ -99,8 +104,9 @@ var ColorPickerComponent = function (_props) {
99
104
  // color which cause a flickering issue
100
105
  //https://github.com/casesandberg/react-color/blob/bc9a0e1dc5d11b06c511a8e02a95bd85c7129f4b/src/components/sketch/SketchFields.js#L51
101
106
  var _a = rgb !== null && rgb !== void 0 ? rgb : {}, r = _a.r, g = _a.g, b = _a.b, a = _a.a;
107
+ var hexInput = (_hex === null || _hex === void 0 ? void 0 : _hex.toLowerCase()) === 'transparent' ? '#000000' : _hex;
102
108
  // react-color doesn't support alpha hexes, so we need to insert it ourselves
103
- var hex = (0, colors_1.normalizeHexWithAlpha)(_hex, a);
109
+ var hex = (0, colors_1.normalizeHexWithAlpha)(hexInput, a);
104
110
  var handleHueChange = (0, react_1.useCallback)(function (data) {
105
111
  // If alpha was zero and the saturation/lightness is changed, reset alpha to full
106
112
  if ('a' in data && data.a === 0) {
@@ -113,15 +119,19 @@ var ColorPickerComponent = function (_props) {
113
119
  // react-color emitted data is very dynamic and uses properties from labels
114
120
  if ('Hex' in data) {
115
121
  var newHex = data.Hex;
116
- var parsedRgba = (0, colors_1.hexToRgb)(data.Hex);
122
+ if (newHex.toLowerCase() === 'transparent' && hex !== constants_1.TRANSPARENT_HEX) {
123
+ onChange(constants_1.TRANSPARENT_RGBA);
124
+ onChangeComplete({ rgb: constants_1.TRANSPARENT_RGBA });
125
+ return;
126
+ }
127
+ if (!(0, colors_1.isValidHex)(newHex))
128
+ return;
129
+ var parsedRgba = (0, colors_1.hexToRgb)(newHex);
117
130
  var newRgba = enableAlphaSelector ? parsedRgba : tslib_1.__assign(tslib_1.__assign({}, parsedRgba), { a: 1 }); // No alpha values when enableAlphaSelector is disabled
118
131
  onChange(newRgba);
119
- // No need to invoke onChange based on isValidHex as onChange is standard handler for react-color
120
- // CustomPicker HOC takes care that onChange is invoked with correct values in case of invalid value of rgba.
121
- if ((0, colors_1.isValidHex)(newHex))
122
- onChangeComplete({ rgb: newRgba });
132
+ onChangeComplete({ rgb: newRgba });
123
133
  }
124
- else if (data.R || data.G || data.B || data.A) {
134
+ else if ('R' in data || 'G' in data || 'B' in data || 'A' in data) {
125
135
  var _a = tslib_1.__read(Object.keys(data), 1), changedKey = _a[0];
126
136
  // Reset alpha IF:
127
137
  // Changed value is R/G/B AND current alpha is 0 AND new value is different from old value
@@ -135,7 +145,7 @@ var ColorPickerComponent = function (_props) {
135
145
  onChange(newRgba);
136
146
  onChangeComplete({ rgb: newRgba });
137
147
  }
138
- }, [onChange, onChangeComplete, enableAlphaSelector, r, g, b, a]);
148
+ }, [onChange, onChangeComplete, enableAlphaSelector, r, g, b, a, hex]);
139
149
  return ((0, jsx_runtime_1.jsxs)(stack_1.Stack, tslib_1.__assign({ direction: "vertical", gap: 4 }, { children: [renderColorSuggestionPanel ? renderColorSuggestionPanel(hex) : null, (0, jsx_runtime_1.jsx)(box_1.Box, tslib_1.__assign({ className: "relative w-full h-32 rounded-16 overflow-hidden", style: { height: '150px' } }, { children: (0, jsx_runtime_1.jsx)(common_1.Saturation, tslib_1.__assign({}, props, { onChange: handleHueChange })) })), (0, jsx_runtime_1.jsxs)(stack_1.Stack, tslib_1.__assign({ direction: "vertical", gap: 2 }, { children: [(0, jsx_runtime_1.jsx)(box_1.Box, tslib_1.__assign({ className: "flex gap-2 justify-between ml-2" }, { children: (0, jsx_runtime_1.jsxs)(box_1.Box, tslib_1.__assign({ className: "flex flex-col items-start gap-2" }, { children: [(0, jsx_runtime_1.jsxs)(box_1.Box, tslib_1.__assign({ className: "flex items-center gap-2" }, { children: [(0, jsx_runtime_1.jsx)(box_1.Box, tslib_1.__assign({ className: "relative h-3", style: { width: enableAlphaSelector ? '261px' : '228px' } }, { children: (0, jsx_runtime_1.jsx)(common_1.Hue, tslib_1.__assign({ pointer: CustomPointer, radius: "24px" }, props, { onChange: handleHueChange })) })), (0, jsx_runtime_1.jsx)(exports.ColorPreview, { color: rgb })] })), enableAlphaSelector ? ((0, jsx_runtime_1.jsx)(box_1.Box, tslib_1.__assign({ className: "relative h-3", style: { width: '261px' } }, { children: (0, jsx_runtime_1.jsx)(common_1.Alpha, tslib_1.__assign({ pointer: CustomPointer, radius: "24px", style: { container: { margin: 0 } } }, props)) }))) : null] })) })), (0, jsx_runtime_1.jsxs)(box_1.Box, tslib_1.__assign({ className: "grid w-full gap-2",
140
150
  // 5 columns with alpha, 4 columns without
141
151
  style: {
@@ -1,3 +1,4 @@
1
+ import type { RGBColor } from 'react-color';
1
2
  export declare const GRADIENT_TYPE: {
2
3
  LINEAR: string;
3
4
  RADIAL: string;
@@ -12,3 +13,5 @@ export declare const COLOR_TYPE: {
12
13
  readonly GRADIENT: "gradient";
13
14
  };
14
15
  export declare const SWATCHES_PER_ROW = 10;
16
+ export declare const TRANSPARENT_HEX = "#00000000";
17
+ export declare const TRANSPARENT_RGBA: RGBColor;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SWATCHES_PER_ROW = exports.COLOR_TYPE = exports.TAB_IDS = exports.GRADIENT_TYPE = void 0;
3
+ exports.TRANSPARENT_RGBA = exports.TRANSPARENT_HEX = exports.SWATCHES_PER_ROW = exports.COLOR_TYPE = exports.TAB_IDS = exports.GRADIENT_TYPE = void 0;
4
4
  exports.GRADIENT_TYPE = {
5
5
  LINEAR: 'linear',
6
6
  RADIAL: 'radial',
@@ -11,3 +11,5 @@ exports.COLOR_TYPE = {
11
11
  GRADIENT: 'gradient',
12
12
  };
13
13
  exports.SWATCHES_PER_ROW = 10;
14
+ exports.TRANSPARENT_HEX = '#00000000';
15
+ exports.TRANSPARENT_RGBA = { r: 0, g: 0, b: 0, a: 0 };