@ultraviolet/plus 0.10.6 → 0.11.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 (41) 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/index.d.ts +95 -3
  28. package/dist/src/components/EstimateCost/Components/Item.js +1 -2
  29. package/dist/src/components/EstimateCost/EstimateCostContent.js +2 -4
  30. package/dist/src/components/EstimateCost/OverlayComponent.js +2 -4
  31. package/dist/src/components/Navigation/Navigation.js +50 -0
  32. package/dist/src/components/Navigation/NavigationContent.js +230 -0
  33. package/dist/src/components/Navigation/NavigationProvider.js +55 -0
  34. package/dist/src/components/Navigation/components/Group.js +53 -0
  35. package/dist/src/components/Navigation/components/Item.js +437 -0
  36. package/dist/src/components/Navigation/components/PinnedItems.js +30 -0
  37. package/dist/src/components/Navigation/components/Separator.js +12 -0
  38. package/dist/src/components/Navigation/constants.js +37 -0
  39. package/dist/src/components/Navigation/locales/en.js +9 -0
  40. package/dist/src/index.js +1 -0
  41. package/package.json +9 -10
@@ -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 };
@@ -0,0 +1,437 @@
1
+ import _styled from '@emotion/styled/base';
2
+ import '@emotion/react';
3
+ import { MenuV2, Stack, Tooltip, Expandable, Button, Badge, Text, fadeIn } from '@ultraviolet/ui';
4
+ import { useState, useCallback, useEffect, useMemo, Children, isValidElement, cloneElement } from 'react';
5
+ import { useNavigation } from '../NavigationProvider.js';
6
+ import { ANIMATION_DURATION, PIN_BUTTON_OPACITY_TRANSITION, shrinkHeight } from '../constants.js';
7
+ import { jsxs, Fragment, jsx } from '@emotion/react/jsx-runtime';
8
+ import { CategoryIcon } from '../../../../@ultraviolet/icons/dist/components/CategoryIcon/index.js';
9
+ import { Icon } from '../../../../@ultraviolet/icons/dist/components/Icon/index.js';
10
+
11
+ 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)."; }
12
+ const NeutralButtonLink = process.env.NODE_ENV === "production" ? {
13
+ name: "rhgg7c",
14
+ styles: "color:inherit;text-decoration:none;background-color:inherit;border:none;text-align:left"
15
+ } : {
16
+ name: "rhgg7c",
17
+ styles: "color:inherit;text-decoration:none;background-color:inherit;border:none;text-align:left",
18
+ toString: _EMOTION_STRINGIFIED_CSS_ERROR__
19
+ };
20
+ const ExpandedPinnedButton = /*#__PURE__*/_styled(Button, {
21
+ target: "e134hokc11"
22
+ })("opacity:0;right:0;position:absolute;left:-24px;top:0;bottom:0;margin:auto;&:hover,&:focus{opacity:1;}transition:", PIN_BUTTON_OPACITY_TRANSITION, ";transition-delay:0.3s;");
23
+ const CollapsedPinnedButton = /*#__PURE__*/_styled(Button, {
24
+ target: "e134hokc10"
25
+ })("opacity:0;&:hover,&:focus{opacity:1;}transition:", PIN_BUTTON_OPACITY_TRANSITION, ";transition-delay:0.3s;");
26
+ const StyledMenuItem = /*#__PURE__*/_styled(MenuV2.Item, {
27
+ target: "e134hokc9"
28
+ })("text-align:left;&:hover{", ExpandedPinnedButton, ",", CollapsedPinnedButton, "{opacity:1;}}");
29
+ const StyledMenu = /*#__PURE__*/_styled(MenuV2, {
30
+ target: "e134hokc8"
31
+ })(process.env.NODE_ENV === "production" ? {
32
+ name: "educr3",
33
+ styles: "width:180px"
34
+ } : {
35
+ name: "educr3",
36
+ styles: "width:180px",
37
+ toString: _EMOTION_STRINGIFIED_CSS_ERROR__
38
+ });
39
+ const StyledBadge = /*#__PURE__*/_styled(Badge, {
40
+ target: "e134hokc7"
41
+ })("transition:", PIN_BUTTON_OPACITY_TRANSITION, ";transition-delay:0.3s;");
42
+ const PaddingStack = /*#__PURE__*/_styled(Stack, {
43
+ target: "e134hokc6"
44
+ })(process.env.NODE_ENV === "production" ? {
45
+ name: "13feash",
46
+ styles: "padding-left:28px"
47
+ } : {
48
+ name: "13feash",
49
+ styles: "padding-left:28px",
50
+ toString: _EMOTION_STRINGIFIED_CSS_ERROR__
51
+ });
52
+ const AnimatedIcon = /*#__PURE__*/_styled(Icon, {
53
+ target: "e134hokc5"
54
+ })();
55
+ const WrapText = /*#__PURE__*/_styled(Text, {
56
+ shouldForwardProp: prop => !['animation', 'subLabel'].includes(prop),
57
+ target: "e134hokc4"
58
+ })("overflow-wrap:", ({
59
+ animation
60
+ }) => animation ? 'normal' : 'anywhere', ";white-space:", ({
61
+ animation
62
+ }) => animation ? 'nowrap' : 'normal', ";");
63
+ const StyledStack = /*#__PURE__*/_styled(Stack, {
64
+ target: "e134hokc3"
65
+ })(process.env.NODE_ENV === "production" ? {
66
+ name: "13feash",
67
+ styles: "padding-left:28px"
68
+ } : {
69
+ name: "13feash",
70
+ styles: "padding-left:28px",
71
+ toString: _EMOTION_STRINGIFIED_CSS_ERROR__
72
+ });
73
+ const StyledContainer = /*#__PURE__*/_styled(Stack, {
74
+ target: "e134hokc2"
75
+ })(NeutralButtonLink, ";border-radius:", ({
76
+ theme
77
+ }) => theme.radii.default, ";&[data-has-no-expand='false']{cursor:pointer;}margin-top:", ({
78
+ theme
79
+ }) => theme.space['0.25'], ";padding:", ({
80
+ theme
81
+ }) => `calc(${theme.space['0.25']} + ${theme.space['0.5']}) ${theme.space['1']}`, ";&[data-has-sub-label='true']{padding:", ({
82
+ theme
83
+ }) => `${theme.space['0.5']} ${theme.space['1']}`, ";}width:100%;&:hover[data-has-no-expand='false']:not([disabled]):not(\n [data-is-active='true']\n ),&:focus[data-has-no-expand='false']:not([disabled]):not(\n [data-is-active='true']\n ),&[data-has-active-children='true'][data-has-no-expand='false']:not(\n [disabled][data-is-active='true']\n ){background-color:", ({
84
+ theme
85
+ }) => theme.colors.neutral.backgroundHover, ";", ExpandedPinnedButton, ",", CollapsedPinnedButton, "{opacity:1;}&[data-is-pinnable='true']{", StyledBadge, "{opacity:0;}}", WrapText, "{color:", ({
86
+ theme
87
+ }) => theme.colors.neutral.textWeakHover, ";}}&:active[data-has-no-expand='false']:not([disabled]):not(\n [data-is-active='true']\n ){background-color:", ({
88
+ theme
89
+ }) => theme.colors.neutral.backgroundHover, ";}&[data-is-active='true'],&:hover[data-has-active='true']{background-color:", ({
90
+ theme
91
+ }) => theme.colors.primary.background, ";&:hover{background-color:", ({
92
+ theme
93
+ }) => theme.colors.primary.backgroundHover, ";}}&[disabled]{cursor:not-allowed;background-color:unset;", WrapText, "{color:", ({
94
+ theme
95
+ }) => theme.colors.neutral.textWeakDisabled, ";}}&[data-animation='collapse']{animation:", shrinkHeight, " ", ANIMATION_DURATION, "ms ease-in-out;", WrapText, ",", AnimatedIcon, ",", StyledBadge, "{animation:", fadeIn, " ", ANIMATION_DURATION, "ms ease-in-out reverse;}}&[data-animation='expand']{animation:", shrinkHeight, " ", ANIMATION_DURATION, "ms ease-in-out reverse;", WrapText, ",", AnimatedIcon, ",", StyledBadge, "{animation:", fadeIn, " ", ANIMATION_DURATION, "ms ease-in-out;}", StyledStack, "{display:none;}}");
96
+ const MenuStack = /*#__PURE__*/_styled(Stack, {
97
+ target: "e134hokc1"
98
+ })("padding:", ({
99
+ theme
100
+ }) => `0 ${theme.space['2']}`, ";margin-top:", ({
101
+ theme
102
+ }) => theme.space['0.25'], ";");
103
+ const ContainerCategoryIcon = /*#__PURE__*/_styled(Stack, {
104
+ target: "e134hokc0"
105
+ })(process.env.NODE_ENV === "production" ? {
106
+ name: "d47oax",
107
+ styles: "min-width:20px"
108
+ } : {
109
+ name: "d47oax",
110
+ styles: "min-width:20px",
111
+ toString: _EMOTION_STRINGIFIED_CSS_ERROR__
112
+ });
113
+ const Item = ({
114
+ children,
115
+ categoryIcon,
116
+ label,
117
+ subLabel,
118
+ badgeText,
119
+ badgeSentiment,
120
+ href,
121
+ onClick,
122
+ toggle,
123
+ active,
124
+ noPinButton,
125
+ type = 'default',
126
+ hasParents,
127
+ as,
128
+ disabled,
129
+ noExpand = false
130
+ }) => {
131
+ const context = useNavigation();
132
+ if (!context) {
133
+ throw new Error('Navigation.Item can only be used inside a Navigation');
134
+ }
135
+ const {
136
+ expanded,
137
+ locales,
138
+ pinnedFeature,
139
+ pinItem,
140
+ unpinItem,
141
+ pinnedItems,
142
+ pinLimit,
143
+ animation
144
+ } = context;
145
+ const [internalToggle, setToggle] = useState(toggle !== false);
146
+ const triggerToggle = useCallback(value => {
147
+ setToggle(value);
148
+ onClick?.(internalToggle);
149
+ }, [internalToggle, onClick]);
150
+ useEffect(() => {
151
+ if (animation === 'collapse') {
152
+ setToggle(false);
153
+ }
154
+ if (animation === 'expand') {
155
+ setTimeout(() => {
156
+ setToggle(toggle ?? true);
157
+ }, 1);
158
+ }
159
+ }, [animation, toggle]);
160
+ const PaddedStack = noExpand ? Stack : PaddingStack;
161
+ const hasHrefAndNoChildren = href && !children;
162
+ const haspinnedFeatureAndNoChildren = pinnedFeature && !children && !noPinButton;
163
+ const isItemPinned = pinnedItems.includes(label);
164
+ const shouldShowPinnedButton = useMemo(() => {
165
+ if (href || disabled) return false;
166
+ if (pinnedItems.length >= pinLimit && type === 'default') return false;
167
+ if (haspinnedFeatureAndNoChildren && type !== 'default') {
168
+ return true;
169
+ }
170
+ if (haspinnedFeatureAndNoChildren && !isItemPinned) {
171
+ return true;
172
+ }
173
+ return false;
174
+ }, [disabled, haspinnedFeatureAndNoChildren, href, isItemPinned, pinLimit, pinnedItems.length, type]);
175
+ const hasActiveChildren = useMemo(() => {
176
+ if (!children) return false;
177
+ return Children.map(children, child => /*#__PURE__*/isValidElement(child) ? child.props?.active : false).includes(true);
178
+ }, [children]);
179
+ const containerTag = useMemo(() => {
180
+ if (as) {
181
+ return as;
182
+ }
183
+ if (hasHrefAndNoChildren) {
184
+ return 'a';
185
+ }
186
+ if (noExpand) {
187
+ return 'div';
188
+ }
189
+ return 'button';
190
+ }, [as, hasHrefAndNoChildren, noExpand]);
191
+ const Container = StyledContainer.withComponent(containerTag, {
192
+ target: "e134hokc12"
193
+ });
194
+ const ariaExpanded = useMemo(() => {
195
+ if (hasHrefAndNoChildren && internalToggle) {
196
+ return true;
197
+ }
198
+ if (hasHrefAndNoChildren && !internalToggle) {
199
+ return false;
200
+ }
201
+ return undefined;
202
+ }, [hasHrefAndNoChildren, internalToggle]);
203
+
204
+ // This content is when the navigation is expanded
205
+ if (expanded || !expanded && animation === 'expand') {
206
+ const renderChildren = Children.map(children, child => /*#__PURE__*/isValidElement(child) ? /*#__PURE__*/cloneElement(child, {
207
+ hasParents: true
208
+ }) : child);
209
+ return jsxs(Fragment, {
210
+ children: [jsxs(Container, {
211
+ gap: 1,
212
+ direction: "row",
213
+ alignItems: "center",
214
+ justifyContent: "space-between",
215
+ "data-has-sub-label": !!subLabel,
216
+ onClick: () => {
217
+ if (children) {
218
+ return triggerToggle(!internalToggle);
219
+ }
220
+ return onClick?.();
221
+ },
222
+ "aria-expanded": ariaExpanded,
223
+ href: href,
224
+ target: href ? '_blank' : undefined,
225
+ "data-is-pinnable": shouldShowPinnedButton,
226
+ "data-is-active": active,
227
+ "data-animation": animation,
228
+ "data-has-children": !!children,
229
+ "data-has-active-children": hasActiveChildren,
230
+ "data-has-no-expand": noExpand,
231
+ disabled: disabled,
232
+ children: [jsxs(Stack, {
233
+ direction: "row",
234
+ gap: 1,
235
+ alignItems: "center",
236
+ justifyContent: "center",
237
+ children: [categoryIcon ? jsx(ContainerCategoryIcon, {
238
+ alignItems: "center",
239
+ justifyContent: "center",
240
+ children: jsx(CategoryIcon, {
241
+ name: categoryIcon
242
+ })
243
+ }) : null, jsxs(Stack, {
244
+ children: [jsx(WrapText, {
245
+ as: "span",
246
+ variant: "bodySmallStrong",
247
+ sentiment: active ? 'primary' : 'neutral',
248
+ prominence: categoryIcon || !hasParents ? undefined : 'weak',
249
+ animation: animation,
250
+ disabled: disabled,
251
+ children: label
252
+ }), subLabel ? jsx(WrapText, {
253
+ as: "span",
254
+ variant: "caption",
255
+ sentiment: "neutral",
256
+ prominence: "weak",
257
+ animation: animation,
258
+ disabled: disabled,
259
+ subLabel: true,
260
+ children: subLabel
261
+ }) : null]
262
+ })]
263
+ }), jsxs(Stack, {
264
+ direction: "row",
265
+ alignItems: "center",
266
+ gap: href ? 1 : undefined,
267
+ children: [badgeText || haspinnedFeatureAndNoChildren ? jsxs(Fragment, {
268
+ children: [badgeText ? jsx(StyledBadge, {
269
+ sentiment: badgeSentiment,
270
+ size: "small",
271
+ prominence: "strong",
272
+ disabled: disabled,
273
+ children: badgeText
274
+ }) : null, shouldShowPinnedButton ? jsx(Tooltip, {
275
+ text: isItemPinned ? locales['navigation.unpin.tooltip'] : locales['navigation.pin.tooltip'],
276
+ placement: "right",
277
+ children: jsx("div", {
278
+ style: {
279
+ position: 'relative'
280
+ },
281
+ children: jsx(ExpandedPinnedButton, {
282
+ size: "xsmall",
283
+ variant: "ghost",
284
+ sentiment: active ? 'primary' : 'neutral',
285
+ onClick: () => isItemPinned ? unpinItem(label) : pinItem(label),
286
+ icon: "pin"
287
+ })
288
+ })
289
+ }) : null]
290
+ }) : null, hasHrefAndNoChildren ? jsx(AnimatedIcon, {
291
+ name: "open-in-new",
292
+ sentiment: "neutral",
293
+ prominence: "weak",
294
+ disabled: disabled
295
+ }) : null, children ? jsxs(Stack, {
296
+ gap: 1,
297
+ direction: "row",
298
+ alignItems: "center",
299
+ children: [type === 'pinnedGroup' && pinLimit !== Infinity ? jsxs(WrapText, {
300
+ as: "span",
301
+ variant: "caption",
302
+ sentiment: "neutral",
303
+ prominence: "weak",
304
+ children: [pinnedItems.length, "/", pinLimit]
305
+ }) : null, !animation && !noExpand ? jsx(AnimatedIcon, {
306
+ name: internalToggle ? 'arrow-down' : 'arrow-right',
307
+ sentiment: "neutral",
308
+ prominence: "weak"
309
+ }) : null]
310
+ }) : null]
311
+ })]
312
+ }), children ? jsx(Fragment, {
313
+ children: !noExpand ? jsx(Expandable, {
314
+ opened: internalToggle,
315
+ animationDuration: animation ? ANIMATION_DURATION / 2 : undefined,
316
+ children: jsx(PaddedStack, {
317
+ children: renderChildren
318
+ })
319
+ }) : jsx(PaddedStack, {
320
+ children: renderChildren
321
+ })
322
+ }) : null]
323
+ });
324
+ }
325
+
326
+ // This content is the menu of the navigation when collapsed
327
+ if (categoryIcon || Children.count(children) > 0 && !hasParents) {
328
+ return jsx(MenuStack, {
329
+ gap: 1,
330
+ alignItems: "start",
331
+ justifyContent: "start",
332
+ children: Children.count(children) > 0 ? jsx(StyledMenu, {
333
+ disclosure: jsx(Button, {
334
+ sentiment: "neutral",
335
+ variant: hasActiveChildren ? 'filled' : 'ghost',
336
+ size: "small",
337
+ icon: !categoryIcon ? 'dots-horizontal' : undefined,
338
+ children: categoryIcon ? jsx(Stack, {
339
+ direction: "row",
340
+ gap: 1,
341
+ alignItems: "center",
342
+ justifyContent: "center",
343
+ children: jsx(CategoryIcon, {
344
+ name: categoryIcon
345
+ })
346
+ }) : null
347
+ }),
348
+ placement: "right",
349
+ children: Children.map(children, child => /*#__PURE__*/isValidElement(child) ? /*#__PURE__*/cloneElement(child, {
350
+ hasParents: true
351
+ }) : child)
352
+ }) : jsx(Tooltip, {
353
+ text: label,
354
+ placement: "right",
355
+ children: jsx(Button, {
356
+ sentiment: "neutral",
357
+ variant: active ? 'filled' : 'ghost',
358
+ size: "small",
359
+ onClick: () => onClick?.(),
360
+ children: jsx(Stack, {
361
+ direction: "row",
362
+ gap: 1,
363
+ alignItems: "center",
364
+ justifyContent: "center",
365
+ children: jsx(CategoryIcon, {
366
+ name: categoryIcon ?? 'console'
367
+ })
368
+ })
369
+ })
370
+ })
371
+ });
372
+ }
373
+
374
+ // This content is what is inside a menu item the navigation is collapsed
375
+ if (hasParents) {
376
+ return jsx(StyledMenuItem, {
377
+ href: href,
378
+ onClick: () => onClick?.(),
379
+ borderless: true,
380
+ children: jsxs(Stack, {
381
+ gap: 1,
382
+ direction: "row",
383
+ alignItems: "center",
384
+ justifyContent: "space-between",
385
+ children: [jsx(WrapText, {
386
+ as: "span",
387
+ variant: "bodySmall",
388
+ children: label
389
+ }), shouldShowPinnedButton ? jsx(Tooltip, {
390
+ text: isItemPinned ? locales['navigation.unpin.tooltip'] : locales['navigation.pin.tooltip'],
391
+ placement: "right",
392
+ children: jsx(CollapsedPinnedButton, {
393
+ size: "xsmall",
394
+ variant: "ghost",
395
+ sentiment: active ? 'primary' : 'neutral',
396
+ onClick: () => {
397
+ if (isItemPinned) {
398
+ unpinItem(label);
399
+ } else {
400
+ pinItem(label);
401
+ }
402
+ },
403
+ icon: "auto-fix"
404
+ })
405
+ }) : null]
406
+ })
407
+ });
408
+ }
409
+
410
+ // This content is for when navigation is collapsed and we show an icon of link
411
+ if (!hasParents && href) {
412
+ return jsx(Tooltip, {
413
+ text: label,
414
+ placement: "right",
415
+ children: jsx(MenuStack, {
416
+ gap: 1,
417
+ alignItems: "start",
418
+ justifyContent: "start",
419
+ children: jsx(Container, {
420
+ gap: 1,
421
+ alignItems: "center",
422
+ justifyContent: "center",
423
+ href: href,
424
+ target: "_blank",
425
+ children: jsx(AnimatedIcon, {
426
+ name: "open-in-new",
427
+ sentiment: "neutral",
428
+ prominence: "weak"
429
+ })
430
+ })
431
+ })
432
+ });
433
+ }
434
+ return null;
435
+ };
436
+
437
+ export { Item };
@@ -0,0 +1,30 @@
1
+ import { useNavigation } from '../NavigationProvider.js';
2
+ import { Item } from './Item.js';
3
+ import { jsx } from '@emotion/react/jsx-runtime';
4
+
5
+ const PinnedItems = () => {
6
+ const context = useNavigation();
7
+ if (!context) {
8
+ throw new Error('Navigation.PinnedItems can only be used inside a Navigation');
9
+ }
10
+ const {
11
+ locales,
12
+ pinnedItems,
13
+ pinnedFeature
14
+ } = context;
15
+ if (pinnedItems.length > 0 && pinnedFeature) {
16
+ return jsx(Item, {
17
+ label: locales['navigation.pinned.item.group.label'],
18
+ categoryIcon: "pin",
19
+ toggle: false,
20
+ type: "pinnedGroup",
21
+ children: pinnedItems.map(item => jsx(Item, {
22
+ label: item,
23
+ type: "pinned"
24
+ }, item))
25
+ });
26
+ }
27
+ return null;
28
+ };
29
+
30
+ export { PinnedItems };
@@ -0,0 +1,12 @@
1
+ import _styled from '@emotion/styled/base';
2
+ import { Separator as Separator$1 } from '@ultraviolet/ui';
3
+ import { jsx } from '@emotion/react/jsx-runtime';
4
+
5
+ const StyledSeparator = /*#__PURE__*/_styled(Separator$1, {
6
+ target: "e1tbaa9b0"
7
+ })("margin:", ({
8
+ theme
9
+ }) => `${theme.space['2']} -${theme.space['2']}`, ";");
10
+ const Separator = () => jsx(StyledSeparator, {});
11
+
12
+ export { Separator };
@@ -0,0 +1,37 @@
1
+ import { keyframes } from '@emotion/react';
2
+
3
+ const NAVIGATION_MIN_WIDTH = 220; // in px
4
+ const NAVIGATION_WIDTH = 280; // in px
5
+ const NAVIGATION_COLLASPED_WIDTH = 67; // in px
6
+ const NAVIGATION_MAX_WIDTH = 320; // in px
7
+
8
+ /**
9
+ * ANIMATIONS
10
+ */
11
+ const PIN_BUTTON_OPACITY_TRANSITION = 'opacity 250ms ease-in-out'; // this is the transition animation when hovering pin button
12
+ const ANIMATION_DURATION = 700; // collapse and expand animation duration of the whole nav in ms
13
+
14
+ const shrinkHeight = keyframes`
15
+ 0% {
16
+ max-height: 50px; // this is on purpose higher than the actual height of the item
17
+ }
18
+
19
+ 100% {
20
+ max-height: 32px;
21
+ }
22
+ `;
23
+ const groupAnimation = keyframes`
24
+ 0% {
25
+ opacity: 0;
26
+ max-height: 0;
27
+ margin-bottom: -8px;
28
+ }
29
+
30
+ 100% {
31
+ opacity: 1;
32
+ max-height: 40px;
33
+ margin-bottom: 0;
34
+ }
35
+ `;
36
+
37
+ export { ANIMATION_DURATION, NAVIGATION_COLLASPED_WIDTH, NAVIGATION_MAX_WIDTH, NAVIGATION_MIN_WIDTH, NAVIGATION_WIDTH, PIN_BUTTON_OPACITY_TRANSITION, groupAnimation, shrinkHeight };
@@ -0,0 +1,9 @@
1
+ var NavigationLocales = {
2
+ 'navigation.pin.tooltip': 'Pin product',
3
+ 'navigation.unpin.tooltip': 'Unpin product',
4
+ 'navigation.pinned.item.group.label': 'Pinned items',
5
+ 'navigation.expand.button': 'Expand sidebar',
6
+ 'navigation.collapse.button': 'Collapse sidebar'
7
+ };
8
+
9
+ export { NavigationLocales as default };
package/dist/src/index.js CHANGED
@@ -5,5 +5,6 @@ export { EstimateCost } from './components/EstimateCost/EstimateCost.js';
5
5
  export { default as estimateCostDefaultLocales } from './components/EstimateCost/locales/en.js';
