@ultraviolet/plus 0.10.6 → 0.11.1

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 (45) hide show
  1. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/Icons.js +53 -0
  2. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/ai.svg.js +20 -0
  3. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/baremetal.svg.js +28 -0
  4. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/billing.svg.js +26 -0
  5. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/compute.svg.js +26 -0
  6. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/console.svg.js +26 -0
  7. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/containers.svg.js +24 -0
  8. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/database.svg.js +22 -0
  9. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/datacenter.svg.js +26 -0
  10. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/dedicated-server.svg.js +24 -0
  11. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/dev-tools.svg.js +32 -0
  12. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/documentation.svg.js +26 -0
  13. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/iot.svg.js +30 -0
  14. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/labs.svg.js +28 -0
  15. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/managed-services.svg.js +22 -0
  16. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/network.svg.js +31 -0
  17. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/observability.svg.js +22 -0
  18. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/pin.svg.js +29 -0
  19. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/security.svg.js +26 -0
  20. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/serverless.svg.js +22 -0
  21. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/storage.svg.js +22 -0
  22. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/tools-services.svg.js +24 -0
  23. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/use-case.svg.js +26 -0
  24. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/vpc.svg.js +60 -0
  25. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/assets/web-hosting.svg.js +24 -0
  26. package/dist/@ultraviolet/icons/dist/components/CategoryIcon/index.js +27 -0
  27. package/dist/@ultraviolet/icons/dist/components/ProductIcon/Icons.js +5 -1
  28. package/dist/@ultraviolet/icons/dist/components/ProductIcon/assets/cost-manager.svg.js +73 -0
  29. package/dist/@ultraviolet/icons/dist/components/ProductIcon/assets/managed-search-database.svg.js +59 -0
  30. package/dist/index.d.ts +98 -4
  31. package/dist/src/components/EstimateCost/Components/Item.js +1 -2
  32. package/dist/src/components/EstimateCost/EstimateCost.js +2 -0
  33. package/dist/src/components/EstimateCost/EstimateCostContent.js +5 -5
  34. package/dist/src/components/EstimateCost/OverlayComponent.js +10 -7
  35. package/dist/src/components/Navigation/Navigation.js +50 -0
  36. package/dist/src/components/Navigation/NavigationContent.js +230 -0
  37. package/dist/src/components/Navigation/NavigationProvider.js +55 -0
  38. package/dist/src/components/Navigation/components/Group.js +53 -0
  39. package/dist/src/components/Navigation/components/Item.js +445 -0
  40. package/dist/src/components/Navigation/components/PinnedItems.js +30 -0
  41. package/dist/src/components/Navigation/components/Separator.js +12 -0
  42. package/dist/src/components/Navigation/constants.js +37 -0
  43. package/dist/src/components/Navigation/locales/en.js +9 -0
  44. package/dist/src/index.js +1 -0
  45. package/package.json +12 -13
