orcs-design-system 3.3.65 → 3.3.67
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/es/components/ColorPicker/ColorPicker.stories.js +52 -0
- package/es/components/ColorPicker/index.js +15 -2
- package/es/components/SideNavV2/SideNav.js +5 -1
- package/es/components/SideNavV2/__tests__/resize.test.js +65 -0
- package/es/components/SideNavV2/components/ExpandedPanel.js +33 -4
- package/es/components/SideNavV2/hooks/useResize.js +6 -0
- package/package.json +1 -1
|
@@ -123,6 +123,53 @@ export const Controlled = () => {
|
|
|
123
123
|
})
|
|
124
124
|
});
|
|
125
125
|
};
|
|
126
|
+
export const DefaultOpen = () => {
|
|
127
|
+
const [color, setColor] = useState(initialColor);
|
|
128
|
+
return /*#__PURE__*/_jsx(Box, {
|
|
129
|
+
p: "l",
|
|
130
|
+
position: "relative",
|
|
131
|
+
children: /*#__PURE__*/_jsx(Flex, {
|
|
132
|
+
width: "100%",
|
|
133
|
+
height: "150px",
|
|
134
|
+
justifyContent: "flex-end",
|
|
135
|
+
alignItems: "flex-start",
|
|
136
|
+
background: color,
|
|
137
|
+
borderRadius: "2",
|
|
138
|
+
p: "r",
|
|
139
|
+
children: /*#__PURE__*/_jsx(ColorPicker, {
|
|
140
|
+
value: color,
|
|
141
|
+
onChange: setColor,
|
|
142
|
+
position: "bottom-start",
|
|
143
|
+
defaultOpen: true,
|
|
144
|
+
children: _ref3 => {
|
|
145
|
+
let {
|
|
146
|
+
toggleColorPicker
|
|
147
|
+
} = _ref3;
|
|
148
|
+
return /*#__PURE__*/_jsx(Popover, {
|
|
149
|
+
direction: "left",
|
|
150
|
+
height: "35px",
|
|
151
|
+
width: "fit-content",
|
|
152
|
+
text: "Picker locked open",
|
|
153
|
+
ml: "auto",
|
|
154
|
+
children: /*#__PURE__*/_jsx(Button, {
|
|
155
|
+
onClick: toggleColorPicker,
|
|
156
|
+
height: "35px",
|
|
157
|
+
width: "35px",
|
|
158
|
+
borderRadius: "35px",
|
|
159
|
+
borderColor: "white30",
|
|
160
|
+
bg: "white30",
|
|
161
|
+
ariaLabel: "Colour picker always open",
|
|
162
|
+
children: /*#__PURE__*/_jsx(Icon, {
|
|
163
|
+
icon: ["fas", "palette"],
|
|
164
|
+
color: "white"
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
})
|
|
170
|
+
})
|
|
171
|
+
});
|
|
172
|
+
};
|
|
126
173
|
Default.__docgenInfo = {
|
|
127
174
|
"description": "",
|
|
128
175
|
"methods": [],
|
|
@@ -132,4 +179,9 @@ Controlled.__docgenInfo = {
|
|
|
132
179
|
"description": "",
|
|
133
180
|
"methods": [],
|
|
134
181
|
"displayName": "Controlled"
|
|
182
|
+
};
|
|
183
|
+
DefaultOpen.__docgenInfo = {
|
|
184
|
+
"description": "",
|
|
185
|
+
"methods": [],
|
|
186
|
+
"displayName": "DefaultOpen"
|
|
135
187
|
};
|
|
@@ -38,11 +38,12 @@ const ColorPicker = _ref => {
|
|
|
38
38
|
onReset,
|
|
39
39
|
isSaving,
|
|
40
40
|
isResetting,
|
|
41
|
+
defaultOpen = false,
|
|
41
42
|
// Spread all other props to the underlying library
|
|
42
43
|
...colorPickerProps
|
|
43
44
|
} = _ref;
|
|
44
45
|
const [initialColor, setInitialColor] = useState(value);
|
|
45
|
-
const [isOpen, setIsOpen] = useState(
|
|
46
|
+
const [isOpen, setIsOpen] = useState(defaultOpen);
|
|
46
47
|
const [color, setColor] = useState(value);
|
|
47
48
|
const toggleColorPicker = () => setIsOpen(!isOpen);
|
|
48
49
|
const baseStyles = useMemo(() => ({
|
|
@@ -169,7 +170,8 @@ ColorPicker.propTypes = {
|
|
|
169
170
|
onSave: PropTypes.func,
|
|
170
171
|
onReset: PropTypes.func,
|
|
171
172
|
isSaving: PropTypes.bool,
|
|
172
|
-
isResetting: PropTypes.bool
|
|
173
|
+
isResetting: PropTypes.bool,
|
|
174
|
+
defaultOpen: PropTypes.bool
|
|
173
175
|
// Note: We don't need to define PropTypes for the spread props
|
|
174
176
|
// as they'll be passed directly to the underlying library
|
|
175
177
|
};
|
|
@@ -423,6 +425,17 @@ ColorPicker.__docgenInfo = {
|
|
|
423
425
|
},
|
|
424
426
|
"required": false
|
|
425
427
|
},
|
|
428
|
+
"defaultOpen": {
|
|
429
|
+
"defaultValue": {
|
|
430
|
+
"value": "false",
|
|
431
|
+
"computed": false
|
|
432
|
+
},
|
|
433
|
+
"description": "",
|
|
434
|
+
"type": {
|
|
435
|
+
"name": "bool"
|
|
436
|
+
},
|
|
437
|
+
"required": false
|
|
438
|
+
},
|
|
426
439
|
"value": {
|
|
427
440
|
"description": "",
|
|
428
441
|
"type": {
|
|
@@ -73,6 +73,8 @@ const SideNavV2 = _ref => {
|
|
|
73
73
|
// Memoize expensive calculations to prevent unnecessary re-renders
|
|
74
74
|
const currentItem = useMemo(() => expandedItem !== null ? items[expandedItem] : null, [expandedItem, items]);
|
|
75
75
|
const {
|
|
76
|
+
isResizing,
|
|
77
|
+
hasResized,
|
|
76
78
|
handleResizeStart
|
|
77
79
|
} = useResize(expandedRef, isSmallScreen, expandedItem, handleWidthChange, currentItem);
|
|
78
80
|
|
|
@@ -147,7 +149,9 @@ const SideNavV2 = _ref => {
|
|
|
147
149
|
isSmallScreen: isSmallScreen,
|
|
148
150
|
expandedRef: expandedRef,
|
|
149
151
|
onResizeStart: handleResizeStart,
|
|
150
|
-
onItemClick: handleItemClick
|
|
152
|
+
onItemClick: handleItemClick,
|
|
153
|
+
isResizing: isResizing,
|
|
154
|
+
hasResized: hasResized
|
|
151
155
|
}, item.name);
|
|
152
156
|
})]
|
|
153
157
|
});
|
|
@@ -31,6 +31,9 @@ const TestComponent = _ref => {
|
|
|
31
31
|
}), /*#__PURE__*/_jsx("div", {
|
|
32
32
|
"data-testid": "resize-status",
|
|
33
33
|
children: resizeHandlers.isResizing ? "resizing" : "not-resizing"
|
|
34
|
+
}), /*#__PURE__*/_jsx("div", {
|
|
35
|
+
"data-testid": "has-resized-status",
|
|
36
|
+
children: resizeHandlers.hasResized ? "has-resized" : "not-resized"
|
|
34
37
|
})]
|
|
35
38
|
});
|
|
36
39
|
};
|
|
@@ -145,4 +148,66 @@ describe("useResize hook", () => {
|
|
|
145
148
|
});
|
|
146
149
|
expect(mockExpandedRef.current.style.height).toBe("250px");
|
|
147
150
|
});
|
|
151
|
+
it("should track isResizing state correctly during resize operations", () => {
|
|
152
|
+
const {
|
|
153
|
+
getByTestId
|
|
154
|
+
} = render(/*#__PURE__*/_jsx(TestComponent, {
|
|
155
|
+
expandedRef: mockExpandedRef,
|
|
156
|
+
isSmallScreen: false,
|
|
157
|
+
expandedItem: 0,
|
|
158
|
+
onWidthChange: mockOnWidthChange,
|
|
159
|
+
currentItem: 1
|
|
160
|
+
}));
|
|
161
|
+
|
|
162
|
+
// Initially not resizing
|
|
163
|
+
expect(getByTestId("resize-status")).toHaveTextContent("not-resizing");
|
|
164
|
+
|
|
165
|
+
// Start resizing
|
|
166
|
+
const resizeHandle = getByTestId("resize-handle");
|
|
167
|
+
fireEvent.mouseDown(resizeHandle);
|
|
168
|
+
|
|
169
|
+
// Should be resizing now
|
|
170
|
+
expect(getByTestId("resize-status")).toHaveTextContent("resizing");
|
|
171
|
+
|
|
172
|
+
// End resize
|
|
173
|
+
fireEvent.mouseUp(document);
|
|
174
|
+
|
|
175
|
+
// Should not be resizing anymore
|
|
176
|
+
expect(getByTestId("resize-status")).toHaveTextContent("not-resizing");
|
|
177
|
+
});
|
|
178
|
+
it("should track hasResized state correctly when resize movement occurs", () => {
|
|
179
|
+
const {
|
|
180
|
+
getByTestId
|
|
181
|
+
} = render(/*#__PURE__*/_jsx(TestComponent, {
|
|
182
|
+
expandedRef: mockExpandedRef,
|
|
183
|
+
isSmallScreen: false,
|
|
184
|
+
expandedItem: 0,
|
|
185
|
+
onWidthChange: mockOnWidthChange,
|
|
186
|
+
currentItem: 1
|
|
187
|
+
}));
|
|
188
|
+
|
|
189
|
+
// Initially not resized
|
|
190
|
+
expect(getByTestId("has-resized-status")).toHaveTextContent("not-resized");
|
|
191
|
+
|
|
192
|
+
// Start resizing
|
|
193
|
+
const resizeHandle = getByTestId("resize-handle");
|
|
194
|
+
fireEvent.mouseDown(resizeHandle);
|
|
195
|
+
|
|
196
|
+
// Still not resized (no movement yet)
|
|
197
|
+
expect(getByTestId("has-resized-status")).toHaveTextContent("not-resized");
|
|
198
|
+
|
|
199
|
+
// Simulate mouse move (actual resize)
|
|
200
|
+
fireEvent.mouseMove(document, {
|
|
201
|
+
clientX: 600
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// Should be marked as resized
|
|
205
|
+
expect(getByTestId("has-resized-status")).toHaveTextContent("has-resized");
|
|
206
|
+
|
|
207
|
+
// End resize
|
|
208
|
+
fireEvent.mouseUp(document);
|
|
209
|
+
|
|
210
|
+
// Should still be marked as resized
|
|
211
|
+
expect(getByTestId("has-resized-status")).toHaveTextContent("has-resized");
|
|
212
|
+
});
|
|
148
213
|
});
|
|
@@ -21,6 +21,8 @@ import Icon from "../../Icon";
|
|
|
21
21
|
* @param {React.RefObject} props.expandedRef - Ref for the expanded panel
|
|
22
22
|
* @param {Function} props.onResizeStart - Resize start handler
|
|
23
23
|
* @param {Function} props.onItemClick - Item click handler
|
|
24
|
+
* @param {boolean} props.isResizing - Whether a resize operation is currently active
|
|
25
|
+
* @param {boolean} props.hasResized - Whether any resize movement has occurred
|
|
24
26
|
* @returns {JSX.Element} Rendered expanded panel or null if not applicable
|
|
25
27
|
*/
|
|
26
28
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
@@ -33,7 +35,9 @@ const ExpandedPanel = _ref => {
|
|
|
33
35
|
isSmallScreen,
|
|
34
36
|
expandedRef,
|
|
35
37
|
onResizeStart,
|
|
36
|
-
onItemClick
|
|
38
|
+
onItemClick,
|
|
39
|
+
isResizing,
|
|
40
|
+
hasResized
|
|
37
41
|
} = _ref;
|
|
38
42
|
const panelRef = useRef(null);
|
|
39
43
|
const isHoveringInPanelRef = useRef(false);
|
|
@@ -61,7 +65,7 @@ const ExpandedPanel = _ref => {
|
|
|
61
65
|
return /*#__PURE__*/_jsxs(Box, {
|
|
62
66
|
position: "relative",
|
|
63
67
|
height: "100%",
|
|
64
|
-
zIndex: "
|
|
68
|
+
zIndex: "1",
|
|
65
69
|
children: [/*#__PURE__*/_jsxs(SideNavExpanded, {
|
|
66
70
|
ref: el => {
|
|
67
71
|
expandedRef.current = el;
|
|
@@ -78,6 +82,15 @@ const ExpandedPanel = _ref => {
|
|
|
78
82
|
}), item.component()]
|
|
79
83
|
}), /*#__PURE__*/_jsx(ResizeHandle, {
|
|
80
84
|
onMouseDown: onResizeStart,
|
|
85
|
+
onClick: e => {
|
|
86
|
+
// Prevent click from firing if we're currently resizing or if we've resized
|
|
87
|
+
if (isResizing || hasResized) {
|
|
88
|
+
e.preventDefault();
|
|
89
|
+
e.stopPropagation();
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
onItemClick(item, true);
|
|
93
|
+
},
|
|
81
94
|
children: /*#__PURE__*/_jsxs(ToggleIcon, {
|
|
82
95
|
className: "resize-icon",
|
|
83
96
|
children: [/*#__PURE__*/_jsx(Icon, {
|
|
@@ -107,10 +120,12 @@ ExpandedPanel.propTypes = {
|
|
|
107
120
|
isSmallScreen: PropTypes.bool,
|
|
108
121
|
expandedRef: PropTypes.object,
|
|
109
122
|
onResizeStart: PropTypes.func.isRequired,
|
|
110
|
-
onItemClick: PropTypes.func.isRequired
|
|
123
|
+
onItemClick: PropTypes.func.isRequired,
|
|
124
|
+
isResizing: PropTypes.bool,
|
|
125
|
+
hasResized: PropTypes.bool
|
|
111
126
|
};
|
|
112
127
|
ExpandedPanel.__docgenInfo = {
|
|
113
|
-
"description": "ExpandedPanel - A resizable panel component for expanded navigation items\n\nRenders an expandable panel that can be resized by the user. Supports both\ndesktop (horizontal resize) and mobile (vertical resize) orientations.\nHover behavior is handled at the parent component level.\n\n@param {Object} props - Component props\n@param {Object} props.item - Navigation item data\n@param {number} [props.expandedItem] - Currently expanded item index\n@param {boolean} props.isExpanded - Whether the navigation is expanded\n@param {number} [props.expandedWidth] - Width of the expanded panel (desktop)\n@param {boolean} props.isSmallScreen - Whether currently on a small screen\n@param {React.RefObject} props.expandedRef - Ref for the expanded panel\n@param {Function} props.onResizeStart - Resize start handler\n@param {Function} props.onItemClick - Item click handler\n@returns {JSX.Element} Rendered expanded panel or null if not applicable",
|
|
128
|
+
"description": "ExpandedPanel - A resizable panel component for expanded navigation items\n\nRenders an expandable panel that can be resized by the user. Supports both\ndesktop (horizontal resize) and mobile (vertical resize) orientations.\nHover behavior is handled at the parent component level.\n\n@param {Object} props - Component props\n@param {Object} props.item - Navigation item data\n@param {number} [props.expandedItem] - Currently expanded item index\n@param {boolean} props.isExpanded - Whether the navigation is expanded\n@param {number} [props.expandedWidth] - Width of the expanded panel (desktop)\n@param {boolean} props.isSmallScreen - Whether currently on a small screen\n@param {React.RefObject} props.expandedRef - Ref for the expanded panel\n@param {Function} props.onResizeStart - Resize start handler\n@param {Function} props.onItemClick - Item click handler\n@param {boolean} props.isResizing - Whether a resize operation is currently active\n@param {boolean} props.hasResized - Whether any resize movement has occurred\n@returns {JSX.Element} Rendered expanded panel or null if not applicable",
|
|
114
129
|
"methods": [],
|
|
115
130
|
"displayName": "ExpandedPanel",
|
|
116
131
|
"props": {
|
|
@@ -191,6 +206,20 @@ ExpandedPanel.__docgenInfo = {
|
|
|
191
206
|
"name": "func"
|
|
192
207
|
},
|
|
193
208
|
"required": true
|
|
209
|
+
},
|
|
210
|
+
"isResizing": {
|
|
211
|
+
"description": "",
|
|
212
|
+
"type": {
|
|
213
|
+
"name": "bool"
|
|
214
|
+
},
|
|
215
|
+
"required": false
|
|
216
|
+
},
|
|
217
|
+
"hasResized": {
|
|
218
|
+
"description": "",
|
|
219
|
+
"type": {
|
|
220
|
+
"name": "bool"
|
|
221
|
+
},
|
|
222
|
+
"required": false
|
|
194
223
|
}
|
|
195
224
|
}
|
|
196
225
|
};
|
|
@@ -16,11 +16,13 @@ import { calculateDesktopWidth, calculateMobileHeight, applyResizeCursor, remove
|
|
|
16
16
|
*/
|
|
17
17
|
const useResize = (expandedRef, isSmallScreen, expandedItem, onWidthChange, currentItem) => {
|
|
18
18
|
const [isResizing, setIsResizing] = useState(false);
|
|
19
|
+
const [hasResized, setHasResized] = useState(false);
|
|
19
20
|
const [resizeStartY, setResizeStartY] = useState(0);
|
|
20
21
|
const [resizeStartHeight, setResizeStartHeight] = useState(0);
|
|
21
22
|
const handleResizeStart = useCallback(e => {
|
|
22
23
|
e.preventDefault();
|
|
23
24
|
setIsResizing(true);
|
|
25
|
+
setHasResized(false); // Reset resize flag
|
|
24
26
|
applyResizeCursor(isSmallScreen);
|
|
25
27
|
if (isSmallScreen && expandedRef.current) {
|
|
26
28
|
setResizeStartY(e.clientY);
|
|
@@ -31,6 +33,9 @@ const useResize = (expandedRef, isSmallScreen, expandedItem, onWidthChange, curr
|
|
|
31
33
|
if (!isResizing || !expandedRef.current) {
|
|
32
34
|
return;
|
|
33
35
|
}
|
|
36
|
+
|
|
37
|
+
// Mark that we've actually resized
|
|
38
|
+
setHasResized(true);
|
|
34
39
|
if (isSmallScreen) {
|
|
35
40
|
// Vertical resizing for small screens
|
|
36
41
|
const newHeight = calculateMobileHeight(e.clientY, resizeStartY, resizeStartHeight, currentItem);
|
|
@@ -84,6 +89,7 @@ const useResize = (expandedRef, isSmallScreen, expandedItem, onWidthChange, curr
|
|
|
84
89
|
}, [isSmallScreen, expandedRef]);
|
|
85
90
|
return {
|
|
86
91
|
isResizing,
|
|
92
|
+
hasResized,
|
|
87
93
|
handleResizeStart,
|
|
88
94
|
handleResizeMove,
|
|
89
95
|
handleResizeEnd
|