orcs-design-system 3.3.32 → 3.3.34

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.
@@ -386,7 +386,8 @@ export const headerAvatarVariants = () => {
386
386
  headerAvatar: true,
387
387
  sizing: "small",
388
388
  image: "https://randomuser.me/api/portraits/men/32.jpg",
389
- imageAlt: "Avatar for John Doe"
389
+ imageAlt: "Avatar for John Doe",
390
+ onClick: handleClick
390
391
  }), /*#__PURE__*/_jsx(Avatar, {
391
392
  headerAvatar: true,
392
393
  sizing: "large",
@@ -399,7 +400,8 @@ export const headerAvatarVariants = () => {
399
400
  sizing: "small",
400
401
  shape: "square",
401
402
  image: "https://images.unsplash.com/photo-1464802686167-b939a6910659?q=80&w=3500&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
402
- imageAlt: "Avatar for Nebula UI"
403
+ imageAlt: "Avatar for Nebula UI",
404
+ onClick: handleClick
403
405
  })]
404
406
  });
405
407
  };
@@ -360,47 +360,54 @@ const HeaderAvatarShape = styled("div").withConfig({
360
360
  })
361
361
  };
362
362
  });
363
- const HeaderAvatarActionPopover = styled(Popover).withConfig({
364
- displayName: "Avatar__HeaderAvatarActionPopover",
363
+ const HeaderAvatarAction = styled("button").withConfig({
364
+ displayName: "Avatar__HeaderAvatarAction",
365
365
  componentId: "sc-1wtet2j-11"
366
+ })(() => ({
367
+ cursor: "pointer",
368
+ padding: "0",
369
+ background: "none",
370
+ border: "none",
371
+ outline: "none",
372
+ appearance: "none",
373
+ position: "relative",
374
+ "&:hover": {
375
+ "& > .icon-container": {
376
+ opacity: "1"
377
+ }
378
+ }
379
+ }));
380
+ const IconContainer = styled("div").withConfig({
381
+ displayName: "Avatar__IconContainer",
382
+ componentId: "sc-1wtet2j-12"
366
383
  })(_ref6 => {
367
384
  let {
368
- $shape
385
+ $shape,
386
+ $sizing
369
387
  } = _ref6;
370
388
  return {
389
+ opacity: "0",
390
+ transition: "opacity 0.2s ease-in-out",
371
391
  position: "absolute",
372
- top: 0,
373
- right: 0,
374
- transform: $shape === "circle" ? "translate(-5%, 5%)" : "translate(20%, -20%)"
375
- };
376
- });
377
- const HeaderAvatarAction = styled("button").withConfig({
378
- displayName: "Avatar__HeaderAvatarAction",
379
- componentId: "sc-1wtet2j-12"
380
- })(_ref7 => {
381
- let {
382
- ...props
383
- } = _ref7;
384
- return {
385
- width: "36px",
386
- height: "36px",
387
- borderRadius: "50%",
388
- background: "#e6e6e6",
389
- border: "solid 2px #fff",
390
- boxShadow: "0 2px 8px 0 rgba(0,0,0,0.10)",
392
+ top: $sizing === "large" ? "6px" : "4px",
393
+ left: $sizing === "large" ? "6px" : "4px",
394
+ width: $sizing === "large" ? "calc(100% - 12px)" : "calc(100% - 8px)",
395
+ height: $sizing === "large" ? "calc(100% - 18px)" : "calc(100% - 12px)",
391
396
  display: "flex",
392
397
  alignItems: "center",
393
398
  justifyContent: "center",
394
- cursor: "pointer",
395
- zIndex: 2,
396
- padding: 0,
397
- transition: "background 0.2s ease-in-out",
398
- "&:hover, &:focus": {
399
- background: themeGet("colors.primaryLighter")(props)
400
- }
399
+ background: "rgba(0, 0, 0, 0.5)",
400
+ zIndex: "2",
401
+ borderRadius: $shape === "circle" || !$shape ? "50%" : "0",
402
+ ...($shape === "hexagon" && {
403
+ clipPath: "polygon(50% 0, 95% 25%, 95% 75%, 50% 100%, 5% 75%, 5% 25%)"
404
+ }),
405
+ ...($shape === "tag" && {
406
+ clipPath: "polygon(6% 0, 95% 0, 95% 65%, 50% 100%, 6% 65%)"
407
+ })
401
408
  };
402
409
  });
403
- const Avatar = _ref8 => {
410
+ const Avatar = _ref7 => {
404
411
  let {
405
412
  sizing,
406
413
  image,
@@ -419,7 +426,7 @@ const Avatar = _ref8 => {
419
426
  headerAvatar = false,
420
427
  onClick,
421
428
  ...props
422
- } = _ref8;
429
+ } = _ref7;
423
430
  const hasTitle = !!title;
424
431
  const hasSubtitle = !!subtitle;
425
432
  const hasSubtitleContent = !!subtitleContent;
@@ -443,11 +450,11 @@ const Avatar = _ref8 => {
443
450
  theme
444
451
  }) || customSize;
445
452
  }
446
- return /*#__PURE__*/_jsxs(HeaderAvatarWrapper, {
453
+ const avatarContent = /*#__PURE__*/_jsx(HeaderAvatarWrapper, {
447
454
  ...props,
448
455
  $size: size,
449
456
  $shape: shape,
450
- children: [/*#__PURE__*/_jsx(HeaderAvatarBorder, {
457
+ children: /*#__PURE__*/_jsx(HeaderAvatarBorder, {
451
458
  $size: size,
452
459
  $shape: shape,
453
460
  $sizing: sizing,
@@ -469,27 +476,35 @@ const Avatar = _ref8 => {
469
476
  icon: ["fas", "user"]
470
477
  })
471
478
  })
472
- }), onClick && sizing === "large" && /*#__PURE__*/_jsx(HeaderAvatarActionPopover, {
479
+ })
480
+ });
481
+ if (onClick) {
482
+ return /*#__PURE__*/_jsx(Popover, {
473
483
  direction: "right",
474
484
  width: "fit-content",
475
485
  $shape: shape,
476
486
  text: shape === "circle" ? "Upload profile picture" : "Change image",
477
- children: /*#__PURE__*/_jsx(HeaderAvatarAction, {
487
+ children: /*#__PURE__*/_jsxs(HeaderAvatarAction, {
478
488
  onClick: onClick,
479
489
  "aria-label": "Edit avatar",
480
- children: shape === "circle" ? /*#__PURE__*/_jsx(Icon, {
481
- icon: ["fas", "camera"],
482
- size: "lg",
483
- color: "greyDarker"
484
- }) : /*#__PURE__*/_jsx(Icon, {
485
- icon: ["fas", "edit"],
486
- size: "lg",
487
- color: "greyDarker",
488
- transform: "right-1"
489
- })
490
+ children: [/*#__PURE__*/_jsx(IconContainer, {
491
+ $shape: shape,
492
+ $sizing: sizing,
493
+ className: "icon-container",
494
+ children: shape === "circle" ? /*#__PURE__*/_jsx(Icon, {
495
+ icon: ["fas", "camera"],
496
+ size: sizing === "large" ? "lg" : "1x",
497
+ color: "white"
498
+ }) : /*#__PURE__*/_jsx(Icon, {
499
+ icon: ["fas", "image"],
500
+ size: sizing === "large" ? "lg" : "1x",
501
+ color: "white"
502
+ })
503
+ }), avatarContent]
490
504
  })
491
- })]
492
- });
505
+ });
506
+ }
507
+ return avatarContent;
493
508
  }
