@telefonica/mistica 17.3.0 → 17.4.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.
- package/css/blau.css +24 -16
- package/css/esimflag.css +35 -18
- package/css/mistica.css +1 -1
- package/css/movistar.css +29 -18
- package/css/o2.css +26 -18
- package/css/telefonica.css +38 -18
- package/css/vivo-evolution.css +66 -20
- package/css/vivo.css +26 -18
- package/dist/accordion.css-mistica.js +10 -10
- package/dist/align.css-mistica.js +1 -1
- package/dist/autocomplete.css-mistica.js +4 -4
- package/dist/avatar.css-mistica.js +1 -1
- package/dist/badge.css-mistica.js +1 -1
- package/dist/box.css-mistica.js +13 -13
- package/dist/boxed.css-mistica.js +24 -24
- package/dist/boxed.d.ts +9 -0
- package/dist/boxed.js +18 -15
- package/dist/button-group.css-mistica.js +1 -1
- package/dist/button-layout.css-mistica.js +19 -19
- package/dist/button.css-mistica.js +50 -50
- package/dist/callout.css-mistica.js +13 -13
- package/dist/card-internal.css-mistica.js +22 -22
- package/dist/carousel.css-mistica.js +30 -30
- package/dist/checkbox.css-mistica.js +15 -15
- package/dist/chip.css-mistica.js +18 -18
- package/dist/circle.css-mistica.js +2 -2
- package/dist/community/advanced-data-card.css-mistica.js +19 -19
- package/dist/community/ai-card.css-mistica.js +12 -12
- package/dist/community/blocks.css-mistica.js +1 -1
- package/dist/community/cyber/example-component.css-mistica.js +1 -1
- package/dist/community/example-component.css-mistica.js +2 -2
- package/dist/community/skins/cyber-skin.js +19 -17
- package/dist/counter.css-mistica.js +6 -6
- package/dist/cover-hero.css-mistica.js +7 -7
- package/dist/credit-card-number-field.css-mistica.js +3 -3
- package/dist/date-field.css-mistica.js +1 -1
- package/dist/date-time-picker.css-mistica.js +1 -1
- package/dist/dialog.css-mistica.js +10 -10
- package/dist/divider.css-mistica.js +5 -5
- package/dist/double-field.css-mistica.js +2 -2
- package/dist/drawer.css-mistica.js +4 -4
- package/dist/empty-state-card.css-mistica.js +1 -1
- package/dist/empty-state.css-mistica.js +8 -8
- package/dist/fade-in.css-mistica.js +1 -1
- package/dist/feedback.css-mistica.js +5 -5
- package/dist/file-upload.css-mistica.js +10 -10
- package/dist/fixed-footer-layout.css-mistica.js +6 -6
- package/dist/form.css-mistica.js +1 -1
- package/dist/generated/mistica-icons/icon-panel-collapse-regular.js +165 -0
- package/dist/generated/mistica-icons/icon-panel-expand-regular.js +159 -0
- package/dist/grid-layout.css-mistica.js +3 -3
- package/dist/grid.css-mistica.js +120 -120
- package/dist/header.css-mistica.js +1 -1
- package/dist/hero.css-mistica.js +4 -4
- package/dist/horizontal-scroll.css-mistica.js +1 -1
- package/dist/icon-button.css-mistica.js +53 -53
- package/dist/icons/icon-chevron.css-mistica.js +2 -2
- package/dist/icons/icon-error.css-mistica.js +1 -1
- package/dist/image.css-mistica.js +8 -8
- package/dist/index.d.ts +5 -0
- package/dist/index.js +10 -1
- package/dist/inline.css-mistica.js +11 -11
- package/dist/list.css-mistica.js +40 -28
- package/dist/list.css.d.ts +2 -0
- package/dist/list.d.ts +3 -1
- package/dist/list.js +176 -165
- package/dist/loading-bar.css-mistica.js +1 -1
- package/dist/loading-screen.css-mistica.js +12 -12
- package/dist/logo.css-mistica.js +5 -5
- package/dist/menu.css-mistica.js +13 -13
- package/dist/mobile-navigation-menu.d.ts +26 -0
- package/dist/mobile-navigation-menu.js +145 -0
- package/dist/mosaic.css-mistica.js +1 -1
- package/dist/navigation-bar.css-mistica.js +31 -97
- package/dist/navigation-bar.css.d.ts +0 -24
- package/dist/navigation-bar.d.ts +3 -38
- package/dist/navigation-bar.js +399 -586
- package/dist/navigation-breadcrumbs.css-mistica.js +1 -1
- package/dist/navigation-shared.css-mistica.js +79 -0
- package/dist/navigation-shared.css.d.ts +26 -0
- package/dist/navigation-shared.d.ts +66 -0
- package/dist/navigation-shared.js +264 -0
- package/dist/package-version.js +1 -1
- package/dist/pagination.css-mistica.js +22 -22
- package/dist/pin-field.css-mistica.js +4 -4
- package/dist/popover.css-mistica.js +1 -1
- package/dist/portal.d.ts +1 -1
- package/dist/progress-bar.css-mistica.js +7 -7
- package/dist/radio-button.css-mistica.js +27 -27
- package/dist/rating.css-mistica.js +4 -4
- package/dist/responsive-layout.css-mistica.js +6 -6
- package/dist/screen-reader-only.css-mistica.js +1 -1
- package/dist/select.css-mistica.js +21 -21
- package/dist/sheet-action-row.css-mistica.js +1 -1
- package/dist/sheet-common.css-mistica.js +7 -7
- package/dist/sheet-info.css-mistica.js +1 -1
- package/dist/sidenav-bar-context.d.ts +25 -0
- package/dist/sidenav-bar-context.js +72 -0
- package/dist/sidenav-bar-data.d.ts +15 -0
- package/dist/sidenav-bar-data.js +38 -0
- package/dist/sidenav-bar-first-level-item.d.ts +42 -0
- package/dist/sidenav-bar-first-level-item.js +174 -0
- package/dist/sidenav-bar-keyboard.d.ts +13 -0
- package/dist/sidenav-bar-keyboard.js +314 -0
- package/dist/sidenav-bar-layout.css-mistica.js +28 -0
- package/dist/sidenav-bar-layout.css.d.ts +5 -0
- package/dist/sidenav-bar-layout.d.ts +22 -0
- package/dist/sidenav-bar-layout.js +103 -0
- package/dist/sidenav-bar-mobile.d.ts +24 -0
- package/dist/sidenav-bar-mobile.js +332 -0
- package/dist/sidenav-bar-motion.d.ts +32 -0
- package/dist/sidenav-bar-motion.js +84 -0
- package/dist/sidenav-bar-panel.d.ts +31 -0
- package/dist/sidenav-bar-panel.js +208 -0
- package/dist/sidenav-bar-row.d.ts +82 -0
- package/dist/sidenav-bar-row.js +230 -0
- package/dist/sidenav-bar-second-level-item.d.ts +43 -0
- package/dist/sidenav-bar-second-level-item.js +89 -0
- package/dist/sidenav-bar-section.d.ts +23 -0
- package/dist/sidenav-bar-section.js +167 -0
- package/dist/sidenav-bar-types.d.ts +192 -0
- package/dist/sidenav-bar-types.js +11 -0
- package/dist/sidenav-bar.css-mistica.js +325 -0
- package/dist/sidenav-bar.css.d.ts +93 -0
- package/dist/sidenav-bar.d.ts +102 -0
- package/dist/sidenav-bar.js +492 -0
- package/dist/skeletons.css-mistica.js +8 -8
- package/dist/skins/blau.js +12 -8
- package/dist/skins/esimflag.js +13 -9
- package/dist/skins/movistar.js +13 -9
- package/dist/skins/o2.js +13 -9
- package/dist/skins/skin-contract.css-mistica.js +735 -731
- package/dist/skins/skin-contract.css.d.ts +4 -0
- package/dist/skins/telefonica.js +13 -9
- package/dist/skins/types/colors.d.ts +2 -0
- package/dist/skins/vivo-evolution.js +14 -10
- package/dist/skins/vivo.js +13 -9
- package/dist/skip-link.css-mistica.js +2 -2
- package/dist/slider.css-mistica.js +24 -24
- package/dist/snackbar.css-mistica.js +14 -14
- package/dist/spinner.css-mistica.js +1 -1
- package/dist/square.css-mistica.js +1 -1
- package/dist/stack.css-mistica.js +5 -5
- package/dist/stacking-group.css-mistica.js +1 -1
- package/dist/stepper.css-mistica.js +9 -9
- package/dist/switch-component.css-mistica.js +48 -42
- package/dist/switch-component.css.d.ts +2 -0
- package/dist/switch-component.js +18 -18
- package/dist/table.css-mistica.js +9 -9
- package/dist/tabs.css-mistica.js +22 -22
- package/dist/tag.css-mistica.js +3 -3
- package/dist/text-field-base.css-mistica.js +19 -19
- package/dist/text-field-components.css-mistica.js +10 -10
- package/dist/text-link.css-mistica.js +6 -6
- package/dist/text-tokens.d.ts +6 -0
- package/dist/text-tokens.js +157 -133
- package/dist/text.css-mistica.js +6 -6
- package/dist/timeline.css-mistica.js +11 -11
- package/dist/timer.css-mistica.js +6 -6
- package/dist/tooltip.css-mistica.js +2 -2
- package/dist/touchable.css-mistica.js +4 -4
- package/dist/utils/aspect-ratio-support.css-mistica.js +2 -2
- package/dist/video.css-mistica.js +1 -1
- package/dist/vivinho-loading-animation/vivinho-loading-animation.css-mistica.js +1 -1
- package/dist-es/accordion.css-mistica.js +7 -7
- package/dist-es/align.css-mistica.js +1 -1
- package/dist-es/autocomplete.css-mistica.js +2 -2
- package/dist-es/avatar.css-mistica.js +1 -1
- package/dist-es/badge.css-mistica.js +1 -1
- package/dist-es/box.css-mistica.js +13 -13
- package/dist-es/boxed.css-mistica.js +23 -23
- package/dist-es/boxed.js +25 -25
- package/dist-es/button-group.css-mistica.js +1 -1
- package/dist-es/button-layout.css-mistica.js +16 -16
- package/dist-es/button.css-mistica.js +38 -38
- package/dist-es/callout.css-mistica.js +12 -12
- package/dist-es/card-internal.css-mistica.js +17 -17
- package/dist-es/carousel.css-mistica.js +10 -10
- package/dist-es/checkbox.css-mistica.js +13 -13
- package/dist-es/chip.css-mistica.js +17 -17
- package/dist-es/circle.css-mistica.js +2 -2
- package/dist-es/community/advanced-data-card.css-mistica.js +7 -7
- package/dist-es/community/ai-card.css-mistica.js +4 -4
- package/dist-es/community/blocks.css-mistica.js +1 -1
- package/dist-es/community/cyber/example-component.css-mistica.js +1 -1
- package/dist-es/community/example-component.css-mistica.js +2 -2
- package/dist-es/community/skins/cyber-skin.js +19 -17
- package/dist-es/counter.css-mistica.js +2 -2
- package/dist-es/cover-hero.css-mistica.js +4 -4
- package/dist-es/credit-card-number-field.css-mistica.js +3 -3
- package/dist-es/date-field.css-mistica.js +1 -1
- package/dist-es/date-time-picker.css-mistica.js +1 -1
- package/dist-es/dialog.css-mistica.js +5 -5
- package/dist-es/divider.css-mistica.js +5 -5
- package/dist-es/double-field.css-mistica.js +2 -2
- package/dist-es/drawer.css-mistica.js +2 -2
- package/dist-es/empty-state-card.css-mistica.js +1 -1
- package/dist-es/empty-state.css-mistica.js +7 -7
- package/dist-es/fade-in.css-mistica.js +1 -1
- package/dist-es/feedback.css-mistica.js +2 -2
- package/dist-es/file-upload.css-mistica.js +8 -8
- package/dist-es/fixed-footer-layout.css-mistica.js +3 -3
- package/dist-es/form.css-mistica.js +1 -1
- package/dist-es/generated/mistica-icons/icon-panel-collapse-regular.js +115 -0
- package/dist-es/generated/mistica-icons/icon-panel-expand-regular.js +109 -0
- package/dist-es/grid-layout.css-mistica.js +3 -3
- package/dist-es/grid.css-mistica.js +120 -120
- package/dist-es/header.css-mistica.js +1 -1
- package/dist-es/hero.css-mistica.js +3 -3
- package/dist-es/horizontal-scroll.css-mistica.js +1 -1
- package/dist-es/icon-button.css-mistica.js +53 -53
- package/dist-es/icons/icon-chevron.css-mistica.js +2 -2
- package/dist-es/icons/icon-error.css-mistica.js +1 -1
- package/dist-es/image.css-mistica.js +4 -4
- package/dist-es/index.js +2279 -2276
- package/dist-es/inline.css-mistica.js +11 -11
- package/dist-es/list.css-mistica.js +8 -2
- package/dist-es/list.js +275 -264
- package/dist-es/loading-bar.css-mistica.js +1 -1
- package/dist-es/loading-screen.css-mistica.js +5 -5
- package/dist-es/logo.css-mistica.js +5 -5
- package/dist-es/menu.css-mistica.js +13 -13
- package/dist-es/mobile-navigation-menu.js +90 -0
- package/dist-es/mosaic.css-mistica.js +1 -1
- package/dist-es/navigation-bar.css-mistica.js +11 -20
- package/dist-es/navigation-bar.js +469 -656
- package/dist-es/navigation-breadcrumbs.css-mistica.js +1 -1
- package/dist-es/navigation-shared.css-mistica.js +11 -0
- package/dist-es/navigation-shared.js +192 -0
- package/dist-es/package-version.js +1 -1
- package/dist-es/pagination.css-mistica.js +19 -19
- package/dist-es/pin-field.css-mistica.js +2 -2
- package/dist-es/popover.css-mistica.js +1 -1
- package/dist-es/progress-bar.css-mistica.js +7 -7
- package/dist-es/radio-button.css-mistica.js +22 -22
- package/dist-es/rating.css-mistica.js +3 -3
- package/dist-es/responsive-layout.css-mistica.js +6 -6
- package/dist-es/screen-reader-only.css-mistica.js +1 -1
- package/dist-es/select.css-mistica.js +18 -18
- package/dist-es/sheet-action-row.css-mistica.js +1 -1
- package/dist-es/sheet-common.css-mistica.js +2 -2
- package/dist-es/sheet-info.css-mistica.js +1 -1
- package/dist-es/sidenav-bar-context.js +14 -0
- package/dist-es/sidenav-bar-data.js +12 -0
- package/dist-es/sidenav-bar-first-level-item.js +124 -0
- package/dist-es/sidenav-bar-keyboard.js +253 -0
- package/dist-es/sidenav-bar-layout.css-mistica.js +2 -0
- package/dist-es/sidenav-bar-layout.js +86 -0
- package/dist-es/sidenav-bar-mobile.js +277 -0
- package/dist-es/sidenav-bar-motion.js +26 -0
- package/dist-es/sidenav-bar-panel.js +146 -0
- package/dist-es/sidenav-bar-row.js +208 -0
- package/dist-es/sidenav-bar-second-level-item.js +72 -0
- package/dist-es/sidenav-bar-section.js +112 -0
- package/dist-es/sidenav-bar-types.js +2 -0
- package/dist-es/sidenav-bar.css-mistica.js +74 -0
- package/dist-es/sidenav-bar.js +429 -0
- package/dist-es/skeletons.css-mistica.js +7 -7
- package/dist-es/skins/blau.js +12 -8
- package/dist-es/skins/esimflag.js +13 -9
- package/dist-es/skins/movistar.js +13 -9
- package/dist-es/skins/o2.js +13 -9
- package/dist-es/skins/skin-contract.css-mistica.js +735 -731
- package/dist-es/skins/telefonica.js +13 -9
- package/dist-es/skins/vivo-evolution.js +14 -10
- package/dist-es/skins/vivo.js +13 -9
- package/dist-es/skip-link.css-mistica.js +2 -2
- package/dist-es/slider.css-mistica.js +20 -20
- package/dist-es/snackbar.css-mistica.js +5 -5
- package/dist-es/spinner.css-mistica.js +1 -1
- package/dist-es/square.css-mistica.js +1 -1
- package/dist-es/stack.css-mistica.js +5 -5
- package/dist-es/stacking-group.css-mistica.js +1 -1
- package/dist-es/stepper.css-mistica.js +3 -3
- package/dist-es/style.css +1 -1
- package/dist-es/switch-component.css-mistica.js +37 -37
- package/dist-es/switch-component.js +26 -26
- package/dist-es/table.css-mistica.js +9 -9
- package/dist-es/tabs.css-mistica.js +19 -19
- package/dist-es/tag.css-mistica.js +2 -2
- package/dist-es/text-field-base.css-mistica.js +17 -17
- package/dist-es/text-field-components.css-mistica.js +4 -4
- package/dist-es/text-link.css-mistica.js +6 -6
- package/dist-es/text-tokens.js +82 -67
- package/dist-es/text.css-mistica.js +6 -6
- package/dist-es/timeline.css-mistica.js +10 -10
- package/dist-es/timer.css-mistica.js +6 -6
- package/dist-es/tooltip.css-mistica.js +2 -2
- package/dist-es/touchable.css-mistica.js +2 -2
- package/dist-es/utils/aspect-ratio-support.css-mistica.js +2 -2
- package/dist-es/video.css-mistica.js +1 -1
- package/dist-es/vivinho-loading-animation/vivinho-loading-animation.css-mistica.js +1 -1
- package/package.json +2 -1
- package/src/boxed.css.ts +1 -0
- package/src/boxed.tsx +18 -5
- package/src/callout.css.ts +4 -2
- package/src/community/skins/cyber-skin.tsx +19 -16
- package/src/index.tsx +14 -0
- package/src/list.css.ts +36 -1
- package/src/list.tsx +370 -344
- package/src/mobile-navigation-menu.tsx +168 -0
- package/src/navigation-bar.css.ts +2 -267
- package/src/navigation-bar.tsx +77 -370
- package/src/navigation-shared.css.ts +289 -0
- package/src/navigation-shared.tsx +262 -0
- package/src/package-version.tsx +1 -1
- package/src/portal.tsx +1 -1
- package/src/sidenav-bar-context.tsx +41 -0
- package/src/sidenav-bar-data.ts +49 -0
- package/src/sidenav-bar-first-level-item.tsx +203 -0
- package/src/sidenav-bar-keyboard.tsx +393 -0
- package/src/sidenav-bar-layout.css.ts +89 -0
- package/src/sidenav-bar-layout.tsx +61 -0
- package/src/sidenav-bar-mobile.tsx +302 -0
- package/src/sidenav-bar-motion.tsx +70 -0
- package/src/sidenav-bar-panel.tsx +269 -0
- package/src/sidenav-bar-row.tsx +272 -0
- package/src/sidenav-bar-second-level-item.tsx +99 -0
- package/src/sidenav-bar-section.tsx +98 -0
- package/src/sidenav-bar-types.ts +224 -0
- package/src/sidenav-bar.css.ts +1018 -0
- package/src/sidenav-bar.tsx +821 -0
- package/src/skins/blau.tsx +12 -8
- package/src/skins/esimflag.tsx +13 -9
- package/src/skins/movistar.tsx +13 -9
- package/src/skins/o2.tsx +13 -9
- package/src/skins/skin-contract.css.ts +2 -0
- package/src/skins/telefonica.tsx +13 -9
- package/src/skins/types/colors.tsx +2 -0
- package/src/skins/vivo-evolution.tsx +14 -10
- package/src/skins/vivo.tsx +13 -9
- package/src/switch-component.css.ts +20 -0
- package/src/switch-component.tsx +9 -1
- package/src/text-tokens.tsx +24 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import {style, styleVariants} from '@vanilla-extract/css';
|
|
2
|
+
import {sprinkles} from './sprinkles.css';
|
|
3
|
+
import {NAVBAR_HEIGHT_DESKTOP, NAVBAR_HEIGHT_MOBILE} from './theme';
|
|
4
|
+
import * as mq from './media-queries.css';
|
|
5
|
+
import {vars} from './skins/skin-contract.css';
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
* Styles of the parts that every navigation surface shares: the header of a bar, the content of that
|
|
9
|
+
* header, the burger icon, the panel that the burger opens, and the spacer of a fixed bar. `NavigationBar`,
|
|
10
|
+
* `MainNavigationBar`, `FunnelNavigationBar` and `SidenavBar` all read them, so a change here reaches the
|
|
11
|
+
* four of them.
|
|
12
|
+
*
|
|
13
|
+
* The styles of the desktop menu of `MainNavigationBar` stay in `navigation-bar.css.ts`, because that menu
|
|
14
|
+
* belongs to that component alone.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export const NAVBAR_ZINDEX = 25;
|
|
18
|
+
|
|
19
|
+
export const BURGER_MENU_ANIMATION_DURATION_MS = 300;
|
|
20
|
+
|
|
21
|
+
const borderWidth = 1;
|
|
22
|
+
|
|
23
|
+
// Header ----------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
export const topFixed = style([
|
|
26
|
+
sprinkles({
|
|
27
|
+
position: 'fixed',
|
|
28
|
+
top: 0,
|
|
29
|
+
left: 0,
|
|
30
|
+
right: 0,
|
|
31
|
+
}),
|
|
32
|
+
{
|
|
33
|
+
zIndex: NAVBAR_ZINDEX,
|
|
34
|
+
},
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
const navbarBase = style([
|
|
38
|
+
sprinkles({
|
|
39
|
+
display: 'flex',
|
|
40
|
+
alignItems: 'center',
|
|
41
|
+
width: '100%',
|
|
42
|
+
}),
|
|
43
|
+
{
|
|
44
|
+
borderWidth,
|
|
45
|
+
borderBottomStyle: 'solid',
|
|
46
|
+
|
|
47
|
+
'@media': {
|
|
48
|
+
[mq.tabletOrSmaller]: {
|
|
49
|
+
transition: 'border-color 300ms',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
]);
|
|
54
|
+
|
|
55
|
+
export const navbarBorderColorVariants = styleVariants({
|
|
56
|
+
default: [navbarBase, {borderColor: vars.colors.divider}],
|
|
57
|
+
noBorder: [navbarBase, {borderColor: 'transparent'}],
|
|
58
|
+
menuOpen: [
|
|
59
|
+
navbarBase,
|
|
60
|
+
{
|
|
61
|
+
borderColor: vars.colors.divider,
|
|
62
|
+
|
|
63
|
+
'@media': {
|
|
64
|
+
[mq.tabletOrSmaller]: {
|
|
65
|
+
borderColor: 'transparent',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
export const navigationBarContent = style([
|
|
73
|
+
sprinkles({
|
|
74
|
+
alignItems: 'center',
|
|
75
|
+
width: '100%',
|
|
76
|
+
display: 'flex',
|
|
77
|
+
}),
|
|
78
|
+
{
|
|
79
|
+
height: NAVBAR_HEIGHT_DESKTOP,
|
|
80
|
+
'@media': {
|
|
81
|
+
[mq.tabletOrSmaller]: {
|
|
82
|
+
height: NAVBAR_HEIGHT_MOBILE - borderWidth,
|
|
83
|
+
},
|
|
84
|
+
[mq.desktopOrBigger]: {
|
|
85
|
+
':last-child': {
|
|
86
|
+
height: NAVBAR_HEIGHT_DESKTOP - borderWidth,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
]);
|
|
92
|
+
|
|
93
|
+
export const navigationBarContentRight = style([
|
|
94
|
+
sprinkles({
|
|
95
|
+
display: 'flex',
|
|
96
|
+
alignItems: 'center',
|
|
97
|
+
justifyContent: 'flex-end',
|
|
98
|
+
}),
|
|
99
|
+
{
|
|
100
|
+
height: NAVBAR_HEIGHT_DESKTOP,
|
|
101
|
+
'@media': {
|
|
102
|
+
[mq.tabletOrSmaller]: {
|
|
103
|
+
paddingLeft: 24,
|
|
104
|
+
flex: 1,
|
|
105
|
+
height: NAVBAR_HEIGHT_MOBILE - borderWidth,
|
|
106
|
+
},
|
|
107
|
+
[mq.desktopOrBigger]: {
|
|
108
|
+
':last-child': {
|
|
109
|
+
height: NAVBAR_HEIGHT_DESKTOP - borderWidth,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
]);
|
|
115
|
+
|
|
116
|
+
export const navigationBarContentRightExpanded = style([
|
|
117
|
+
navigationBarContentRight,
|
|
118
|
+
sprinkles({
|
|
119
|
+
flex: 1,
|
|
120
|
+
}),
|
|
121
|
+
{
|
|
122
|
+
paddingLeft: 56,
|
|
123
|
+
},
|
|
124
|
+
]);
|
|
125
|
+
|
|
126
|
+
export const desktopOnly = style({
|
|
127
|
+
'@media': {
|
|
128
|
+
[mq.tabletOrSmaller]: {
|
|
129
|
+
display: 'none',
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
export const logoContainer = style([
|
|
135
|
+
sprinkles({
|
|
136
|
+
display: 'flex',
|
|
137
|
+
justifyContent: 'center',
|
|
138
|
+
}),
|
|
139
|
+
{
|
|
140
|
+
'@media': {
|
|
141
|
+
[mq.tabletOrSmaller]: {
|
|
142
|
+
marginRight: 0,
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
]);
|
|
147
|
+
|
|
148
|
+
// The spacer keeps the content of the page below a bar that is fixed to the top of the viewport.
|
|
149
|
+
export const spacerMobile = style({
|
|
150
|
+
'@media': {
|
|
151
|
+
[mq.tabletOrSmaller]: {
|
|
152
|
+
height: NAVBAR_HEIGHT_MOBILE,
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
export const spacer = style([
|
|
158
|
+
sprinkles({
|
|
159
|
+
height: NAVBAR_HEIGHT_DESKTOP,
|
|
160
|
+
}),
|
|
161
|
+
spacerMobile,
|
|
162
|
+
]);
|
|
163
|
+
|
|
164
|
+
// Burger icon -----------------------------------------------------------------
|
|
165
|
+
|
|
166
|
+
export const burgerIconContainer = style([
|
|
167
|
+
sprinkles({
|
|
168
|
+
position: 'relative',
|
|
169
|
+
width: 24,
|
|
170
|
+
height: 24,
|
|
171
|
+
}),
|
|
172
|
+
{
|
|
173
|
+
verticalAlign: 'middle',
|
|
174
|
+
borderRadius: 50,
|
|
175
|
+
},
|
|
176
|
+
]);
|
|
177
|
+
|
|
178
|
+
const iconBase = style([
|
|
179
|
+
sprinkles({
|
|
180
|
+
position: 'absolute',
|
|
181
|
+
}),
|
|
182
|
+
{
|
|
183
|
+
top: 0,
|
|
184
|
+
left: 0,
|
|
185
|
+
transition: 'transform 300ms, opacity 100ms',
|
|
186
|
+
},
|
|
187
|
+
]);
|
|
188
|
+
|
|
189
|
+
export const iconCloseOpen = style([
|
|
190
|
+
iconBase,
|
|
191
|
+
{
|
|
192
|
+
opacity: 1,
|
|
193
|
+
transform: 'rotate(0) scale(1)',
|
|
194
|
+
},
|
|
195
|
+
]);
|
|
196
|
+
|
|
197
|
+
export const iconCloseHidden = style([
|
|
198
|
+
iconBase,
|
|
199
|
+
{
|
|
200
|
+
opacity: 0,
|
|
201
|
+
transform: 'rotate(-45deg) scale(0.9)',
|
|
202
|
+
},
|
|
203
|
+
]);
|
|
204
|
+
|
|
205
|
+
export const iconMenuOpen = style([
|
|
206
|
+
iconBase,
|
|
207
|
+
{
|
|
208
|
+
opacity: 1,
|
|
209
|
+
transform: 'scale(1)',
|
|
210
|
+
},
|
|
211
|
+
]);
|
|
212
|
+
|
|
213
|
+
export const iconMenuHidden = style([
|
|
214
|
+
iconBase,
|
|
215
|
+
{
|
|
216
|
+
opacity: 0,
|
|
217
|
+
transform: 'scale(0.7)',
|
|
218
|
+
},
|
|
219
|
+
]);
|
|
220
|
+
|
|
221
|
+
export const burgerMenuButton = style({
|
|
222
|
+
marginRight: 24,
|
|
223
|
+
width: 'fit-content',
|
|
224
|
+
'@media': {
|
|
225
|
+
[mq.desktopOrBigger]: {
|
|
226
|
+
display: 'none',
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// Burger menu panel -----------------------------------------------------------
|
|
232
|
+
|
|
233
|
+
export const burgerMenu = sprinkles({
|
|
234
|
+
position: 'fixed',
|
|
235
|
+
left: 0,
|
|
236
|
+
right: 0,
|
|
237
|
+
bottom: 0,
|
|
238
|
+
background: vars.colors.background,
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
export const burgerMenuContainer = sprinkles({
|
|
242
|
+
height: '100%',
|
|
243
|
+
position: 'relative',
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
export const burgerMenuContentContainer = style([
|
|
247
|
+
sprinkles({
|
|
248
|
+
overflowY: 'auto',
|
|
249
|
+
width: '100%',
|
|
250
|
+
height: '100%',
|
|
251
|
+
position: 'absolute',
|
|
252
|
+
top: 0,
|
|
253
|
+
}),
|
|
254
|
+
{
|
|
255
|
+
transition: `transform ${BURGER_MENU_ANIMATION_DURATION_MS}ms ease-out`,
|
|
256
|
+
'@media': {
|
|
257
|
+
['(prefers-reduced-motion)']: {
|
|
258
|
+
transition: 'none',
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
]);
|
|
263
|
+
|
|
264
|
+
export const burgerMenuTransition = {
|
|
265
|
+
enter: style({
|
|
266
|
+
transform: 'translate(-100vw)',
|
|
267
|
+
}),
|
|
268
|
+
enterActive: style({
|
|
269
|
+
transform: 'translate(0)',
|
|
270
|
+
transition: `transform ${BURGER_MENU_ANIMATION_DURATION_MS}ms ease-out`,
|
|
271
|
+
'@media': {
|
|
272
|
+
['(prefers-reduced-motion)']: {
|
|
273
|
+
transition: 'none',
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
}),
|
|
277
|
+
exit: style({
|
|
278
|
+
transform: 'translate(0)',
|
|
279
|
+
}),
|
|
280
|
+
exitActive: style({
|
|
281
|
+
transform: 'translate(-100vw)',
|
|
282
|
+
transition: `transform ${BURGER_MENU_ANIMATION_DURATION_MS}ms ease-out`,
|
|
283
|
+
'@media': {
|
|
284
|
+
['(prefers-reduced-motion)']: {
|
|
285
|
+
transition: 'none',
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
}),
|
|
289
|
+
};
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import classnames from 'classnames';
|
|
4
|
+
import ResponsiveLayout from './responsive-layout';
|
|
5
|
+
import Inline from './inline';
|
|
6
|
+
import Box from './box';
|
|
7
|
+
import {Text3} from './text';
|
|
8
|
+
import {IconButton} from './icon-button';
|
|
9
|
+
import IconMenuRegular from './generated/mistica-icons/icon-menu-regular';
|
|
10
|
+
import IconCloseRegular from './generated/mistica-icons/icon-close-regular';
|
|
11
|
+
import IconChevronLeftRegular from './generated/mistica-icons/icon-chevron-left-regular';
|
|
12
|
+
import {ThemeVariant, normalizeVariant} from './theme-variant-context';
|
|
13
|
+
import {useTheme} from './hooks';
|
|
14
|
+
import {vars} from './skins/skin-contract.css';
|
|
15
|
+
import {getPrefixedDataAttributes} from './utils/dom';
|
|
16
|
+
import * as tokens from './text-tokens';
|
|
17
|
+
import * as styles from './navigation-shared.css';
|
|
18
|
+
|
|
19
|
+
import type {BoxProps} from './box';
|
|
20
|
+
import type {NonDeprecatedVariant, Variant} from './theme-variant-context';
|
|
21
|
+
import type {DataAttributes, HeadingType} from './utils/types';
|
|
22
|
+
import type {ExclusifyUnion} from './utils/utility-types';
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
* The parts that every navigation surface shares. `NavigationBar`, `MainNavigationBar` and
|
|
26
|
+
* `FunnelNavigationBar` build their bars with them, and so does the mobile `SidenavBar`. A change here
|
|
27
|
+
* reaches the four components, so every one of them carries screenshot tests.
|
|
28
|
+
*
|
|
29
|
+
* The desktop menu of `MainNavigationBar` stays in `navigation-bar.tsx`, because that menu belongs to that
|
|
30
|
+
* component alone. The panel of a burger menu lives in `mobile-navigation-menu.tsx`.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
export const BurgerMenuIcon = ({isOpen}: {isOpen: boolean}): JSX.Element => {
|
|
34
|
+
return (
|
|
35
|
+
<div className={styles.burgerIconContainer} role="presentation" data-testid="BurgerMenuIcon">
|
|
36
|
+
<div className={isOpen ? styles.iconCloseOpen : styles.iconCloseHidden}>
|
|
37
|
+
<IconCloseRegular />
|
|
38
|
+
</div>
|
|
39
|
+
<div className={isOpen ? styles.iconMenuHidden : styles.iconMenuOpen}>
|
|
40
|
+
<IconMenuRegular />
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
type HeaderProps = {
|
|
47
|
+
children: React.ReactNode;
|
|
48
|
+
topFixed?: boolean;
|
|
49
|
+
variant: NonDeprecatedVariant;
|
|
50
|
+
withBorder?: boolean;
|
|
51
|
+
isBurgerMenuOpen?: boolean;
|
|
52
|
+
dataAttributes?: DataAttributes;
|
|
53
|
+
isBottomRow?: boolean;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const Header = ({
|
|
57
|
+
children,
|
|
58
|
+
topFixed,
|
|
59
|
+
withBorder,
|
|
60
|
+
isBurgerMenuOpen,
|
|
61
|
+
variant,
|
|
62
|
+
dataAttributes,
|
|
63
|
+
}: HeaderProps): JSX.Element => {
|
|
64
|
+
const {isDarkMode} = useTheme();
|
|
65
|
+
|
|
66
|
+
const getBorderClass = () => {
|
|
67
|
+
const isBrandVariant = (variant === 'brand' || variant === 'negative') && !isDarkMode;
|
|
68
|
+
if (isBrandVariant || !withBorder) return styles.navbarBorderColorVariants.noBorder;
|
|
69
|
+
if (isBurgerMenuOpen) return styles.navbarBorderColorVariants.menuOpen;
|
|
70
|
+
|
|
71
|
+
return styles.navbarBorderColorVariants.default;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const backgroundColor = {
|
|
75
|
+
default: vars.colors.background,
|
|
76
|
+
brand: vars.colors.navigationBarBackground,
|
|
77
|
+
negative: vars.colors.backgroundNegative,
|
|
78
|
+
alternative: vars.colors.backgroundAlternative,
|
|
79
|
+
media: vars.colors.navigationBarBackground,
|
|
80
|
+
} as const;
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<header
|
|
84
|
+
className={classnames(getBorderClass(), {[styles.topFixed]: topFixed})}
|
|
85
|
+
style={{
|
|
86
|
+
background: backgroundColor[variant],
|
|
87
|
+
}}
|
|
88
|
+
{...getPrefixedDataAttributes(dataAttributes)}
|
|
89
|
+
>
|
|
90
|
+
{children}
|
|
91
|
+
</header>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
type NavigationBarContentContainerProps = {
|
|
96
|
+
right?: React.ReactNode;
|
|
97
|
+
children?: React.ReactNode;
|
|
98
|
+
desktopOnly?: boolean;
|
|
99
|
+
expandRightContent?: boolean;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export const NavigationBarContentContainer = React.forwardRef<
|
|
103
|
+
HTMLDivElement,
|
|
104
|
+
NavigationBarContentContainerProps
|
|
105
|
+
>(({right, children, desktopOnly, expandRightContent}, ref) => {
|
|
106
|
+
return (
|
|
107
|
+
<div
|
|
108
|
+
ref={ref}
|
|
109
|
+
className={classnames(styles.navigationBarContent, {[styles.desktopOnly]: desktopOnly})}
|
|
110
|
+
>
|
|
111
|
+
{children}
|
|
112
|
+
{right && (
|
|
113
|
+
<div
|
|
114
|
+
className={
|
|
115
|
+
expandRightContent
|
|
116
|
+
? styles.navigationBarContentRightExpanded
|
|
117
|
+
: styles.navigationBarContentRight
|
|
118
|
+
}
|
|
119
|
+
>
|
|
120
|
+
{right}
|
|
121
|
+
</div>
|
|
122
|
+
)}
|
|
123
|
+
</div>
|
|
124
|
+
);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
type WideConfig = {
|
|
128
|
+
paddingX: BoxProps['paddingX'];
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const NavigationBarSideMargins = ({
|
|
132
|
+
children,
|
|
133
|
+
wide,
|
|
134
|
+
backgroundColor,
|
|
135
|
+
}: {
|
|
136
|
+
children: React.ReactNode;
|
|
137
|
+
wide: boolean | WideConfig;
|
|
138
|
+
backgroundColor?: string;
|
|
139
|
+
}): JSX.Element => {
|
|
140
|
+
if (!wide) {
|
|
141
|
+
return <ResponsiveLayout backgroundColor={backgroundColor}>{children}</ResponsiveLayout>;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const defaultWidePaddingX: BoxProps['paddingX'] = {
|
|
145
|
+
mobile: 16,
|
|
146
|
+
tablet: 24,
|
|
147
|
+
desktop: 24,
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
return (
|
|
151
|
+
<Box
|
|
152
|
+
width="100%"
|
|
153
|
+
paddingX={
|
|
154
|
+
wide === true
|
|
155
|
+
? defaultWidePaddingX
|
|
156
|
+
: typeof wide.paddingX === 'number'
|
|
157
|
+
? wide.paddingX
|
|
158
|
+
: {
|
|
159
|
+
...defaultWidePaddingX,
|
|
160
|
+
...wide.paddingX,
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
background={backgroundColor}
|
|
164
|
+
>
|
|
165
|
+
{children}
|
|
166
|
+
</Box>
|
|
167
|
+
);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
type InteractiveProps = ExclusifyUnion<{href: string} | {to: string} | {onPress: () => void}>;
|
|
171
|
+
|
|
172
|
+
type MaybeInteractiveProps = ExclusifyUnion<{href?: string} | {to?: string} | {onPress?: () => void}>;
|
|
173
|
+
|
|
174
|
+
interface NavigationBarCommonProps {
|
|
175
|
+
variant?: Variant;
|
|
176
|
+
onBack?: () => void;
|
|
177
|
+
title?: string;
|
|
178
|
+
titleAs?: HeadingType;
|
|
179
|
+
right?: React.ReactElement;
|
|
180
|
+
withBorder?: boolean;
|
|
181
|
+
children?: undefined;
|
|
182
|
+
wide?: boolean | WideConfig;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
interface NavigationBarTopFixedProps extends NavigationBarCommonProps {
|
|
186
|
+
topFixed?: true;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
interface NavigationBarNotFixedProps extends NavigationBarCommonProps {
|
|
190
|
+
topFixed: false;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
type NavigationBarProps = NavigationBarTopFixedProps | NavigationBarNotFixedProps;
|
|
194
|
+
|
|
195
|
+
export const NavigationBar = ({
|
|
196
|
+
onBack,
|
|
197
|
+
title,
|
|
198
|
+
titleAs,
|
|
199
|
+
right,
|
|
200
|
+
variant = 'default',
|
|
201
|
+
topFixed = true,
|
|
202
|
+
withBorder = true,
|
|
203
|
+
wide = false,
|
|
204
|
+
}: NavigationBarProps): JSX.Element => {
|
|
205
|
+
const {texts, t} = useTheme();
|
|
206
|
+
const content = (
|
|
207
|
+
<NavigationBarContentContainer right={right} expandRightContent>
|
|
208
|
+
<Inline space={24} alignItems="center">
|
|
209
|
+
{onBack && (
|
|
210
|
+
<IconButton
|
|
211
|
+
aria-label={texts.backNavigationBar || t(tokens.backNavigationBar)}
|
|
212
|
+
onPress={onBack}
|
|
213
|
+
Icon={IconChevronLeftRegular}
|
|
214
|
+
bleedLeft
|
|
215
|
+
bleedRight
|
|
216
|
+
/>
|
|
217
|
+
)}
|
|
218
|
+
<Text3 regular truncate as={titleAs}>
|
|
219
|
+
{title}
|
|
220
|
+
</Text3>
|
|
221
|
+
</Inline>
|
|
222
|
+
</NavigationBarContentContainer>
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
const calcPaddingXWhenNotTopFixed = (): BoxProps['paddingX'] => {
|
|
226
|
+
if (typeof wide !== 'object') {
|
|
227
|
+
return 0;
|
|
228
|
+
}
|
|
229
|
+
return wide.paddingX ?? 0;
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
const normalizedVariant = normalizeVariant(variant);
|
|
233
|
+
|
|
234
|
+
return (
|
|
235
|
+
<ThemeVariant variant={normalizedVariant}>
|
|
236
|
+
<Header
|
|
237
|
+
topFixed={topFixed}
|
|
238
|
+
withBorder={withBorder}
|
|
239
|
+
variant={normalizedVariant}
|
|
240
|
+
dataAttributes={{testid: 'NavigationBar'}}
|
|
241
|
+
>
|
|
242
|
+
{topFixed ? (
|
|
243
|
+
<NavigationBarSideMargins wide={wide}>{content}</NavigationBarSideMargins>
|
|
244
|
+
) : (
|
|
245
|
+
<Box width="100%" paddingX={calcPaddingXWhenNotTopFixed()}>
|
|
246
|
+
{content}
|
|
247
|
+
</Box>
|
|
248
|
+
)}
|
|
249
|
+
</Header>
|
|
250
|
+
{topFixed && <div className={styles.spacer} />}
|
|
251
|
+
</ThemeVariant>
|
|
252
|
+
);
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
export type {
|
|
256
|
+
HeaderProps,
|
|
257
|
+
NavigationBarContentContainerProps,
|
|
258
|
+
WideConfig,
|
|
259
|
+
NavigationBarProps,
|
|
260
|
+
InteractiveProps,
|
|
261
|
+
MaybeInteractiveProps,
|
|
262
|
+
};
|
package/src/package-version.tsx
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// DO NOT EDIT THIS FILE. It's autogenerated by set-version.js
|
|
2
|
-
export const PACKAGE_VERSION = '17.
|
|
2
|
+
export const PACKAGE_VERSION = '17.4.0' as string;
|
package/src/portal.tsx
CHANGED
|
@@ -8,7 +8,7 @@ import ReactDOM from 'react-dom';
|
|
|
8
8
|
* This is useful for components that need position fixed, for example
|
|
9
9
|
* for menus, alerts, overlays, etc.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* @see https://react.dev/reference/react-dom/createPortal#usage
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
type Props = {
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
import type {SidenavCollapseState} from './sidenav-bar-types';
|
|
5
|
+
|
|
6
|
+
type SidenavBarContextValue = {
|
|
7
|
+
/** Target collapsed state. It flips at the first frame of the motion. */
|
|
8
|
+
collapsed: boolean;
|
|
9
|
+
/** Phase of the collapse motion, for the parts of a row that must wait until the rail rests. */
|
|
10
|
+
collapseState: SidenavCollapseState;
|
|
11
|
+
/** True when every movement of the sidenav takes zero time. See `useIsMotionOff`. */
|
|
12
|
+
isMotionOff: boolean;
|
|
13
|
+
doublePanel: boolean;
|
|
14
|
+
/** The first-level item whose children show in the panel. One panel opens at a time. */
|
|
15
|
+
panelOpenForItemId: string | null;
|
|
16
|
+
setPanelOpenForItemId: (id: string | null) => void;
|
|
17
|
+
/**
|
|
18
|
+
* The press of an item that navigates: it closes the open panel, then it reports the item as the
|
|
19
|
+
* new selection. One call does both, because the selection alone would reopen the second column that
|
|
20
|
+
* the press just closed. The item passes `null` when it has no id.
|
|
21
|
+
*/
|
|
22
|
+
selectItemAndClosePanel: (itemId: string | null) => void;
|
|
23
|
+
containerRef: React.RefObject<HTMLElement | null>;
|
|
24
|
+
selectedItemId: string | null;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const SidenavBarContext = React.createContext<SidenavBarContextValue>({
|
|
28
|
+
collapsed: false,
|
|
29
|
+
collapseState: 'expanded',
|
|
30
|
+
isMotionOff: false,
|
|
31
|
+
doublePanel: false,
|
|
32
|
+
panelOpenForItemId: null,
|
|
33
|
+
setPanelOpenForItemId: () => {},
|
|
34
|
+
selectItemAndClosePanel: () => {},
|
|
35
|
+
containerRef: React.createRef(),
|
|
36
|
+
selectedItemId: null,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const useSidenavBarContext = (): SidenavBarContextValue => React.useContext(SidenavBarContext);
|
|
40
|
+
|
|
41
|
+
export {SidenavBarContext, useSidenavBarContext};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
SidenavEntry,
|
|
3
|
+
SidenavFirstLevelItem,
|
|
4
|
+
SidenavLogo,
|
|
5
|
+
SidenavSection,
|
|
6
|
+
SidenavSectionTitle,
|
|
7
|
+
SidenavSlot,
|
|
8
|
+
SidenavSlotRenderProps,
|
|
9
|
+
} from './sidenav-bar-types';
|
|
10
|
+
|
|
11
|
+
/** Tells a first-level section apart from a first-level stand-alone item. */
|
|
12
|
+
const isSidenavSection = (entry: SidenavEntry): entry is SidenavSection =>
|
|
13
|
+
Array.isArray((entry as SidenavSection).items);
|
|
14
|
+
|
|
15
|
+
/** The items of the first level, in order: the items of every section, and every stand-alone item. */
|
|
16
|
+
const getFirstLevelItems = (entries: ReadonlyArray<SidenavEntry>): Array<SidenavFirstLevelItem> =>
|
|
17
|
+
entries.flatMap((entry) =>
|
|
18
|
+
isSidenavSection(entry) ? [...entry.items] : [entry as SidenavFirstLevelItem]
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
/** Reads the two shapes of a section title as one pair: the text, and the visibility of the heading. */
|
|
22
|
+
const getSidenavSectionTitle = (title: SidenavSectionTitle): {text: string; isHeadingVisible: boolean} =>
|
|
23
|
+
typeof title === 'string'
|
|
24
|
+
? {text: title, isHeadingVisible: true}
|
|
25
|
+
: {text: title.text, isHeadingVisible: !title.hidden};
|
|
26
|
+
|
|
27
|
+
/** Resolves the function form of a slot with the props of the current state. */
|
|
28
|
+
const renderSidenavSlot = (slot: SidenavSlot, props: SidenavSlotRenderProps): React.ReactNode =>
|
|
29
|
+
typeof slot === 'function' ? slot(props) : slot;
|
|
30
|
+
|
|
31
|
+
/** Resolves the four forms of the logo prop. `defaultLogo` is the logo of the skin, sized by the caller. */
|
|
32
|
+
const renderSidenavLogo = (
|
|
33
|
+
logo: SidenavLogo | undefined,
|
|
34
|
+
props: SidenavSlotRenderProps,
|
|
35
|
+
defaultLogo: React.ReactNode
|
|
36
|
+
): React.ReactNode => {
|
|
37
|
+
if (logo === false) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
if (typeof logo === 'function') {
|
|
41
|
+
return logo(props);
|
|
42
|
+
}
|
|
43
|
+
if (logo === undefined || logo === true) {
|
|
44
|
+
return defaultLogo;
|
|
45
|
+
}
|
|
46
|
+
return logo;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export {isSidenavSection, getFirstLevelItems, getSidenavSectionTitle, renderSidenavSlot, renderSidenavLogo};
|