@@ -0,0 +1,230 @@
1
+ import _styled from '@emotion/styled/base';
2
+ import { Tooltip, Button, Stack } from '@ultraviolet/ui';
3
+ import { useRef, useCallback, useState, useEffect } from 'react';
4
+ import { useNavigation } from './NavigationProvider.js';
5
+ import { ANIMATION_DURATION, NAVIGATION_MAX_WIDTH, NAVIGATION_MIN_WIDTH, NAVIGATION_COLLASPED_WIDTH } from './constants.js';
6
+ import { jsxs, jsx } from '@emotion/react/jsx-runtime';
7
+
8
+ function _EMOTION_STRINGIFIED_CSS_ERROR__() { return "You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."; }
9
+ const StyledNav = /*#__PURE__*/_styled("nav", {
10
+ target: "esezfu57"
11
+ })("display:flex;flex-direction:row;position:relative;border-right:1px solid ", ({
12
+ theme
13
+ }) => theme.colors.neutral.borderWeak, ";");
14
+ const Container = /*#__PURE__*/_styled('div', {
15
+ shouldForwardProp: prop => !['width'].includes(prop),
16
+ target: "esezfu56"
17
+ })("background:", ({
18
+ theme
19
+ }) => theme.colors.neutral.background, ";display:flex;flex-direction:column;width:", ({
20
+ width
21
+ }) => width, "px;&[data-expanded='true'][data-animation='false']{max-width:", NAVIGATION_MAX_WIDTH, "px;min-width:", NAVIGATION_MIN_WIDTH, "px;}&[data-expanded='false']{width:", NAVIGATION_COLLASPED_WIDTH, "px;}&[data-animation='expand']{transition:width ", ANIMATION_DURATION, "ms ease-in-out;width:", ({
22
+ width
23
+ }) => width, "px;}&[data-animation='collapse']{transition:width ", ANIMATION_DURATION, "ms ease-in-out;width:", NAVIGATION_COLLASPED_WIDTH, "px;}");
24
+ const StickyFooter = /*#__PURE__*/_styled("div", {
25
+ target: "esezfu55"
26
+ })("display:flex;width:100%;background:", ({
27
+ theme
28
+ }) => theme.colors.neutral.background, ";border-top:1px solid ", ({
29
+ theme
30
+ }) => theme.colors.neutral.borderWeak, ";padding:", ({
31
+ theme
32
+ }) => `${theme.space['1']} ${theme.space['2']}`, ";transition:justify-content ", ANIMATION_DURATION, "ms ease-in-out;box-shadow:", ({
33
+ theme
34
+ }) => theme.shadows.defaultShadow, ";transition:box-shadow 230ms ease-in-out;justify-content:flex-end;&[data-has-overflow-style='false']{box-shadow:none;border:none;}");
35
+ const Header = /*#__PURE__*/_styled("div", {
36
+ target: "esezfu54"
37
+ })("background:", ({
38
+ theme
39
+ }) => theme.colors.neutral.background, ";");
40
+ const LogoContainer = /*#__PURE__*/_styled(Stack, {
41
+ target: "esezfu53"
42
+ })("margin:", ({
43
+ theme
44
+ }) => `${theme.space['3']} ${theme.space['3']} ${theme.space['2']} ${theme.space['3']}`, ";max-width:220px;height:22px;");
45
+ const ContentContainer = /*#__PURE__*/_styled("div", {
46
+ target: "esezfu52"
47
+ })(process.env.NODE_ENV === "production" ? {
48
+ name: "12is9id",
49
+ styles: "overflow:hidden;display:flex;flex-direction:column;flex-grow:1"
50
+ } : {
51
+ name: "12is9id",
52
+ styles: "overflow:hidden;display:flex;flex-direction:column;flex-grow:1",
53
+ toString: _EMOTION_STRINGIFIED_CSS_ERROR__
54
+ });
55
+ const Content = /*#__PURE__*/_styled(Stack, {
56
+ target: "esezfu51"
57
+ })("overflow-y:auto;overflow-x:hidden;flex-grow:1;&[data-is-expanded='false']{padding:", ({
58
+ theme
59
+ }) => theme.space['2'], " 0;}&[data-is-expanded='true'],&[data-animation='expand']{padding:", ({
60
+ theme
61
+ }) => theme.space['2'], ";}");
62
+ const Slider = /*#__PURE__*/_styled("div", {
63
+ target: "esezfu50"
64
+ })("background:transparent;position:absolute;top:0;bottom:0;right:0;width:8px;cursor:col-resize;border-right:2px solid transparent;display:flex;&:hover{border-color:", ({
65
+ theme
66
+ }) => theme.colors.primary.border, ";}");
67
+ const NavigationContent = ({
68
+ children,
69
+ logo,
70
+ onClickExpand,
71
+ width,
72
+ onWidthResize,
73
+ className
74
+ }) => {
75
+ const sliderRef = useRef(null);
76
+ const navigationRef = useRef(null);
77
+ const contentRef = useRef(null);
78
+ const isScrollAtBottom = useCallback(() => {
79
+ if (contentRef.current) {
80
+ if (contentRef.current.scrollTop + contentRef.current.offsetHeight >= contentRef.current.scrollHeight) {
81
+ return false;
82
+ }
83
+ }
84
+ return true;
85
+ }, []);
86
+ const [footerHasOverflowStyle, setFooterHasOverflowStyle] = useState(isScrollAtBottom());
87
+
88
+ // This is for detecting if there is scroll on the content and set the shadow on the footer
89
+ useEffect(() => {
90
+ const scroll = () => {
91
+ const hasOverflow = isScrollAtBottom();
92
+ if (footerHasOverflowStyle !== hasOverflow) {
93
+ setFooterHasOverflowStyle(hasOverflow);
94
+ }
95
+ };
96
+ if (contentRef.current) {
97
+ contentRef.current.addEventListener('scroll', scroll);
98
+ }
99
+ return () => {
100
+ // eslint-disable-next-line react-hooks/exhaustive-deps
101
+ contentRef.current?.removeEventListener('scroll', scroll);
102
+ };
103
+ }, [footerHasOverflowStyle, isScrollAtBottom]);
104
+
105
+ // This will set the shadow on the footer when the component is mounted
106
+ useEffect(() => {
107
+ setFooterHasOverflowStyle(isScrollAtBottom());
108
+ },
109
+ // eslint-disable-next-line react-hooks/exhaustive-deps
110
+ [contentRef.current]);
111
+ const {
112
+ expanded,
113
+ setExpanded,
114
+ animation,
115
+ setAnimation,
116
+ locales
117
+ } = useNavigation();
118
+
119
+ // This function will be triggered when expand/collapse button is clicked
120
+ const toggleExpand = useCallback(() => {
121
+ onClickExpand?.(!expanded);
122
+ if (navigationRef.current) {
123
+ navigationRef.current.style.width = '';
124
+ }
125
+ setAnimation(expanded ? 'collapse' : 'expand');
126
+ setTimeout(() => {
127
+ setExpanded();
128
+ setFooterHasOverflowStyle(isScrollAtBottom());
129
+ setAnimation(false);
130
+ }, ANIMATION_DURATION);
131
+ }, [expanded, isScrollAtBottom, onClickExpand, setAnimation, setExpanded]);
132
+
133
+ // It will handle the resize of the navigation when the user drag the vertical bar
134
+ useEffect(() => {
135
+ let prevX;
136
+ let navRect;
137
+ let shouldCollapseOnMouseUp = false;
138
+ let shouldExpandOnMouseUp = false;
139
+ const mouseMove = event => {
140
+ if (prevX !== undefined) {
141
+ const navWidth = navRect?.width ?? 0;
142
+ const newWidth = navWidth + (event.clientX - prevX);
143
+ if (navigationRef.current && expanded) {
144
+ navigationRef.current.style.width = `${newWidth}px`;
145
+ }
146
+ if (newWidth <= NAVIGATION_MIN_WIDTH) {
147
+ shouldCollapseOnMouseUp = true;
148
+ } else {
149
+ shouldCollapseOnMouseUp = false;
150
+ }
151
+ if (newWidth >= NAVIGATION_COLLASPED_WIDTH && !expanded) {
152
+ shouldExpandOnMouseUp = true;
153
+ } else {
154
+ shouldExpandOnMouseUp = false;
155
+ }
156
+ }
157
+ };
158
+ const mousedown = event => {
159
+ document.body.style.pointerEvents = 'none';
160
+ document.body.style.userSelect = 'none';
161
+ prevX = event.clientX;
162
+ navRect = navigationRef.current?.getBoundingClientRect();
163
+ const mouseup = () => {
164
+ if (shouldCollapseOnMouseUp || shouldExpandOnMouseUp) {
165
+ toggleExpand();
166
+ }
167
+ if (navigationRef.current) {
168
+ if (!shouldCollapseOnMouseUp && !shouldExpandOnMouseUp) {
169
+ onWidthResize?.(navigationRef.current.offsetWidth);
170
+ }
171
+ if (!expanded) {
172
+ navigationRef.current.style.width = '';
173
+ }
174
+ }
175
+ document.removeEventListener('mousemove', mouseMove);
176
+ window.removeEventListener('mouseup', mouseup);
177
+ document.body.style.pointerEvents = '';
178
+ document.body.style.userSelect = '';
179
+ };
180
+ document.addEventListener('mousemove', mouseMove);
181
+ window.addEventListener('mouseup', mouseup);
182
+ };
183
+ sliderRef.current?.addEventListener('mousedown', mousedown);
184
+ return () => {
185
+ // eslint-disable-next-line react-hooks/exhaustive-deps
186
+ sliderRef.current?.removeEventListener('mousedown', mousedown);
187
+ };
188
+ }, [expanded, onWidthResize, toggleExpand]);
189
+ return jsxs(StyledNav, {
190
+ className: className,
191
+ children: [jsxs(Container, {
192
+ ref: navigationRef,
193
+ "data-animation": animation,
194
+ "data-expanded": expanded,
195
+ width: width,
196
+ children: [jsx(Header, {
197
+ children: jsx(LogoContainer, {
198
+ justifyContent: !expanded ? 'center' : undefined,
199
+ alignItems: "start",
200
+ children: typeof logo === 'function' ? logo(animation ? false : expanded) : logo
201
+ })
202
+ }), jsxs(ContentContainer, {
203
+ children: [jsx(Content, {
204
+ ref: contentRef,
205
+ gap: 0.25,
206
+ "data-is-expanded": expanded,
207
+ "data-animation": animation,
208
+ children: children
209
+ }), jsx(StickyFooter, {
210
+ "data-has-overflow-style": footerHasOverflowStyle,
211
+ children: jsx(Tooltip, {
212
+ text: expanded ? locales['navigation.collapse.button'] : locales['navigation.expand.button'],
213
+ placement: "right",
214
+ children: jsx(Button, {
215
+ variant: "ghost",
216
+ sentiment: "neutral",
217
+ size: "small",
218
+ icon: expanded ? 'arrow-left-double' : 'arrow-right-double',
219
+ onClick: toggleExpand
220
+ })
221
+ })
222
+ })]
223
+ })]
224
+ }), jsx(Slider, {
225
+ ref: sliderRef
226
+ })]
227
+ });
228
+ };
229
+
230
+ export { NavigationContent };
@@ -0,0 +1,55 @@
1
+ import { useReducer, useState, useCallback, useMemo, createContext, useContext } from 'react';
2
+ import NavigationLocales from './locales/en.js';
3
+ import { jsx } from '@emotion/react/jsx-runtime';
4
+
5
+ const NavigationContext = /*#__PURE__*/createContext({
6
+ expanded: true,
7
+ setExpanded: () => {},
8
+ animation: false,
9
+ setAnimation: () => {},
10
+ locales: NavigationLocales,
11
+ pinItem: () => {},
12
+ unpinItem: () => {},
13
+ pinnedItems: [],
14
+ pinLimit: 7
15
+ });
16
+ const useNavigation = () => useContext(NavigationContext);
17
+ const NavigationProvider = ({
18
+ children,
19
+ pinnedFeature,
20
+ onClickPinUnpin,
21
+ initialPinned,
22
+ initialExpanded,
23
+ locales,
24
+ pinLimit
25
+ }) => {
26
+ const [expanded, setExpanded] = useReducer(state => !state, initialExpanded);
27
+ const [pinnedItems, setPinnedItems] = useState(initialPinned ?? []);
28
+ const [animation, setAnimation] = useState(false);
29
+ const pinItem = useCallback(item => {
30
+ setPinnedItems([...pinnedItems, item]);
31
+ onClickPinUnpin?.(pinnedItems);
32
+ }, [onClickPinUnpin, pinnedItems]);
33
+ const unpinItem = useCallback(item => {
34
+ setPinnedItems(pinnedItems.filter(localItem => localItem !== item));
35
+ onClickPinUnpin?.(pinnedItems);
36
+ }, [onClickPinUnpin, pinnedItems]);
37
+ const value = useMemo(() => ({
38
+ expanded,
39
+ setExpanded,
40
+ pinnedItems,
41
+ pinItem,
42
+ unpinItem,
43
+ pinnedFeature,
44
+ locales,
45
+ pinLimit,
46
+ animation,
47
+ setAnimation
48
+ }), [expanded, pinnedItems, pinItem, unpinItem, pinnedFeature, locales, pinLimit, animation]);
49
+ return jsx(NavigationContext.Provider, {
50
+ value: value,
51
+ children: children
52
+ });
53
+ };
54
+
55
+ export { NavigationContext, NavigationProvider, useNavigation };
@@ -0,0 +1,53 @@
1
+ import _styled from '@emotion/styled/base';
2
+ import { Text, Stack } from '@ultraviolet/ui';
3
+ import { Children } from 'react';
4
+ import { useNavigation } from '../NavigationProvider.js';
5
+ import { ANIMATION_DURATION, groupAnimation } from '../constants.js';
6
+ import { jsx, jsxs } from '@emotion/react/jsx-runtime';
7
+
8
+ const StyledText = /*#__PURE__*/_styled(Text, {
9
+ target: "eh4zgrv2"
10
+ })("padding-bottom:", ({
11
+ theme
12
+ }) => theme.space['1'], ";transition:opacity ", ANIMATION_DURATION, "ms ease-in-out,height ", ANIMATION_DURATION, "ms ease-in-out;height:", ({
13
+ theme
14
+ }) => `calc(${theme.typography.bodySmallStrong.lineHeight} + ${theme.space['1']})`, ";");
15
+ const StyledStack = /*#__PURE__*/_styled(Stack, {
16
+ target: "eh4zgrv1"
17
+ })("padding-top:", ({
18
+ theme
19
+ }) => theme.space['1'], ";");
20
+ const Container = /*#__PURE__*/_styled("div", {
21
+ target: "eh4zgrv0"
22
+ })("&[data-animation='expand']{", StyledText, "{animation:", groupAnimation, " ", ANIMATION_DURATION, "ms ease-in-out;}}&[data-animation='collapse']{", StyledText, "{animation:", groupAnimation, " ", ANIMATION_DURATION, "ms ease-in-out reverse;}}");
23
+ const Group = ({
24
+ children,
25
+ label
26
+ }) => {
27
+ const context = useNavigation();
28
+ if (!context) {
29
+ throw new Error('Navigation.Group can only be used inside a Navigation');
30
+ }
31
+ const {
32
+ expanded,
33
+ animation
34
+ } = context;
35
+ if (Children.count(children) > 0) {
36
+ return jsx(Container, {
37
+ "data-animation": animation,
38
+ children: jsxs(StyledStack, {
39
+ direction: "column",
40
+ children: [expanded || animation === 'expand' ? jsx(StyledText, {
41
+ as: "span",
42
+ variant: "bodySmallStrong",
43
+ sentiment: "neutral",
44
+ prominence: "weak",
45
+ children: label
46
+ }) : null, children]
47
+ })
48
+ });
49
+ }
50
+ return null;
51
+ };
52
+
53
+ export { Group };