494
509
  const component = /*#__PURE__*/_jsxs(AvatarWrapper, {
495
510
  ...props,
@@ -1,14 +1,17 @@
1
- import React, { useState, useEffect, useRef } from "react";
1
+ import React, { useState, useMemo } from "react";
2
2
  import PropTypes from "prop-types";
3
3
  import Box from "../Box";
4
4
  import ColorPickerLib from "react-best-gradient-color-picker";
5
+ import { FloatingPortal } from "@floating-ui/react";
6
+ import { getFloatingUiRootElement } from "../../utils/floatingUiHelpers";
7
+ import useActionMenu from "../ActionsMenu/useActionMenu";
5
8
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
6
9
  const ColorPicker = _ref => {
7
10
  let {
8
11
  value,
9
12
  onChange,
10
13
  children,
11
- position = "bottom-start",
14
+ position = "bottom-end",
12
15
  zIndex = 20,
13
16
  bg = "#202020",
14
17
  p = "s",
@@ -33,131 +36,52 @@ const ColorPicker = _ref => {
33
36
  ...colorPickerProps
34
37
  } = _ref;
35
38
  const [isOpen, setIsOpen] = useState(false);
36
- const colorPickerRef = useRef(null);
37
- const triggerRef = useRef(null);
38
-
39
- // Handle clicks outside to close
40
- useEffect(() => {
41
- function handleClickOutside(event) {
42
- if (colorPickerRef.current && !colorPickerRef.current.contains(event.target) && triggerRef.current && !triggerRef.current.contains(event.target)) {
43
- setIsOpen(false);
44
- }
45
- }
46
- if (isOpen) {
47
- document.addEventListener("mousedown", handleClickOutside);
48
- return () => {
49
- document.removeEventListener("mousedown", handleClickOutside);
50
- };
51
- }
52
- return undefined;
53
- }, [isOpen]);
54
39
  const toggleColorPicker = () => setIsOpen(!isOpen);
55
-
56
- // Calculate position based on position prop
57
- const getPositionStyles = () => {
58
- const baseStyles = {
59
- position: "absolute",
60
- zIndex,
61
- bg,
62
- p,
63
- borderRadius
64
- };
65
- switch (position) {
66
- case "top-start":
67
- return {
68
- ...baseStyles,
69
- bottom: "100%",
70
- right: "0",
71
- mb: "s"
72
- };
73
- case "top-end":
74
- return {
75
- ...baseStyles,
76
- bottom: "100%",
77
- left: "0",
78
- mb: "s"
79
- };
80
- case "bottom-start":
81
- return {
82
- ...baseStyles,
83
- top: "100%",
84
- right: "0",
85
- mt: "s"
86
- };
87
- case "bottom-end":
88
- return {
89
- ...baseStyles,
90
- top: "100%",
91
- left: "0",
92
- mt: "s"
93
- };
94
- case "left-start":
95
- return {
96
- ...baseStyles,
97
- right: "100%",
98
- top: "0",
99
- mr: "s"
100
- };
101
- case "left-end":
102
- return {
103
- ...baseStyles,
104
- right: "100%",
105
- bottom: "0",
106
- mr: "s"
107
- };
108
- case "right-start":
109
- return {
110
- ...baseStyles,
111
- left: "100%",
112
- top: "0",
113
- ml: "s"
114
- };
115
- case "right-end":
116
- return {
117
- ...baseStyles,
118
- left: "100%",
119
- bottom: "0",
120
- ml: "s"
121
- };
122
- default:
123
- return {
124
- ...baseStyles,
125
- top: "100%",
126
- right: "0",
127
- mt: "s"
128
- };
129
- }
130
- };
40
+ const baseStyles = useMemo(() => ({
41
+ zIndex,
42
+ bg,
43
+ p,
44
+ borderRadius
45
+ }), [zIndex, bg, p, borderRadius]);
46
+ const actionMenu = useActionMenu({
47
+ placement: position,
48
+ open: isOpen,
49
+ onOpenChange: setIsOpen
50
+ });
131
51
  return /*#__PURE__*/_jsxs(Box, {
132
- position: "relative",
133
- children: [/*#__PURE__*/_jsx(Box, {
134
- ref: triggerRef,
135
- children: typeof children === "function" ? children({
136
- isOpen,
137
- toggleColorPicker
138
- }) : children
139
- }), isOpen && /*#__PURE__*/_jsx(Box, {
140
- ref: colorPickerRef,
141
- ...getPositionStyles(),
142
- children: /*#__PURE__*/_jsx(ColorPickerLib, {
143
- value: value,
144
- onChange: onChange,
145
- width: width,
146
- height: height,
147
- hidePresets: hidePresets,
148
- hideInputs: hideInputs,
149
- hideControls: hideControls,
150
- hideOpacity: hideOpacity,
151
- hideEyeDrop: hideEyeDrop,
152
- hideAdvancedSliders: hideAdvancedSliders,
153
- hideColorGuide: hideColorGuide,
154
- hideInputType: hideInputType,
155
- hideColorTypeBtns: hideColorTypeBtns,
156
- hideGradientType: hideGradientType,
157
- hideGradientAngle: hideGradientAngle,
158
- hideGradientStop: hideGradientStop,
159
- hideGradientControls: hideGradientControls,
160
- ...colorPickerProps
52
+ ref: actionMenu.refs.setReference,
53
+ ...actionMenu.getReferenceProps(),
54
+ children: [typeof children === "function" ? children({
55
+ isOpen,
56
+ toggleColorPicker
57
+ }) : children, isOpen && /*#__PURE__*/_jsx(FloatingPortal, {
58
+ root: getFloatingUiRootElement(actionMenu.refs.reference),
59
+ preserveTabOrder: true,
60
+ children: /*#__PURE__*/_jsx(Box, {
61
+ ref: actionMenu.refs.setFloating,
62
+ style: actionMenu.floatingStyles,
63
+ ...baseStyles,
64
+ ...actionMenu.getFloatingProps(),
65
+ children: /*#__PURE__*/_jsx(ColorPickerLib, {
66
+ value: value,
67
+ onChange: onChange,
68
+ width: width,
69
+ height: height,
70
+ hidePresets: hidePresets,
71
+ hideInputs: hideInputs,
72
+ hideControls: hideControls,
73
+ hideOpacity: hideOpacity,
74
+ hideEyeDrop: hideEyeDrop,
75
+ hideAdvancedSliders: hideAdvancedSliders,
76
+ hideColorGuide: hideColorGuide,
77
+ hideInputType: hideInputType,
78
+ hideColorTypeBtns: hideColorTypeBtns,
79
+ hideGradientType: hideGradientType,
80
+ hideGradientAngle: hideGradientAngle,
81
+ hideGradientStop: hideGradientStop,
82
+ hideGradientControls: hideGradientControls,
83
+ ...colorPickerProps
84
+ })
161
85
  })
162
86
  })]
163
87
  });
@@ -197,7 +121,7 @@ ColorPicker.__docgenInfo = {
197
121
  "props": {
198
122
  "position": {
199
123
  "defaultValue": {
200
- "value": "\"bottom-start\"",
124
+ "value": "\"bottom-end\"",
201
125
  "computed": false
202
126
  },
203
127
  "description": "",
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useEffect, useMemo, useState } from "react";
1
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
2
  import ReactDOM from "react-dom";
3
3
  import PropTypes from "prop-types";
4
4
  import styled, { keyframes, ThemeProvider } from "styled-components";
@@ -72,6 +72,8 @@ const Modal = _ref => {
72
72
  ...restProps
73
73
  } = _ref;
74
74
  const [lastActiveElement, setLastActiveElement] = useState(null);
75
+ const [isSelectingText, setIsSelectingText] = useState(false);
76
+ const isSelectingTextRef = useRef(false);
75
77
  const ariaLabel = useMemo(() => {
76
78
  if (restProps.ariaLabel) {
77
79
  return restProps.ariaLabel;
@@ -101,28 +103,51 @@ const Modal = _ref => {
101
103
  focusLastActiveElement();
102
104
  }
103
105
  }, [visible, focusLastActiveElement, lastActiveElement]);
106
+ useEffect(() => {
107
+ isSelectingTextRef.current = isSelectingText;
108
+ }, [isSelectingText]);
104
109
  useEffect(() => {
105
110
  if (!visible) return;
106
111
 
107
112
  /* Adding onClick handler on the Overlay does not work.
108
113
  * So we add a global listener and check if the element clicked is the
109
- * overlay vida overlayID.
114
+ * overlay via overlayID.
110
115
  */
111
- const handler = e => {
116
+ const handleMouseDown = e => {
117
+ // Check if the user is starting to select text
118
+ if (e.target.closest(`#${modalID}`)) {
119
+ setIsSelectingText(true);
120
+ }
121
+ };
122
+ const handleMouseUp = () => {
123
+ // Reset text selection state after a short delay
124
+ setTimeout(() => {
125
+ setIsSelectingText(false);
126
+ }, 100);
127
+ };
128
+ const handleClick = e => {
129
+ if (e.target.id === overlayID && !isSelectingTextRef.current) {
130
+ onClose();
131
+ }
132
+ };
133
+ const handleTouchStart = e => {
112
134
  if (e.target.id === overlayID) {
113
135
  onClose();
114
136
  }
115
137
  };
116
- const eventTypes = ["touchstart", "click"];
117
- eventTypes.map(type => {
118
- window.addEventListener(type, handler, true);
119
- });
138
+
139
+ // Add event listeners
140
+ window.addEventListener("mousedown", handleMouseDown, true);
141
+ window.addEventListener("mouseup", handleMouseUp, true);
142
+ window.addEventListener("click", handleClick, true);
143
+ window.addEventListener("touchstart", handleTouchStart, true);
120
144
  return () => {
121
- eventTypes.map(type => {
122
- window.removeEventListener(type, handler, true);
123
- });
145
+ window.removeEventListener("mousedown", handleMouseDown, true);
146
+ window.removeEventListener("mouseup", handleMouseUp, true);
147
+ window.removeEventListener("click", handleClick, true);
148
+ window.removeEventListener("touchstart", handleTouchStart, true);
124
149
  };
125
- }, [visible, onClose, overlayID]);
150
+ }, [visible, onClose, overlayID, modalID]);
126
151
  if (!visible) return null;
127
152
  const component = /*#__PURE__*/_jsx(Overlay, {
128
153
  alignItems: "center",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orcs-design-system",
3
- "version": "3.3.32",
3
+ "version": "3.3.34",
4
4
  "engines": {
5
5
  "node": "20.12.2"
6
6
  },