6
6
  export { CustomerSatisfaction } from './components/CustomerSatisfaction/index.js';
7
7
  export { Conversation } from './components/Conversation/index.js';
8
+ export { Navigation } from './components/Navigation/Navigation.js';
8
9
  export { FAQ } from './components/FAQ/index.js';
9
10
  export { SteppedListContainer } from './components/SteppedListCard/SteppedListContainer.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultraviolet/plus",
3
- "version": "0.10.6",
3
+ "version": "0.11.0",
4
4
  "description": "Ultraviolet Plus",
5
5
  "homepage": "https://github.com/scaleway/ultraviolet#readme",
6
6
  "repository": {
@@ -39,25 +39,24 @@
39
39
  "react-dom": "18.2.0"
40
40
  },
41
41
  "devDependencies": {
42
- "@babel/core": "7.24.1",
42
+ "@babel/core": "7.24.3",
43
43
  "@emotion/babel-plugin": "11.11.0",
44
44
  "@emotion/react": "11.11.4",
45
45
  "@emotion/styled": "11.11.0",
46
- "@types/react": "18.2.61",
47
- "@types/react-dom": "18.2.19",
46
+ "@types/react": "18.2.64",
47
+ "@types/react-dom": "18.2.21",
48
48
  "react": "18.2.0",
49
49
  "react-dom": "18.2.0",
50
- "@ultraviolet/icons": "2.11.0",
50
+ "@ultraviolet/icons": "2.11.1",
51
51
  "@ultraviolet/illustrations": "1.6.4"
52
52
  },
53
53
  "dependencies": {
54
- "@uiw/codemirror-extensions-langs": "4.21.24",
55
- "@uiw/codemirror-theme-material": "4.21.24",
56
- "@uiw/react-codemirror": "4.21.24",
57
- "react-flatten-children": "1.1.2",
54
+ "@uiw/codemirror-extensions-langs": "4.21.25",
55
+ "@uiw/codemirror-theme-material": "4.21.25",
56
+ "@uiw/react-codemirror": "4.21.25",
58
57
  "react-intersection-observer": "9.8.1",
59
58
  "@ultraviolet/themes": "1.9.0",
60
- "@ultraviolet/ui": "1.44.0"
59
+ "@ultraviolet/ui": "1.45.0"
61
60
  },
62
61
  "scripts": {
63
62
  "build": "rollup -c ../../rollup.config.mjs",