@lifesg/react-design-system 3.5.0 → 3.6.0-canary.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.
- package/breadcrumb/breadcrumb.js +1 -1
- package/breadcrumb/breadcrumb.js.map +1 -1
- package/breadcrumb/breadcrumb.style.d.ts +1 -6
- package/breadcrumb/breadcrumb.style.js +27 -43
- package/breadcrumb/breadcrumb.style.js.map +1 -1
- package/breadcrumb/types.d.ts +2 -5
- package/cjs/breadcrumb/breadcrumb.js +1 -1
- package/cjs/breadcrumb/breadcrumb.js.map +1 -1
- package/cjs/breadcrumb/breadcrumb.style.js +16 -32
- package/cjs/breadcrumb/breadcrumb.style.js.map +1 -1
- package/cjs/drawer/drawer.js +1 -1
- package/cjs/drawer/drawer.js.map +1 -1
- package/cjs/drawer/drawer.styles.js +48 -31
- package/cjs/drawer/drawer.styles.js.map +1 -1
- package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.js +1 -1
- package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.js.map +1 -1
- package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js +30 -16
- package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js.map +1 -1
- package/cjs/local-nav/local-nav-menu/local-nav-menu.js +1 -1
- package/cjs/local-nav/local-nav-menu/local-nav-menu.js.map +1 -1
- package/cjs/local-nav/local-nav-menu/local-nav-menu.styles.js +25 -11
- package/cjs/local-nav/local-nav-menu/local-nav-menu.styles.js.map +1 -1
- package/cjs/menu/menu-content.js +1 -1
- package/cjs/menu/menu-content.js.map +1 -1
- package/cjs/menu/menu-content.styles.js +4 -1
- package/cjs/menu/menu-content.styles.js.map +1 -1
- package/cjs/menu/menu-item.styles.js +1 -1
- package/cjs/menu/menu-item.styles.js.map +1 -1
- package/cjs/menu/menu-link.styles.js +1 -1
- package/cjs/menu/menu-link.styles.js.map +1 -1
- package/cjs/menu/menu-section.js +1 -1
- package/cjs/menu/menu-section.js.map +1 -1
- package/cjs/menu/menu-section.styles.js +23 -9
- package/cjs/menu/menu-section.styles.js.map +1 -1
- package/cjs/navbar/navbar-items.js +1 -1
- package/cjs/navbar/navbar-items.js.map +1 -1
- package/cjs/pagination/pagination.js +1 -1
- package/cjs/pagination/pagination.js.map +1 -1
- package/cjs/shared/dropdown-list/dropdown-label.js +1 -1
- package/cjs/shared/dropdown-list/dropdown-label.js.map +1 -1
- package/cjs/shared/fade-wrapper/fade-wrapper.js +1 -1
- package/cjs/shared/fade-wrapper/fade-wrapper.js.map +1 -1
- package/drawer/drawer.d.ts +1 -1
- package/drawer/drawer.js +1 -1
- package/drawer/drawer.js.map +1 -1
- package/drawer/drawer.styles.d.ts +8 -1
- package/drawer/drawer.styles.js +46 -29
- package/drawer/drawer.styles.js.map +1 -1
- package/drawer/types.d.ts +7 -0
- package/input-group/types.d.ts +1 -1
- package/input-select/types.d.ts +1 -1
- package/local-nav/local-nav-dropdown/local-nav-dropdown.js +1 -1
- package/local-nav/local-nav-dropdown/local-nav-dropdown.js.map +1 -1
- package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.d.ts +3 -0
- package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js +42 -28
- package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js.map +1 -1
- package/local-nav/local-nav-menu/local-nav-menu.js +1 -1
- package/local-nav/local-nav-menu/local-nav-menu.js.map +1 -1
- package/local-nav/local-nav-menu/local-nav-menu.styles.d.ts +3 -0
- package/local-nav/local-nav-menu/local-nav-menu.styles.js +25 -11
- package/local-nav/local-nav-menu/local-nav-menu.styles.js.map +1 -1
- package/local-nav/types.d.ts +17 -0
- package/menu/menu-content.js +1 -1
- package/menu/menu-content.js.map +1 -1
- package/menu/menu-content.styles.d.ts +1 -0
- package/menu/menu-content.styles.js +17 -14
- package/menu/menu-content.styles.js.map +1 -1
- package/menu/menu-item.styles.js +1 -1
- package/menu/menu-item.styles.js.map +1 -1
- package/menu/menu-link.styles.js +1 -1
- package/menu/menu-link.styles.js.map +1 -1
- package/menu/menu-section.d.ts +1 -1
- package/menu/menu-section.js +1 -1
- package/menu/menu-section.js.map +1 -1
- package/menu/menu-section.styles.d.ts +9 -2
- package/menu/menu-section.styles.js +22 -8
- package/menu/menu-section.styles.js.map +1 -1
- package/menu/menu.d.ts +1 -1
- package/menu/types.d.ts +2 -2
- package/navbar/navbar-items.js +1 -1
- package/navbar/navbar-items.js.map +1 -1
- package/navbar/types.d.ts +1 -0
- package/package.json +1 -1
- package/pagination/pagination.js +1 -1
- package/pagination/pagination.js.map +1 -1
- package/pagination/types.d.ts +1 -0
- package/select-histogram/types.d.ts +1 -1
- package/shared/dropdown-list/dropdown-label.d.ts +2 -2
- package/shared/dropdown-list/dropdown-label.js +1 -1
- package/shared/dropdown-list/dropdown-label.js.map +1 -1
- package/shared/dropdown-list/types.d.ts +2 -2
- package/shared/fade-wrapper/fade-wrapper.js +1 -1
- package/shared/fade-wrapper/fade-wrapper.js.map +1 -1
- package/shared/fade-wrapper/types.d.ts +1 -0
package/drawer/drawer.styles.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import i,{css as t}from"styled-components";import{ClickableIcon as
|
|
1
|
+
import i,{css as t}from"styled-components";import{ClickableIcon as e}from"../shared/clickable-icon/clickable-icon.js";import{Motion as o,Colour as a,Shadow as n,Radius as d,MediaQuery as s,Spacing as r,Font as l,Border as c}from"../theme/index.js";import{Typography as h}from"../typography/typography.js";const p=t`
|
|
2
2
|
transition-property: right, visibility;
|
|
3
3
|
|
|
4
4
|
&[data-status="initial"] {
|
|
@@ -7,19 +7,19 @@ import i,{css as t}from"styled-components";import{ClickableIcon as o}from"../sha
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
&[data-status="open"] {
|
|
10
|
-
transition-duration: ${
|
|
11
|
-
transition-timing-function: ${
|
|
10
|
+
transition-duration: ${o["duration-800"]};
|
|
11
|
+
transition-timing-function: ${o["ease-entrance"]};
|
|
12
12
|
right: 0;
|
|
13
13
|
visibility: visible;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
&[data-status="close"] {
|
|
17
|
-
transition-duration: ${
|
|
18
|
-
transition-timing-function: ${
|
|
17
|
+
transition-duration: ${o["duration-800"]};
|
|
18
|
+
transition-timing-function: ${o["ease-exit"]};
|
|
19
19
|
right: -100%;
|
|
20
20
|
visibility: hidden;
|
|
21
21
|
}
|
|
22
|
-
`,
|
|
22
|
+
`,g=i.div`
|
|
23
23
|
position: fixed;
|
|
24
24
|
top: 0;
|
|
25
25
|
|
|
@@ -27,22 +27,22 @@ import i,{css as t}from"styled-components";import{ClickableIcon as o}from"../sha
|
|
|
27
27
|
flex-direction: column;
|
|
28
28
|
height: 100%;
|
|
29
29
|
|
|
30
|
-
background-color: ${
|
|
30
|
+
background-color: ${a.bg};
|
|
31
31
|
box-shadow: ${n["lg-subtle"]};
|
|
32
32
|
|
|
33
|
-
${
|
|
33
|
+
${p}
|
|
34
34
|
|
|
35
35
|
width: 40%;
|
|
36
36
|
border-top-left-radius: ${d.md};
|
|
37
37
|
border-bottom-left-radius: ${d.md};
|
|
38
38
|
overflow: hidden;
|
|
39
39
|
|
|
40
|
-
${
|
|
40
|
+
${s.MaxWidth.xl} {
|
|
41
41
|
width: 50%;
|
|
42
42
|
min-width: 700px;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
${
|
|
45
|
+
${s.MaxWidth.lg} {
|
|
46
46
|
width: 100%;
|
|
47
47
|
min-width: unset;
|
|
48
48
|
border-top-left-radius: 0;
|
|
@@ -52,40 +52,57 @@ import i,{css as t}from"styled-components";import{ClickableIcon as o}from"../sha
|
|
|
52
52
|
top: 0;
|
|
53
53
|
display: flex;
|
|
54
54
|
align-items: center;
|
|
55
|
-
gap: ${
|
|
56
|
-
padding: ${
|
|
57
|
-
${
|
|
58
|
-
calc(${l.Spec["heading-lh-md"]} + ${
|
|
59
|
-
background-color: ${
|
|
60
|
-
border-bottom: ${
|
|
55
|
+
gap: ${r["spacing-16"]};
|
|
56
|
+
padding: ${r["spacing-32"]} ${r["spacing-16"]}
|
|
57
|
+
${r["spacing-16"]}
|
|
58
|
+
calc(${l.Spec["heading-lh-md"]} + ${r["spacing-32"]});
|
|
59
|
+
background-color: ${a.bg};
|
|
60
|
+
border-bottom: ${c["width-010"]} ${c.solid} ${a.border};
|
|
61
61
|
|
|
62
|
-
${
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
${i=>i.$stacked&&t`
|
|
63
|
+
/* Stack the call-to-action below the heading when the drawer is too
|
|
64
|
+
narrow to fit both on one line. */
|
|
65
|
+
flex-direction: column;
|
|
66
|
+
align-items: stretch;
|
|
67
|
+
gap: ${r["spacing-16"]};
|
|
68
|
+
`}
|
|
69
|
+
|
|
70
|
+
${s.MaxWidth.lg} {
|
|
71
|
+
padding: ${r["spacing-32"]} ${r["spacing-20"]}
|
|
72
|
+
${r["spacing-16"]}
|
|
73
|
+
calc(${l.Spec["heading-lh-md"]} + ${r["spacing-24"]});
|
|
67
74
|
}
|
|
68
|
-
`,
|
|
69
|
-
|
|
75
|
+
`,f=i.div`
|
|
76
|
+
display: flex;
|
|
77
|
+
/* Flush right, beside the heading. */
|
|
78
|
+
margin-left: auto;
|
|
79
|
+
|
|
80
|
+
${i=>i.$stacked&&t`
|
|
81
|
+
/* When stacked, flush left so the buttons line up with the heading
|
|
82
|
+
(the header's left padding already clears the close icon). */
|
|
83
|
+
margin-left: 0;
|
|
84
|
+
`}
|
|
85
|
+
`,m=i(e)`
|
|
86
|
+
color: ${a.icon};
|
|
70
87
|
padding: 0;
|
|
71
88
|
position: absolute;
|
|
72
|
-
top: ${
|
|
73
|
-
left: ${
|
|
89
|
+
top: ${r["spacing-32"]};
|
|
90
|
+
left: ${r["spacing-16"]};
|
|
74
91
|
&:active,
|
|
75
92
|
&:focus {
|
|
76
|
-
color: ${
|
|
93
|
+
color: ${a["icon-hover"]};
|
|
77
94
|
}
|
|
78
95
|
|
|
79
96
|
svg {
|
|
80
97
|
height: ${l.Spec["heading-lh-md"]};
|
|
81
98
|
width: ${l.Spec["heading-lh-md"]};
|
|
82
99
|
}
|
|
83
|
-
`,b=i(
|
|
100
|
+
`,b=i(h.HeadingMD)`
|
|
84
101
|
text-overflow: ellipsis;
|
|
85
102
|
overflow: hidden;
|
|
86
103
|
white-space: nowrap;
|
|
87
|
-
`,
|
|
104
|
+
`,u=i.div`
|
|
88
105
|
flex: 1;
|
|
89
106
|
overflow-y: auto;
|
|
90
|
-
`;export{m as CloseButton,
|
|
107
|
+
`;export{f as CallToAction,m as CloseButton,g as Container,u as Content,$ as Header,b as Heading};
|
|
91
108
|
//# sourceMappingURL=drawer.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.styles.js","sources":["../../src/drawer/drawer.styles.tsx"],"sourcesContent":["import styled, { css } from \"styled-components\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport {\n Border,\n Colour,\n Font,\n MediaQuery,\n Motion,\n Radius,\n Shadow,\n Spacing,\n} from \"../theme\";\nimport { Typography } from \"../typography\";\n\n// =============================================================================\n// STYLE INTERFACE, transient props are denoted with $\n// See more https://styled-components.com/docs/api#transient-props\n// =============================================================================\ninterface StyleProps {\n $show?: boolean | undefined;\n}\n\n// =============================================================================\n// STYLING HELPERS\n// =============================================================================\n// FloatingUI transition styles\nconst FLOATING_TRANSITION_STYLES = css`\n transition-property: right, visibility;\n\n &[data-status=\"initial\"] {\n right: -100%;\n visibility: hidden;\n }\n\n &[data-status=\"open\"] {\n transition-duration: ${Motion[\"duration-800\"]};\n transition-timing-function: ${Motion[\"ease-entrance\"]};\n right: 0;\n visibility: visible;\n }\n\n &[data-status=\"close\"] {\n transition-duration: ${Motion[\"duration-800\"]};\n transition-timing-function: ${Motion[\"ease-exit\"]};\n right: -100%;\n visibility: hidden;\n }\n`;\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const Container = styled.div<StyleProps>`\n position: fixed;\n top: 0;\n\n display: flex;\n flex-direction: column;\n height: 100%;\n\n background-color: ${Colour.bg};\n box-shadow: ${Shadow[\"lg-subtle\"]};\n\n ${FLOATING_TRANSITION_STYLES}\n\n width: 40%;\n border-top-left-radius: ${Radius[\"md\"]};\n border-bottom-left-radius: ${Radius[\"md\"]};\n overflow: hidden;\n\n ${MediaQuery.MaxWidth.xl} {\n width: 50%;\n min-width: 700px;\n }\n\n ${MediaQuery.MaxWidth.lg} {\n width: 100%;\n min-width: unset;\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n`;\n\nexport const Header = styled.div
|
|
1
|
+
{"version":3,"file":"drawer.styles.js","sources":["../../src/drawer/drawer.styles.tsx"],"sourcesContent":["import styled, { css } from \"styled-components\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport {\n Border,\n Colour,\n Font,\n MediaQuery,\n Motion,\n Radius,\n Shadow,\n Spacing,\n} from \"../theme\";\nimport { Typography } from \"../typography\";\n\n// =============================================================================\n// STYLE INTERFACE, transient props are denoted with $\n// See more https://styled-components.com/docs/api#transient-props\n// =============================================================================\ninterface StyleProps {\n $show?: boolean | undefined;\n}\n\ninterface HeaderStyleProps {\n $stacked?: boolean | undefined;\n}\n\ninterface CallToActionStyleProps {\n $stacked?: boolean | undefined;\n}\n\n// =============================================================================\n// STYLING HELPERS\n// =============================================================================\n// FloatingUI transition styles\nconst FLOATING_TRANSITION_STYLES = css`\n transition-property: right, visibility;\n\n &[data-status=\"initial\"] {\n right: -100%;\n visibility: hidden;\n }\n\n &[data-status=\"open\"] {\n transition-duration: ${Motion[\"duration-800\"]};\n transition-timing-function: ${Motion[\"ease-entrance\"]};\n right: 0;\n visibility: visible;\n }\n\n &[data-status=\"close\"] {\n transition-duration: ${Motion[\"duration-800\"]};\n transition-timing-function: ${Motion[\"ease-exit\"]};\n right: -100%;\n visibility: hidden;\n }\n`;\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const Container = styled.div<StyleProps>`\n position: fixed;\n top: 0;\n\n display: flex;\n flex-direction: column;\n height: 100%;\n\n background-color: ${Colour.bg};\n box-shadow: ${Shadow[\"lg-subtle\"]};\n\n ${FLOATING_TRANSITION_STYLES}\n\n width: 40%;\n border-top-left-radius: ${Radius[\"md\"]};\n border-bottom-left-radius: ${Radius[\"md\"]};\n overflow: hidden;\n\n ${MediaQuery.MaxWidth.xl} {\n width: 50%;\n min-width: 700px;\n }\n\n ${MediaQuery.MaxWidth.lg} {\n width: 100%;\n min-width: unset;\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n`;\n\nexport const Header = styled.div<HeaderStyleProps>`\n top: 0;\n display: flex;\n align-items: center;\n gap: ${Spacing[\"spacing-16\"]};\n padding: ${Spacing[\"spacing-32\"]} ${Spacing[\"spacing-16\"]}\n ${Spacing[\"spacing-16\"]}\n calc(${Font.Spec[\"heading-lh-md\"]} + ${Spacing[\"spacing-32\"]});\n background-color: ${Colour.bg};\n border-bottom: ${Border[\"width-010\"]} ${Border.solid} ${Colour.border};\n\n ${(props) =>\n props.$stacked &&\n css`\n /* Stack the call-to-action below the heading when the drawer is too\n narrow to fit both on one line. */\n flex-direction: column;\n align-items: stretch;\n gap: ${Spacing[\"spacing-16\"]};\n `}\n\n ${MediaQuery.MaxWidth.lg} {\n padding: ${Spacing[\"spacing-32\"]} ${Spacing[\"spacing-20\"]}\n ${Spacing[\"spacing-16\"]}\n calc(${Font.Spec[\"heading-lh-md\"]} + ${Spacing[\"spacing-24\"]});\n }\n`;\n\nexport const CallToAction = styled.div<CallToActionStyleProps>`\n display: flex;\n /* Flush right, beside the heading. */\n margin-left: auto;\n\n ${(props) =>\n props.$stacked &&\n css`\n /* When stacked, flush left so the buttons line up with the heading\n (the header's left padding already clears the close icon). */\n margin-left: 0;\n `}\n`;\n\nexport const CloseButton = styled(ClickableIcon)`\n color: ${Colour.icon};\n padding: 0;\n position: absolute;\n top: ${Spacing[\"spacing-32\"]};\n left: ${Spacing[\"spacing-16\"]};\n &:active,\n &:focus {\n color: ${Colour[\"icon-hover\"]};\n }\n\n svg {\n height: ${Font.Spec[\"heading-lh-md\"]};\n width: ${Font.Spec[\"heading-lh-md\"]};\n }\n`;\n\nexport const Heading = styled(Typography.HeadingMD)`\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n`;\n\nexport const Content = styled.div`\n flex: 1;\n overflow-y: auto;\n`;\n"],"names":["FLOATING_TRANSITION_STYLES","css","Motion","Container","styled","div","Colour","bg","Shadow","Radius","MediaQuery","MaxWidth","xl","lg","Header","Spacing","Font","Spec","Border","solid","border","props","$stacked","CallToAction","CloseButton","ClickableIcon","icon","Heading","Typography","HeadingMD","Content"],"mappings":"iTAkCA,MAAMA,EAA6BC,CAAG;;;;;;;;;+BASPC,EAAO;sCACAA,EAAO;;;;;;+BAMdA,EAAO;sCACAA,EAAO;;;;EAShCC,EAAYC,EAAOC,GAAe;;;;;;;;wBAQvBC,EAAOC;kBACbC,EAAO;;MAEnBR;;;8BAGwBS,EAAW;iCACRA,EAAW;;;MAGtCC,EAAWC,SAASC;;;;;MAKpBF,EAAWC,SAASE;;;;;;EAQbC,EAASV,EAAOC,GAAqB;;;;WAIvCU,EAAQ;eACJA,EAAQ,iBAAiBA,EAAQ;UACtCA,EAAQ;eACHC,EAAKC,KAAK,sBAAsBF,EAAQ;wBAC/BT,EAAOC;qBACVW,EAAO,gBAAgBA,EAAOC,SAASb,EAAOc;;MAE5DC,GACCA,EAAMC,UACNrB,CAAG;;;;;mBAKQc,EAAQ;;;MAGrBL,EAAWC,SAASE;mBACPE,EAAQ,iBAAiBA,EAAQ;cACtCA,EAAQ;mBACHC,EAAKC,KAAK,sBAAsBF,EAAQ;;EAI9CQ,EAAenB,EAAOC,GAA2B;;;;;MAKvDgB,GACCA,EAAMC,UACNrB,CAAG;;;;;EAOEuB,EAAcpB,EAAOqB,EAAc;aACnCnB,EAAOoB;;;WAGTX,EAAQ;YACPA,EAAQ;;;iBAGHT,EAAO;;;;kBAINU,EAAKC,KAAK;iBACXD,EAAKC,KAAK;;EAIdU,EAAUvB,EAAOwB,EAAWC,UAAU;;;;EAMtCC,EAAU1B,EAAOC,GAAG;;;"}
|
package/drawer/types.d.ts
CHANGED
|
@@ -11,4 +11,11 @@ export interface DrawerProps {
|
|
|
11
11
|
onClose?: (() => void) | undefined;
|
|
12
12
|
/** Called when the overlay is clicked */
|
|
13
13
|
onOverlayClick?: (() => void) | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Optional element rendered in the header, e.g. a link or button.
|
|
16
|
+
*
|
|
17
|
+
* Sits beside the title on wider drawers, and wraps onto its own line
|
|
18
|
+
* below the title once the drawer is narrow.
|
|
19
|
+
*/
|
|
20
|
+
customCallToAction?: React.ReactNode | undefined;
|
|
14
21
|
}
|
package/input-group/types.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export interface ListAddon<T, V> extends DropdownDisplayProps<T, V>, DropdownSea
|
|
|
22
22
|
* Values: "loading" | "fail" | "success"
|
|
23
23
|
*/
|
|
24
24
|
optionsLoadState?: ItemsLoadStateType | undefined;
|
|
25
|
-
/** Specifies the truncation type. Truncated text will be replaced with ellipsis. Values: "middle" | "end" */
|
|
25
|
+
/** Specifies the truncation type. Truncated text will be replaced with ellipsis. Specify "none" to display the text in full. Values: "middle" | "end" | "none" */
|
|
26
26
|
optionTruncationType?: TruncateType | undefined;
|
|
27
27
|
onRetry?: (() => void) | undefined;
|
|
28
28
|
onHideOptions?: (() => void) | undefined;
|
package/input-select/types.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export interface InputSelectOptionsProps<T> {
|
|
|
8
8
|
* Values: "loading" | "fail" | "success"
|
|
9
9
|
*/
|
|
10
10
|
optionsLoadState?: ItemsLoadStateType | undefined;
|
|
11
|
-
/** Specifies the truncation type. Truncated text will be replaced with ellipsis. Values: "middle" | "end" */
|
|
11
|
+
/** Specifies the truncation type. Truncated text will be replaced with ellipsis. Specify "none" to display the text in full. Values: "middle" | "end" | "none" */
|
|
12
12
|
optionTruncationType?: TruncateType | undefined;
|
|
13
13
|
onShowOptions?: (() => void) | undefined;
|
|
14
14
|
onHideOptions?: (() => void) | undefined;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsxs as e,Fragment as t,jsx as n}from"react/jsx-runtime";import r,{useRef as i,useState as o,useImperativeHandle as d,useEffect as l}from"react";import{Typography as s}from"../../typography/typography.js";import"../../util/calendar-helper.js";import"../../util/date-helper.js";import"../../util/date-input-helper.js";import{useId as c}from"../../util/simple-id-generator.js";import"../../util/string-helper.js";import"@react-aria/live-announcer";import{NavWrapper as a,NavSelect as p,NavSelectIcon as u,NavItemList as m,Backdrop as
|
|
1
|
+
import{jsxs as e,Fragment as t,jsx as n}from"react/jsx-runtime";import r,{useRef as i,useState as o,useImperativeHandle as d,useEffect as l}from"react";import{Typography as s}from"../../typography/typography.js";import"../../util/calendar-helper.js";import"../../util/date-helper.js";import"../../util/date-input-helper.js";import{useId as c}from"../../util/simple-id-generator.js";import"../../util/string-helper.js";import"@react-aria/live-announcer";import{NavWrapper as a,NavSelect as p,NavSelectIcon as u,NavItemList as m,Backdrop as h,NavItem as f,LeftAddon as w,StyledTickIcon as v,TitleContainer as g,NavItemLabel as y,RightAddon as b}from"./local-nav-dropdown.styles.js";const x=r.forwardRef((({defaultLabel:r,stickyOffset:x=0,onNavItemSelect:D,items:E,selectedItemIndex:I,id:L,"data-testid":C,className:j,renderItem:S},A)=>{const B=i(null),z=i(null),H=i(null),K=i([]),[M,N]=o(!1),[O,R]=o(!1),[T,W]=o(0),[U,q]=o(0),[F,G]=o(0),[J,P]=o(0),Q=C||"local-nav-dropdown",V=c();d(A,(()=>H.current));const X="number"==typeof I&&I>=0&&M?E[I].title:r;l((()=>{if(z.current){const e=z.current.getBoundingClientRect().height;q(e)}}),[]),l((()=>(Y(),()=>{Z("remove")})),[]),l((()=>{Z(O&&M?"add":"remove")}),[O,M]),l((()=>{W(window.innerHeight);const e=()=>{W(window.innerHeight)};return window.addEventListener("resize",e),()=>window.removeEventListener("resize",e)}),[]),l((()=>{const e=new IntersectionObserver((e=>{const[t]=e;N(!t.isIntersecting)}),{threshold:1,rootMargin:`-${x}px 0px 0px 0px`});return B.current&&e.observe(B.current),()=>e.disconnect()}),[x]),l((()=>{const e=()=>{const e=null==H?void 0:H.current;if(e){const t=e.getBoundingClientRect(),n=document.body.clientWidth-t.right,r=t.left,i=Math.max(n,r);G(i)}};return e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}}),[]),l((()=>{var e;O&&(null===(e=K.current[J])||void 0===e||e.focus())}),[O,J]);const Y=()=>{if(!document.getElementById(k)){const e=document.createElement("style");e.id=k;const t=document.documentElement.clientWidth,n=window.innerWidth-t;e.innerHTML=`\n\t\t\t\t.${$} {\n\t\t\t\t\toverflow: hidden;\n\t\t\t\t\tpadding-right: ${n}px !important;\n\t\t\t\t\t-ms-overflow-style: none;\n\t\t\t\t\tscrollbar-width: none;\n\t\t\t\t}\n\n\t\t\t\t.${$}::-webkit-scrollbar {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\t`,document.body.appendChild(e)}},Z=e=>{const t=document.body.classList.contains($);"add"!==e||t?"remove"===e&&t&&document.body.classList.remove($):document.body.classList.add($)},_=(e,t)=>{const{key:n}=e;"Enter"!==n&&" "!==n||(e.preventDefault(),t(e))};return e(t,{children:[n("span",{ref:B,"data-testid":"sticky-ref"}),e(a,{$isStickied:M,$sideMargin:F,$stickyOffset:x,ref:H,id:L,"data-testid":Q,className:j,children:[e(p,{ref:z,role:"button",onClick:()=>{R((e=>!e))},onKeyDown:e=>{const{key:t}=e;"ArrowDown"===t?(e.preventDefault(),O||R(!0),P(0)):"ArrowUp"===t?(e.preventDefault(),O||R(!0),P(E.length-1)):"Enter"===t||" "===t?(e.preventDefault(),R(!0),P(0)):("Tab"===t||"Escape"===t)&&R(!1)},"data-testid":`${Q}-label`,$isDropdownExpanded:O,"aria-haspopup":"true","aria-expanded":O,"aria-controls":V,tabIndex:0,children:[n(s.BodyBL,{weight:"semibold",children:X}),n(u,{$isDropdownExpanded:O})]}),O&&n(m,{id:V,role:"menu",onKeyDown:e=>{var t;const{key:n}=e;if("ArrowDown"===n){e.preventDefault();const t=(J+1)%E.length;P(t)}else if("ArrowUp"===n){e.preventDefault();const t=J>0?J-1:E.length-1;P(t)}else"Tab"===n?R(!1):"Escape"===n&&(R(!1),null===(t=z.current)||void 0===t||t.focus())},"data-testid":`${Q}-dropdown-list`,$viewportHeight:T-U-x,children:E.map(((t,r)=>(({handleClick:t,isSelected:r,item:i,renderItem:o,index:d})=>{const{id:l,title:s,titleAddon:c}=i;return o?n("li",{id:l,role:"menuitem",onClick:t,onKeyDown:e=>_(e,t),"aria-current":!!r||void 0,tabIndex:-1,ref:e=>{K.current[d]=e},children:o(i,{selected:r,stickied:M})},d):e(f,{id:l,role:"menuitem",$isSelected:r&&M,onClick:t,onKeyDown:e=>_(e,t),"aria-current":!!r||void 0,tabIndex:-1,ref:e=>{K.current[d]=e},children:[r&&n(w,{children:n(v,{})}),c?e(g,{children:[c.left&&n(w,{children:c.left}),n(y,{$isSelected:r,children:s}),c.right&&n(b,{children:c.right})]}):n(y,{$isSelected:r,children:s})]},d)})({handleClick:e=>((e,t,n)=>{D&&D(e,t,n),R(!1)})(e,t,r),isSelected:r===I,item:t,renderItem:S,index:r})))}),O&&M&&n(h,{onClick:()=>{R(!1)}})]})]})})),k="lifesg-ds-local-nav-dropdown-stylesheet",$="lifesg-ds-local-nav-dropdown-open";export{x as LocalNavDropdown};
|
|
2
2
|
//# sourceMappingURL=local-nav-dropdown.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-nav-dropdown.js","sources":["../../../src/local-nav/local-nav-dropdown/local-nav-dropdown.tsx"],"sourcesContent":["import React, { useEffect, useImperativeHandle, useRef, useState } from \"react\";\nimport { Typography } from \"../../typography\";\nimport { useId } from \"../../util\";\nimport { LocalNavDropdownItemComponentProps } from \"../internal-types\";\nimport { LocalNavDropdownProps, LocalNavItemProps } from \"../types\";\nimport {\n Backdrop,\n NavItem,\n NavItemLabel,\n NavItemList,\n NavSelect,\n NavSelectIcon,\n NavWrapper,\n StyledTickIcon,\n} from \"./local-nav-dropdown.styles\";\n\nconst Component = (\n {\n defaultLabel,\n stickyOffset = 0,\n onNavItemSelect,\n items,\n selectedItemIndex,\n id,\n \"data-testid\": testId,\n className,\n renderItem,\n }: LocalNavDropdownProps,\n ref: React.Ref<HTMLElement>\n): JSX.Element => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const detectStickyRef = useRef<HTMLSpanElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const navWrapperRef = useRef<HTMLElement>(null);\n const listItemRefs = useRef<(HTMLLIElement | null)[]>([]);\n const [isStickied, setIsStickied] = useState<boolean>(false);\n const [isDropdownExpanded, setIsDropdownExpanded] =\n useState<boolean>(false);\n const [viewportHeight, setViewportHeight] = useState(0);\n const [dropdowntHeight, setDropdownHeight] = useState(0);\n const [dynamicMargin, setDynamicMargin] = useState(0);\n const [focusedIndex, setFocusedIndex] = useState(0);\n const navTestId = testId || \"local-nav-dropdown\";\n const dropdownListId = useId();\n\n useImperativeHandle(ref, () => navWrapperRef.current!);\n\n const labelText =\n typeof selectedItemIndex === \"number\" &&\n selectedItemIndex >= 0 &&\n isStickied\n ? items[selectedItemIndex].title\n : defaultLabel;\n\n // =============================================================================\n // EFFECTS, EVENT LISTENERS\n // ============================================================================\n\n useEffect(() => {\n if (dropdownRef.current) {\n const dropdownHeight =\n dropdownRef.current.getBoundingClientRect().height;\n setDropdownHeight(dropdownHeight);\n }\n }, []);\n\n useEffect(() => {\n addStylesheetForDocumentBody();\n return () => {\n applyBodyStyleClass(\"remove\");\n };\n }, []);\n\n useEffect(() => {\n if (isDropdownExpanded && isStickied) {\n applyBodyStyleClass(\"add\");\n } else {\n applyBodyStyleClass(\"remove\");\n }\n }, [isDropdownExpanded, isStickied]);\n\n useEffect(() => {\n setViewportHeight(window.innerHeight);\n const handleResize = () => {\n setViewportHeight(window.innerHeight);\n };\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n useEffect(() => {\n const callback = (entries: IntersectionObserverEntry[]) => {\n const [entry] = entries;\n setIsStickied(!entry.isIntersecting);\n };\n\n const observer = new IntersectionObserver(callback, {\n threshold: 1,\n rootMargin: `-${stickyOffset}px 0px 0px 0px`,\n });\n\n if (detectStickyRef.current) {\n observer.observe(detectStickyRef.current);\n }\n\n return () => observer.disconnect();\n }, [stickyOffset]);\n\n useEffect(() => {\n const adjustPadding = () => {\n const dropdown = navWrapperRef?.current;\n if (dropdown) {\n const dropdownRect = dropdown.getBoundingClientRect();\n const spaceToRight =\n document.body.clientWidth - dropdownRect.right;\n const spaceToLeft = dropdownRect.left;\n // Calculate the padding needed to balance the dropdown in the viewport\n const sidePadding = Math.max(spaceToRight, spaceToLeft);\n setDynamicMargin(sidePadding);\n }\n };\n adjustPadding();\n\n window.addEventListener(\"resize\", adjustPadding);\n\n return () => {\n window.removeEventListener(\"resize\", adjustPadding);\n };\n }, []);\n\n useEffect(() => {\n if (isDropdownExpanded) {\n listItemRefs.current[focusedIndex]?.focus();\n }\n }, [isDropdownExpanded, focusedIndex]);\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n\n const addStylesheetForDocumentBody = () => {\n /**\n * This stylesheet is to manipulate the <body>. We only add once\n */\n if (!document.getElementById(STYLESHEET_ID)) {\n const overlayStyleSheet = document.createElement(\"style\");\n overlayStyleSheet.id = STYLESHEET_ID;\n\n const documentWidth = document.documentElement.clientWidth;\n const windowWidth = window.innerWidth;\n const scrollBarWidth = windowWidth - documentWidth;\n\n overlayStyleSheet.innerHTML = `\n\t\t\t\t.${DROPDOWN_OPEN_CLASSNAME} {\n\t\t\t\t\toverflow: hidden;\n\t\t\t\t\tpadding-right: ${scrollBarWidth}px !important;\n\t\t\t\t\t-ms-overflow-style: none;\n\t\t\t\t\tscrollbar-width: none;\n\t\t\t\t}\n\n\t\t\t\t.${DROPDOWN_OPEN_CLASSNAME}::-webkit-scrollbar {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\t`;\n\n document.body.appendChild(overlayStyleSheet);\n }\n };\n\n const applyBodyStyleClass = (action: \"add\" | \"remove\") => {\n const isOverlayStyleClassApplied = document.body.classList.contains(\n DROPDOWN_OPEN_CLASSNAME\n );\n\n if (action === \"add\" && !isOverlayStyleClassApplied) {\n document.body.classList.add(DROPDOWN_OPEN_CLASSNAME);\n } else if (action === \"remove\" && isOverlayStyleClassApplied) {\n document.body.classList.remove(DROPDOWN_OPEN_CLASSNAME);\n }\n };\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n\n const handleToggleDropdown = () => {\n setIsDropdownExpanded((prev) => !prev);\n };\n\n const handleDismissBackdrop = () => {\n setIsDropdownExpanded(false);\n };\n\n const handleNavItemClick = (\n e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,\n item: LocalNavItemProps,\n index: number\n ) => {\n if (onNavItemSelect) {\n onNavItemSelect(e, item, index);\n }\n setIsDropdownExpanded(false);\n };\n\n const handleNavItemKeyDown = (\n e: React.KeyboardEvent<HTMLElement>,\n handleClick: (\n e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>\n ) => void\n ) => {\n const { key } = e;\n\n if (key === \"Enter\" || key === \" \") {\n e.preventDefault();\n handleClick(e);\n }\n };\n\n const handleNavSelectKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n const { key } = e;\n\n if (key === \"ArrowDown\") {\n e.preventDefault();\n if (!isDropdownExpanded) {\n setIsDropdownExpanded(true);\n }\n setFocusedIndex(0);\n } else if (key === \"ArrowUp\") {\n e.preventDefault();\n if (!isDropdownExpanded) {\n setIsDropdownExpanded(true);\n }\n setFocusedIndex(items.length - 1);\n } else if (key === \"Enter\" || key === \" \") {\n e.preventDefault();\n setIsDropdownExpanded(true);\n setFocusedIndex(0);\n } else if (key === \"Tab\") {\n setIsDropdownExpanded(false);\n } else if (key === \"Escape\") {\n setIsDropdownExpanded(false);\n }\n };\n\n const handleNavItemListKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n const { key } = e;\n\n if (key === \"ArrowDown\") {\n e.preventDefault();\n const nextIndex = (focusedIndex + 1) % items.length;\n setFocusedIndex(nextIndex);\n } else if (key === \"ArrowUp\") {\n e.preventDefault();\n const prevIndex =\n focusedIndex > 0 ? focusedIndex - 1 : items.length - 1;\n setFocusedIndex(prevIndex);\n } else if (key === \"Tab\") {\n setIsDropdownExpanded(false);\n } else if (key === \"Escape\") {\n setIsDropdownExpanded(false);\n dropdownRef.current?.focus();\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n\n const renderDropdownNavItem = ({\n handleClick,\n isSelected,\n item,\n renderItem,\n index,\n }: LocalNavDropdownItemComponentProps) => {\n const { id, title } = item;\n\n if (renderItem) {\n return (\n <li\n id={id}\n key={index}\n role=\"menuitem\"\n onClick={handleClick}\n onKeyDown={(e) => handleNavItemKeyDown(e, handleClick)}\n aria-current={isSelected ? true : undefined}\n tabIndex={-1}\n ref={(el) => {\n listItemRefs.current[index] = el;\n }}\n >\n {renderItem(item, {\n selected: isSelected,\n stickied: isStickied,\n })}\n </li>\n );\n }\n\n return (\n <NavItem\n id={id}\n key={index}\n role=\"menuitem\"\n $isSelected={isSelected && isStickied}\n onClick={handleClick}\n onKeyDown={(e) => handleNavItemKeyDown(e, handleClick)}\n aria-current={isSelected ? true : undefined}\n tabIndex={-1}\n ref={(el) => {\n listItemRefs.current[index] = el as HTMLLIElement;\n }}\n >\n {isSelected && <StyledTickIcon />}\n <NavItemLabel $isSelected={isSelected}>{title}</NavItemLabel>\n </NavItem>\n );\n };\n\n return (\n <>\n <span ref={detectStickyRef} data-testid={\"sticky-ref\"} />\n <NavWrapper\n $isStickied={isStickied}\n $sideMargin={dynamicMargin}\n $stickyOffset={stickyOffset}\n ref={navWrapperRef}\n id={id}\n data-testid={navTestId}\n className={className}\n >\n <NavSelect\n ref={dropdownRef}\n role=\"button\"\n onClick={handleToggleDropdown}\n onKeyDown={handleNavSelectKeyDown}\n data-testid={`${navTestId}-label`}\n $isDropdownExpanded={isDropdownExpanded}\n aria-haspopup=\"true\"\n aria-expanded={isDropdownExpanded}\n aria-controls={dropdownListId}\n tabIndex={0}\n >\n <Typography.BodyBL weight=\"semibold\">\n {labelText}\n </Typography.BodyBL>\n <NavSelectIcon $isDropdownExpanded={isDropdownExpanded} />\n </NavSelect>\n {isDropdownExpanded && (\n <NavItemList\n id={dropdownListId}\n role=\"menu\"\n onKeyDown={handleNavItemListKeyDown}\n data-testid={`${navTestId}-dropdown-list`}\n $viewportHeight={\n viewportHeight - dropdowntHeight - stickyOffset\n }\n >\n {items.map((item, i) =>\n renderDropdownNavItem({\n handleClick: (e) =>\n handleNavItemClick(e, item, i),\n isSelected: i === selectedItemIndex,\n item,\n renderItem,\n index: i,\n })\n )}\n </NavItemList>\n )}\n {isDropdownExpanded && isStickied && (\n <Backdrop onClick={handleDismissBackdrop} />\n )}\n </NavWrapper>\n </>\n );\n};\n\nexport const LocalNavDropdown = React.forwardRef(Component);\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\nconst STYLESHEET_ID = \"lifesg-ds-local-nav-dropdown-stylesheet\";\nconst DROPDOWN_OPEN_CLASSNAME = \"lifesg-ds-local-nav-dropdown-open\";\n"],"names":["LocalNavDropdown","React","forwardRef","defaultLabel","stickyOffset","onNavItemSelect","items","selectedItemIndex","id","testId","className","renderItem","ref","detectStickyRef","useRef","dropdownRef","navWrapperRef","listItemRefs","isStickied","setIsStickied","useState","isDropdownExpanded","setIsDropdownExpanded","viewportHeight","setViewportHeight","dropdowntHeight","setDropdownHeight","dynamicMargin","setDynamicMargin","focusedIndex","setFocusedIndex","navTestId","dropdownListId","useId","useImperativeHandle","current","labelText","title","useEffect","dropdownHeight","getBoundingClientRect","height","addStylesheetForDocumentBody","applyBodyStyleClass","window","innerHeight","handleResize","addEventListener","removeEventListener","observer","IntersectionObserver","entries","entry","isIntersecting","threshold","rootMargin","observe","disconnect","adjustPadding","dropdown","dropdownRect","spaceToRight","document","body","clientWidth","right","spaceToLeft","left","sidePadding","Math","max","_a","focus","getElementById","STYLESHEET_ID","overlayStyleSheet","createElement","documentWidth","documentElement","scrollBarWidth","innerWidth","innerHTML","DROPDOWN_OPEN_CLASSNAME","appendChild","action","isOverlayStyleClassApplied","classList","contains","remove","add","handleNavItemKeyDown","e","handleClick","key","preventDefault","_jsxs","_Fragment","children","_jsx","NavWrapper","$isStickied","$sideMargin","$stickyOffset","NavSelect","role","onClick","prev","onKeyDown","length","$isDropdownExpanded","tabIndex","Typography","BodyBL","weight","NavSelectIcon","NavItemList","nextIndex","prevIndex","$viewportHeight","map","item","i","isSelected","index","undefined","el","selected","stickied","NavItem","$isSelected","StyledTickIcon","NavItemLabel","renderDropdownNavItem","handleNavItemClick","Backdrop"],"mappings":"qnBAgBA,MA4WaA,EAAmBC,EAAMC,YA5WpB,EAEVC,eACAC,eAAe,EACfC,kBACAC,QACAC,oBACAC,KACA,cAAeC,EACfC,YACAC,cAEJC,KAKA,MAAMC,EAAkBC,EAAwB,MAC1CC,EAAcD,EAAuB,MACrCE,EAAgBF,EAAoB,MACpCG,EAAeH,EAAiC,KAC/CI,EAAYC,GAAiBC,GAAkB,IAC/CC,EAAoBC,GACvBF,GAAkB,IACfG,EAAgBC,GAAqBJ,EAAS,IAC9CK,EAAiBC,GAAqBN,EAAS,IAC/CO,EAAeC,GAAoBR,EAAS,IAC5CS,EAAcC,GAAmBV,EAAS,GAC3CW,EAAYtB,GAAU,qBACtBuB,EAAiBC,IAEvBC,EAAoBtB,GAAK,IAAMI,EAAcmB,UAE7C,MAAMC,EAC2B,iBAAtB7B,GACPA,GAAqB,GACrBW,EACMZ,EAAMC,GAAmB8B,MACzBlC,EAMVmC,GAAU,KACN,GAAIvB,EAAYoB,QAAS,CACrB,MAAMI,EACFxB,EAAYoB,QAAQK,wBAAwBC,OAChDf,EAAkBa,EACtB,IACD,IAEHD,GAAU,KACNI,IACO,KACHC,EAAoB,SAAS,IAElC,IAEHL,GAAU,KAEFK,EADAtB,GAAsBH,EACF,MAEA,SACxB,GACD,CAACG,EAAoBH,IAExBoB,GAAU,KACNd,EAAkBoB,OAAOC,aACzB,MAAMC,EAAe,KACjBtB,EAAkBoB,OAAOC,YAAY,EAGzC,OADAD,OAAOG,iBAAiB,SAAUD,GAC3B,IAAMF,OAAOI,oBAAoB,SAAUF,EAAa,GAChE,IAEHR,GAAU,KACN,MAKMW,EAAW,IAAIC,sBALHC,IACd,MAAOC,GAASD,EAChBhC,GAAeiC,EAAMC,eAAe,GAGY,CAChDC,UAAW,EACXC,WAAY,IAAInD,oBAOpB,OAJIS,EAAgBsB,SAChBc,EAASO,QAAQ3C,EAAgBsB,SAG9B,IAAMc,EAASQ,YAAY,GACnC,CAACrD,IAEJkC,GAAU,KACN,MAAMoB,EAAgB,KAClB,MAAMC,EAAW3C,aAAa,EAAbA,EAAemB,QAChC,GAAIwB,EAAU,CACV,MAAMC,EAAeD,EAASnB,wBACxBqB,EACFC,SAASC,KAAKC,YAAcJ,EAAaK,MACvCC,EAAcN,EAAaO,KAE3BC,EAAcC,KAAKC,IAAIT,EAAcK,GAC3CtC,EAAiBwC,EACrB,GAMJ,OAJAV,IAEAd,OAAOG,iBAAiB,SAAUW,GAE3B,KACHd,OAAOI,oBAAoB,SAAUU,EAAc,CACtD,GACF,IAEHpB,GAAU,WACFjB,IACkC,QAAlCkD,EAAAtD,EAAakB,QAAQN,UAAa,IAAA0C,GAAAA,EAAEC,QACxC,GACD,CAACnD,EAAoBQ,IAMxB,MAAMa,EAA+B,KAIjC,IAAKoB,SAASW,eAAeC,GAAgB,CACzC,MAAMC,EAAoBb,SAASc,cAAc,SACjDD,EAAkBnE,GAAKkE,EAEvB,MAAMG,EAAgBf,SAASgB,gBAAgBd,YAEzCe,EADcnC,OAAOoC,WACUH,EAErCF,EAAkBM,UAAY,cACnCC,8DAEeH,iHAKfG,sEAKKpB,SAASC,KAAKoB,YAAYR,EAC9B,GAGEhC,EAAuByC,IACzB,MAAMC,EAA6BvB,SAASC,KAAKuB,UAAUC,SACvDL,GAGW,QAAXE,GAAqBC,EAEH,WAAXD,GAAuBC,GAC9BvB,SAASC,KAAKuB,UAAUE,OAAON,GAF/BpB,SAASC,KAAKuB,UAAUG,IAAIP,EAGhC,EA0BEQ,EAAuB,CACzBC,EACAC,KAIA,MAAMC,IAAEA,GAAQF,EAEJ,UAARE,GAA2B,MAARA,IACnBF,EAAEG,iBACFF,EAAYD,GAChB,EAwGJ,OACII,EAAAC,EAAA,CAAAC,SAAA,CACIC,EAAA,OAAA,CAAMtF,IAAKC,EAAe,cAAe,eACzCkF,EAACI,EAAU,CAAAC,YACMlF,EAAUmF,YACV1E,EAAa2E,cACXlG,EACfQ,IAAKI,EACLR,GAAIA,EAAE,cACOuB,EACbrB,UAAWA,EAASuF,SAAA,CAEpBF,EAACQ,EAAS,CACN3F,IAAKG,EACLyF,KAAK,SACLC,QArJa,KACzBnF,GAAuBoF,IAAUA,GAAK,EAqJ1BC,UArHgBhB,IAC5B,MAAME,IAAEA,GAAQF,EAEJ,cAARE,GACAF,EAAEG,iBACGzE,GACDC,GAAsB,GAE1BQ,EAAgB,IACD,YAAR+D,GACPF,EAAEG,iBACGzE,GACDC,GAAsB,GAE1BQ,EAAgBxB,EAAMsG,OAAS,IAChB,UAARf,GAA2B,MAARA,GAC1BF,EAAEG,iBACFxE,GAAsB,GACtBQ,EAAgB,KACD,QAAR+D,GAEQ,WAARA,IADPvE,GAAsB,EAG1B,EA8F6C,cACpB,GAAGS,UAAiB8E,oBACZxF,EAAkB,gBACzB,OAAM,gBACLA,EAAkB,gBAClBW,EACf8E,SAAU,EAACb,SAAA,CAEXC,EAACa,EAAWC,OAAM,CAACC,OAAO,WAAUhB,SAC/B7D,IAEL8D,EAACgB,EAAa,CAAAL,oBAAsBxF,OAEvCA,GACG6E,EAACiB,EAAW,CACR3G,GAAIwB,EACJwE,KAAK,OACLG,UA5GchB,UAC9B,MAAME,IAAEA,GAAQF,EAEhB,GAAY,cAARE,EAAqB,CACrBF,EAAEG,iBACF,MAAMsB,GAAavF,EAAe,GAAKvB,EAAMsG,OAC7C9E,EAAgBsF,EACpB,MAAO,GAAY,YAARvB,EAAmB,CAC1BF,EAAEG,iBACF,MAAMuB,EACFxF,EAAe,EAAIA,EAAe,EAAIvB,EAAMsG,OAAS,EACzD9E,EAAgBuF,EACpB,KAAmB,QAARxB,EACPvE,GAAsB,GACP,WAARuE,IACPvE,GAAsB,GACH,QAAnBiD,EAAAxD,EAAYoB,eAAO,IAAAoC,GAAAA,EAAEC,QACzB,EA2FmD,cACtB,GAAGzC,kBAAyBuF,gBAErC/F,EAAiBE,EAAkBrB,EAAY6F,SAGlD3F,EAAMiH,KAAI,CAACC,EAAMC,IA1FR,GAC1B7B,cACA8B,aACAF,OACA7G,aACAgH,YAEA,MAAMnH,GAAEA,EAAE6B,MAAEA,GAAUmF,EAEtB,OAAI7G,EAEIuF,QACI1F,GAAIA,EAEJgG,KAAK,WACLC,QAASb,EACTe,UAAYhB,GAAMD,EAAqBC,EAAGC,oBAC5B8B,QAAoBE,EAClCd,UAAU,EACVlG,IAAMiH,IACF5G,EAAakB,QAAQwF,GAASE,CAAE,EACnC5B,SAEAtF,EAAW6G,EAAM,CACdM,SAAUJ,EACVK,SAAU7G,KAZTyG,GAmBb5B,EAACiC,EAAO,CACJxH,GAAIA,EAEJgG,KAAK,WAAUyB,YACFP,GAAcxG,EAC3BuF,QAASb,EACTe,UAAYhB,GAAMD,EAAqBC,EAAGC,GAAY,iBACxC8B,QAAoBE,EAClCd,UAAU,EACVlG,IAAMiH,IACF5G,EAAakB,QAAQwF,GAASE,CAAmB,YAGpDH,GAAcxB,EAACgC,EAAc,CAAA,GAC9BhC,EAACiC,EAAY,CAAAF,YAAcP,WAAarF,MAZnCsF,EAaC,EA4CMS,CAAsB,CAClBxC,YAAcD,GAvKf,EACvBA,EACA6B,EACAG,KAEItH,GACAA,EAAgBsF,EAAG6B,EAAMG,GAE7BrG,GAAsB,EAAM,EAgKA+G,CAAmB1C,EAAG6B,EAAMC,GAChCC,WAAYD,IAAMlH,EAClBiH,OACA7G,aACAgH,MAAOF,QAKtBpG,GAAsBH,GACnBgF,EAACoC,EAAQ,CAAC7B,QAtLI,KAC1BnF,GAAsB,EAAM,SAwLzB,IASLoD,EAAgB,0CAChBQ,EAA0B"}
|
|
1
|
+
{"version":3,"file":"local-nav-dropdown.js","sources":["../../../src/local-nav/local-nav-dropdown/local-nav-dropdown.tsx"],"sourcesContent":["import React, { useEffect, useImperativeHandle, useRef, useState } from \"react\";\nimport { Typography } from \"../../typography\";\nimport { useId } from \"../../util\";\nimport { LocalNavDropdownItemComponentProps } from \"../internal-types\";\nimport { LocalNavDropdownProps, LocalNavItemProps } from \"../types\";\nimport {\n Backdrop,\n LeftAddon,\n NavItem,\n NavItemLabel,\n NavItemList,\n NavSelect,\n NavSelectIcon,\n NavWrapper,\n RightAddon,\n StyledTickIcon,\n TitleContainer,\n} from \"./local-nav-dropdown.styles\";\n\nconst Component = (\n {\n defaultLabel,\n stickyOffset = 0,\n onNavItemSelect,\n items,\n selectedItemIndex,\n id,\n \"data-testid\": testId,\n className,\n renderItem,\n }: LocalNavDropdownProps,\n ref: React.Ref<HTMLElement>\n): JSX.Element => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const detectStickyRef = useRef<HTMLSpanElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const navWrapperRef = useRef<HTMLElement>(null);\n const listItemRefs = useRef<(HTMLLIElement | null)[]>([]);\n const [isStickied, setIsStickied] = useState<boolean>(false);\n const [isDropdownExpanded, setIsDropdownExpanded] =\n useState<boolean>(false);\n const [viewportHeight, setViewportHeight] = useState(0);\n const [dropdowntHeight, setDropdownHeight] = useState(0);\n const [dynamicMargin, setDynamicMargin] = useState(0);\n const [focusedIndex, setFocusedIndex] = useState(0);\n const navTestId = testId || \"local-nav-dropdown\";\n const dropdownListId = useId();\n\n useImperativeHandle(ref, () => navWrapperRef.current!);\n\n const labelText =\n typeof selectedItemIndex === \"number\" &&\n selectedItemIndex >= 0 &&\n isStickied\n ? items[selectedItemIndex].title\n : defaultLabel;\n\n // =============================================================================\n // EFFECTS, EVENT LISTENERS\n // ============================================================================\n\n useEffect(() => {\n if (dropdownRef.current) {\n const dropdownHeight =\n dropdownRef.current.getBoundingClientRect().height;\n setDropdownHeight(dropdownHeight);\n }\n }, []);\n\n useEffect(() => {\n addStylesheetForDocumentBody();\n return () => {\n applyBodyStyleClass(\"remove\");\n };\n }, []);\n\n useEffect(() => {\n if (isDropdownExpanded && isStickied) {\n applyBodyStyleClass(\"add\");\n } else {\n applyBodyStyleClass(\"remove\");\n }\n }, [isDropdownExpanded, isStickied]);\n\n useEffect(() => {\n setViewportHeight(window.innerHeight);\n const handleResize = () => {\n setViewportHeight(window.innerHeight);\n };\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n useEffect(() => {\n const callback = (entries: IntersectionObserverEntry[]) => {\n const [entry] = entries;\n setIsStickied(!entry.isIntersecting);\n };\n\n const observer = new IntersectionObserver(callback, {\n threshold: 1,\n rootMargin: `-${stickyOffset}px 0px 0px 0px`,\n });\n\n if (detectStickyRef.current) {\n observer.observe(detectStickyRef.current);\n }\n\n return () => observer.disconnect();\n }, [stickyOffset]);\n\n useEffect(() => {\n const adjustPadding = () => {\n const dropdown = navWrapperRef?.current;\n if (dropdown) {\n const dropdownRect = dropdown.getBoundingClientRect();\n const spaceToRight =\n document.body.clientWidth - dropdownRect.right;\n const spaceToLeft = dropdownRect.left;\n // Calculate the padding needed to balance the dropdown in the viewport\n const sidePadding = Math.max(spaceToRight, spaceToLeft);\n setDynamicMargin(sidePadding);\n }\n };\n adjustPadding();\n\n window.addEventListener(\"resize\", adjustPadding);\n\n return () => {\n window.removeEventListener(\"resize\", adjustPadding);\n };\n }, []);\n\n useEffect(() => {\n if (isDropdownExpanded) {\n listItemRefs.current[focusedIndex]?.focus();\n }\n }, [isDropdownExpanded, focusedIndex]);\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n\n const addStylesheetForDocumentBody = () => {\n /**\n * This stylesheet is to manipulate the <body>. We only add once\n */\n if (!document.getElementById(STYLESHEET_ID)) {\n const overlayStyleSheet = document.createElement(\"style\");\n overlayStyleSheet.id = STYLESHEET_ID;\n\n const documentWidth = document.documentElement.clientWidth;\n const windowWidth = window.innerWidth;\n const scrollBarWidth = windowWidth - documentWidth;\n\n overlayStyleSheet.innerHTML = `\n\t\t\t\t.${DROPDOWN_OPEN_CLASSNAME} {\n\t\t\t\t\toverflow: hidden;\n\t\t\t\t\tpadding-right: ${scrollBarWidth}px !important;\n\t\t\t\t\t-ms-overflow-style: none;\n\t\t\t\t\tscrollbar-width: none;\n\t\t\t\t}\n\n\t\t\t\t.${DROPDOWN_OPEN_CLASSNAME}::-webkit-scrollbar {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\t`;\n\n document.body.appendChild(overlayStyleSheet);\n }\n };\n\n const applyBodyStyleClass = (action: \"add\" | \"remove\") => {\n const isOverlayStyleClassApplied = document.body.classList.contains(\n DROPDOWN_OPEN_CLASSNAME\n );\n\n if (action === \"add\" && !isOverlayStyleClassApplied) {\n document.body.classList.add(DROPDOWN_OPEN_CLASSNAME);\n } else if (action === \"remove\" && isOverlayStyleClassApplied) {\n document.body.classList.remove(DROPDOWN_OPEN_CLASSNAME);\n }\n };\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n\n const handleToggleDropdown = () => {\n setIsDropdownExpanded((prev) => !prev);\n };\n\n const handleDismissBackdrop = () => {\n setIsDropdownExpanded(false);\n };\n\n const handleNavItemClick = (\n e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,\n item: LocalNavItemProps,\n index: number\n ) => {\n if (onNavItemSelect) {\n onNavItemSelect(e, item, index);\n }\n setIsDropdownExpanded(false);\n };\n\n const handleNavItemKeyDown = (\n e: React.KeyboardEvent<HTMLElement>,\n handleClick: (\n e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>\n ) => void\n ) => {\n const { key } = e;\n\n if (key === \"Enter\" || key === \" \") {\n e.preventDefault();\n handleClick(e);\n }\n };\n\n const handleNavSelectKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n const { key } = e;\n\n if (key === \"ArrowDown\") {\n e.preventDefault();\n if (!isDropdownExpanded) {\n setIsDropdownExpanded(true);\n }\n setFocusedIndex(0);\n } else if (key === \"ArrowUp\") {\n e.preventDefault();\n if (!isDropdownExpanded) {\n setIsDropdownExpanded(true);\n }\n setFocusedIndex(items.length - 1);\n } else if (key === \"Enter\" || key === \" \") {\n e.preventDefault();\n setIsDropdownExpanded(true);\n setFocusedIndex(0);\n } else if (key === \"Tab\") {\n setIsDropdownExpanded(false);\n } else if (key === \"Escape\") {\n setIsDropdownExpanded(false);\n }\n };\n\n const handleNavItemListKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n const { key } = e;\n\n if (key === \"ArrowDown\") {\n e.preventDefault();\n const nextIndex = (focusedIndex + 1) % items.length;\n setFocusedIndex(nextIndex);\n } else if (key === \"ArrowUp\") {\n e.preventDefault();\n const prevIndex =\n focusedIndex > 0 ? focusedIndex - 1 : items.length - 1;\n setFocusedIndex(prevIndex);\n } else if (key === \"Tab\") {\n setIsDropdownExpanded(false);\n } else if (key === \"Escape\") {\n setIsDropdownExpanded(false);\n dropdownRef.current?.focus();\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n\n const renderDropdownNavItem = ({\n handleClick,\n isSelected,\n item,\n renderItem,\n index,\n }: LocalNavDropdownItemComponentProps) => {\n const { id, title, titleAddon } = item;\n\n if (renderItem) {\n return (\n <li\n id={id}\n key={index}\n role=\"menuitem\"\n onClick={handleClick}\n onKeyDown={(e) => handleNavItemKeyDown(e, handleClick)}\n aria-current={isSelected ? true : undefined}\n tabIndex={-1}\n ref={(el) => {\n listItemRefs.current[index] = el;\n }}\n >\n {renderItem(item, {\n selected: isSelected,\n stickied: isStickied,\n })}\n </li>\n );\n }\n\n return (\n <NavItem\n id={id}\n key={index}\n role=\"menuitem\"\n $isSelected={isSelected && isStickied}\n onClick={handleClick}\n onKeyDown={(e) => handleNavItemKeyDown(e, handleClick)}\n aria-current={isSelected ? true : undefined}\n tabIndex={-1}\n ref={(el) => {\n listItemRefs.current[index] = el as HTMLLIElement;\n }}\n >\n {isSelected && (\n <LeftAddon>\n <StyledTickIcon />\n </LeftAddon>\n )}\n {titleAddon ? (\n <TitleContainer>\n {titleAddon.left && (\n <LeftAddon>{titleAddon.left}</LeftAddon>\n )}\n <NavItemLabel $isSelected={isSelected}>\n {title}\n </NavItemLabel>\n {titleAddon.right && (\n <RightAddon>{titleAddon.right}</RightAddon>\n )}\n </TitleContainer>\n ) : (\n <NavItemLabel $isSelected={isSelected}>\n {title}\n </NavItemLabel>\n )}\n </NavItem>\n );\n };\n\n return (\n <>\n <span ref={detectStickyRef} data-testid={\"sticky-ref\"} />\n <NavWrapper\n $isStickied={isStickied}\n $sideMargin={dynamicMargin}\n $stickyOffset={stickyOffset}\n ref={navWrapperRef}\n id={id}\n data-testid={navTestId}\n className={className}\n >\n <NavSelect\n ref={dropdownRef}\n role=\"button\"\n onClick={handleToggleDropdown}\n onKeyDown={handleNavSelectKeyDown}\n data-testid={`${navTestId}-label`}\n $isDropdownExpanded={isDropdownExpanded}\n aria-haspopup=\"true\"\n aria-expanded={isDropdownExpanded}\n aria-controls={dropdownListId}\n tabIndex={0}\n >\n <Typography.BodyBL weight=\"semibold\">\n {labelText}\n </Typography.BodyBL>\n <NavSelectIcon $isDropdownExpanded={isDropdownExpanded} />\n </NavSelect>\n {isDropdownExpanded && (\n <NavItemList\n id={dropdownListId}\n role=\"menu\"\n onKeyDown={handleNavItemListKeyDown}\n data-testid={`${navTestId}-dropdown-list`}\n $viewportHeight={\n viewportHeight - dropdowntHeight - stickyOffset\n }\n >\n {items.map((item, i) =>\n renderDropdownNavItem({\n handleClick: (e) =>\n handleNavItemClick(e, item, i),\n isSelected: i === selectedItemIndex,\n item,\n renderItem,\n index: i,\n })\n )}\n </NavItemList>\n )}\n {isDropdownExpanded && isStickied && (\n <Backdrop onClick={handleDismissBackdrop} />\n )}\n </NavWrapper>\n </>\n );\n};\n\nexport const LocalNavDropdown = React.forwardRef(Component);\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\nconst STYLESHEET_ID = \"lifesg-ds-local-nav-dropdown-stylesheet\";\nconst DROPDOWN_OPEN_CLASSNAME = \"lifesg-ds-local-nav-dropdown-open\";\n"],"names":["LocalNavDropdown","React","forwardRef","defaultLabel","stickyOffset","onNavItemSelect","items","selectedItemIndex","id","testId","className","renderItem","ref","detectStickyRef","useRef","dropdownRef","navWrapperRef","listItemRefs","isStickied","setIsStickied","useState","isDropdownExpanded","setIsDropdownExpanded","viewportHeight","setViewportHeight","dropdowntHeight","setDropdownHeight","dynamicMargin","setDynamicMargin","focusedIndex","setFocusedIndex","navTestId","dropdownListId","useId","useImperativeHandle","current","labelText","title","useEffect","dropdownHeight","getBoundingClientRect","height","addStylesheetForDocumentBody","applyBodyStyleClass","window","innerHeight","handleResize","addEventListener","removeEventListener","observer","IntersectionObserver","entries","entry","isIntersecting","threshold","rootMargin","observe","disconnect","adjustPadding","dropdown","dropdownRect","spaceToRight","document","body","clientWidth","right","spaceToLeft","left","sidePadding","Math","max","_a","focus","getElementById","STYLESHEET_ID","overlayStyleSheet","createElement","documentWidth","documentElement","scrollBarWidth","innerWidth","innerHTML","DROPDOWN_OPEN_CLASSNAME","appendChild","action","isOverlayStyleClassApplied","classList","contains","remove","add","handleNavItemKeyDown","e","handleClick","key","preventDefault","_jsxs","_Fragment","children","_jsx","NavWrapper","$isStickied","$sideMargin","$stickyOffset","NavSelect","role","onClick","prev","onKeyDown","length","$isDropdownExpanded","tabIndex","Typography","BodyBL","weight","NavSelectIcon","NavItemList","nextIndex","prevIndex","$viewportHeight","map","item","i","isSelected","index","titleAddon","undefined","el","selected","stickied","NavItem","$isSelected","LeftAddon","StyledTickIcon","TitleContainer","NavItemLabel","RightAddon","renderDropdownNavItem","handleNavItemClick","Backdrop"],"mappings":"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"}
|
|
@@ -28,6 +28,9 @@ export declare const NavSelect: import("styled-components/dist/types").IStyledCo
|
|
|
28
28
|
export declare const NavItem: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, "$isSelected"> & NavItemStyleProps, never> & Partial<Pick<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, "$isSelected"> & NavItemStyleProps, never>>> & string;
|
|
29
29
|
export declare const NavItemList: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLUListElement>, HTMLUListElement>, "$viewportHeight"> & NavItemListStyleProps, never> & Partial<Pick<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLUListElement>, HTMLUListElement>, "$viewportHeight"> & NavItemListStyleProps, never>>> & string;
|
|
30
30
|
export declare const NavItemLabel: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "$isSelected"> & NavItemStyleProps, never> & Partial<Pick<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "$isSelected"> & NavItemStyleProps, never>>> & string;
|
|
31
|
+
export declare const TitleContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>>> & string;
|
|
32
|
+
export declare const LeftAddon: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>>> & string;
|
|
33
|
+
export declare const RightAddon: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>>> & string;
|
|
31
34
|
export declare const StyledTickIcon: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<Omit<import("react").SVGProps<SVGSVGElement>, "ref"> & {
|
|
32
35
|
ref?: ((instance: SVGSVGElement | null) => void) | import("react").RefObject<SVGSVGElement> | null | undefined;
|
|
33
36
|
}, never> & Partial<Pick<Omit<import("react").SVGProps<SVGSVGElement>, "ref"> & {
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import{ChevronDownIcon as i}from"@lifesg/react-icons/chevron-down";import{TickIcon as
|
|
1
|
+
import{ChevronDownIcon as i}from"@lifesg/react-icons/chevron-down";import{TickIcon as e}from"@lifesg/react-icons/tick";import t,{css as o}from"styled-components";import{Colour as r,Motion as n,Spacing as s,Border as a,Radius as d,Font as l}from"../../theme/index.js";const $=t(i)`
|
|
2
2
|
color: ${r.icon};
|
|
3
|
-
transition: transform ${
|
|
3
|
+
transition: transform ${n["duration-250"]} ${n["ease-default"]};
|
|
4
4
|
transform: rotate(${i=>i.$isDropdownExpanded?180:0}deg);
|
|
5
|
-
`,
|
|
5
|
+
`,p=t.div`
|
|
6
6
|
cursor: pointer;
|
|
7
7
|
background: ${r.bg};
|
|
8
|
-
padding: ${
|
|
8
|
+
padding: ${s["spacing-12"]} ${s["spacing-16"]};
|
|
9
9
|
overflow: hidden;
|
|
10
10
|
box-shadow: 0 0 ${a["width-010"]} ${a["width-010"]}
|
|
11
11
|
${r.border};
|
|
12
12
|
border-radius: ${d.sm};
|
|
13
|
-
${i=>i.$isDropdownExpanded&&
|
|
13
|
+
${i=>i.$isDropdownExpanded&&o`
|
|
14
14
|
border-bottom-left-radius: ${d.none};
|
|
15
15
|
border-bottom-right-radius: ${d.none};
|
|
16
16
|
`}
|
|
17
17
|
display: flex;
|
|
18
18
|
justify-content: space-between;
|
|
19
19
|
align-items: center;
|
|
20
|
-
transition: all ${
|
|
20
|
+
transition: all ${n["duration-250"]} ${n["ease-default"]};
|
|
21
21
|
transition-property: background, border-radius, box-shadow, transform;
|
|
22
22
|
|
|
23
23
|
&:focus-visible {
|
|
@@ -25,13 +25,13 @@ import{ChevronDownIcon as i}from"@lifesg/react-icons/chevron-down";import{TickIc
|
|
|
25
25
|
outline-offset: 2px;
|
|
26
26
|
border-radius: ${d.sm};
|
|
27
27
|
}
|
|
28
|
-
`,
|
|
29
|
-
padding: ${i=>i.$isSelected?
|
|
30
|
-
${
|
|
31
|
-
${
|
|
32
|
-
`:
|
|
33
|
-
${
|
|
34
|
-
${
|
|
28
|
+
`,c=t.li`
|
|
29
|
+
padding: ${i=>i.$isSelected?o`
|
|
30
|
+
${s["spacing-12"]} ${s["spacing-8"]}
|
|
31
|
+
${s["spacing-12"]} 0
|
|
32
|
+
`:o`
|
|
33
|
+
${s["spacing-12"]} ${s["spacing-8"]}
|
|
34
|
+
${s["spacing-12"]} ${s["spacing-32"]}
|
|
35
35
|
`};
|
|
36
36
|
background: ${i=>i.$isSelected?r["bg-primary-subtlest"]:r.bg};
|
|
37
37
|
/* Ensures that the tick mark is positioned relative to the selected item */
|
|
@@ -46,10 +46,10 @@ import{ChevronDownIcon as i}from"@lifesg/react-icons/chevron-down";import{TickIc
|
|
|
46
46
|
border-radius: ${d.sm};
|
|
47
47
|
}
|
|
48
48
|
`,g=t.ul`
|
|
49
|
-
transition: all ${
|
|
49
|
+
transition: all ${n["duration-250"]} ${n["ease-default"]};
|
|
50
50
|
transform-origin: top;
|
|
51
51
|
list-style-type: none;
|
|
52
|
-
padding: 0 ${
|
|
52
|
+
padding: 0 ${s["spacing-8"]};
|
|
53
53
|
margin: 0;
|
|
54
54
|
background: ${r.bg};
|
|
55
55
|
cursor: pointer;
|
|
@@ -61,13 +61,27 @@ import{ChevronDownIcon as i}from"@lifesg/react-icons/chevron-down";import{TickIc
|
|
|
61
61
|
overflow-y: auto;
|
|
62
62
|
/* Set a max height for the dropdown list */
|
|
63
63
|
max-height: ${i=>i.$viewportHeight}px;
|
|
64
|
-
`,
|
|
65
|
-
${
|
|
64
|
+
`,m=t.div`
|
|
65
|
+
${l["body-baseline-regular"]}
|
|
66
66
|
color: ${i=>i.$isSelected?r["text-selected"]:r.text};
|
|
67
|
-
`,
|
|
67
|
+
`,b=t.span`
|
|
68
|
+
display: flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
gap: ${s["spacing-8"]};
|
|
71
|
+
flex: 1;
|
|
72
|
+
`,f=t.span`
|
|
73
|
+
display: inline-flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
align-self: flex-start;
|
|
76
|
+
min-height: ${l.Spec["body-lh-baseline"]};
|
|
77
|
+
`,u=t.span`
|
|
78
|
+
display: inline-flex;
|
|
79
|
+
align-items: center;
|
|
80
|
+
margin-left: auto;
|
|
81
|
+
`,x=t(e)`
|
|
68
82
|
color: ${r["icon-selected"]};
|
|
69
|
-
margin: 0 ${
|
|
70
|
-
`,
|
|
83
|
+
margin: 0 ${s["spacing-8"]};
|
|
84
|
+
`,h=t.div`
|
|
71
85
|
position: fixed;
|
|
72
86
|
top: 0;
|
|
73
87
|
right: 0;
|
|
@@ -75,26 +89,26 @@ import{ChevronDownIcon as i}from"@lifesg/react-icons/chevron-down";import{TickIc
|
|
|
75
89
|
bottom: 0;
|
|
76
90
|
background-color: ${r["overlay-strong"]};
|
|
77
91
|
z-index: -1;
|
|
78
|
-
`,
|
|
92
|
+
`,y=t.nav`
|
|
79
93
|
display: block;
|
|
80
94
|
position: sticky;
|
|
81
95
|
top: ${i=>i.$stickyOffset}px;
|
|
82
96
|
width: 100%;
|
|
83
97
|
z-index: 10;
|
|
84
98
|
|
|
85
|
-
${({$isStickied:i,$sideMargin:
|
|
86
|
-
${
|
|
87
|
-
${
|
|
88
|
-
padding: ${
|
|
99
|
+
${({$isStickied:i,$sideMargin:e})=>i&&o`
|
|
100
|
+
${p} {
|
|
101
|
+
${e&&`margin: 0 -${e}px;`}
|
|
102
|
+
padding: ${s["spacing-12"]} ${s["spacing-16"]};
|
|
89
103
|
border-radius: ${d.none};
|
|
90
104
|
}
|
|
91
105
|
|
|
92
106
|
${g} {
|
|
93
|
-
${
|
|
94
|
-
${
|
|
107
|
+
${e&&`margin-left: -${e}px;`}
|
|
108
|
+
${e&&`margin-right: -${e}px;`}
|
|
95
109
|
border-radius-bottom-left: ${d.sm};
|
|
96
110
|
border-radius-bottom-right: ${d.sm};
|
|
97
111
|
}
|
|
98
112
|
`}
|
|
99
|
-
`;export{
|
|
113
|
+
`;export{h as Backdrop,f as LeftAddon,c as NavItem,m as NavItemLabel,g as NavItemList,p as NavSelect,$ as NavSelectIcon,y as NavWrapper,u as RightAddon,x as StyledTickIcon,b as TitleContainer};
|
|
100
114
|
//# sourceMappingURL=local-nav-dropdown.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-nav-dropdown.styles.js","sources":["../../../src/local-nav/local-nav-dropdown/local-nav-dropdown.styles.tsx"],"sourcesContent":["import { ChevronDownIcon } from \"@lifesg/react-icons/chevron-down\";\nimport { TickIcon } from \"@lifesg/react-icons/tick\";\nimport styled, { css } from \"styled-components\";\nimport { Border, Colour, Font, Motion, Radius, Spacing } from \"../../theme\";\n\n// =============================================================================\n// STYLE INTERFACES, transient props are denoted with $\n// See more https://styled-components.com/docs/api#transient-props\n// =============================================================================\ninterface DropdownNavStyleProps {\n $isStickied?: boolean;\n $stickyOffset: number;\n $sideMargin?: number;\n}\n\ninterface NavItemListStyleProps {\n $viewportHeight?: number;\n}\n\ninterface NavItemStyleProps {\n $isSelected?: boolean;\n}\ninterface DropdownExpandedProps {\n $isDropdownExpanded: boolean;\n}\n\ninterface NavIconStyleProps extends DropdownExpandedProps {}\ninterface NavLabelStyleProps extends DropdownExpandedProps {}\n\n// =============================================================================\n// STYLING\n// =============================================================================\n\n// -----------------------------------------------------------------------------\n// NAV SELECT\n// -----------------------------------------------------------------------------\n\nexport const NavSelectIcon = styled(ChevronDownIcon)<NavIconStyleProps>`\n color: ${Colour[\"icon\"]};\n transition: transform ${Motion[\"duration-250\"]} ${Motion[\"ease-default\"]};\n transform: rotate(${(props) => (props.$isDropdownExpanded ? 180 : 0)}deg);\n`;\n\nexport const NavSelect = styled.div<NavLabelStyleProps>`\n cursor: pointer;\n background: ${Colour[\"bg\"]};\n padding: ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-16\"]};\n overflow: hidden;\n box-shadow: 0 0 ${Border[\"width-010\"]} ${Border[\"width-010\"]}\n ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n ${(props) =>\n props.$isDropdownExpanded &&\n css`\n border-bottom-left-radius: ${Radius[\"none\"]};\n border-bottom-right-radius: ${Radius[\"none\"]};\n `}\n display: flex;\n justify-content: space-between;\n align-items: center;\n transition: all ${Motion[\"duration-250\"]} ${Motion[\"ease-default\"]};\n transition-property: background, border-radius, box-shadow, transform;\n\n &:focus-visible {\n outline: 2px solid ${Colour[\"focus-ring\"]};\n outline-offset: 2px;\n border-radius: ${Radius[\"sm\"]};\n }\n`;\n\n// -----------------------------------------------------------------------------\n// NAV ITEMS\n// -----------------------------------------------------------------------------\n\nexport const NavItem = styled.li<NavItemStyleProps>`\n padding: ${(props) =>\n props.$isSelected\n ? css`\n ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-8\"]} \n ${Spacing[\"spacing-12\"]} 0\n `\n : css`\n ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-8\"]}\n ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-32\"]}\n `};\n background: ${(props) =>\n props.$isSelected ? Colour[\"bg-primary-subtlest\"] : Colour[\"bg\"]};\n /* Ensures that the tick mark is positioned relative to the selected item */\n position: relative;\n display: flex;\n /* Vertically align text and tick */\n align-items: center;\n\n &:focus-visible {\n outline: 2px solid ${Colour[\"focus-ring\"]};\n outline-offset: 0px;\n border-radius: ${Radius[\"sm\"]};\n }\n`;\n\nexport const NavItemList = styled.ul<NavItemListStyleProps>`\n transition: all ${Motion[\"duration-250\"]} ${Motion[\"ease-default\"]};\n transform-origin: top;\n list-style-type: none;\n padding: 0 ${Spacing[\"spacing-8\"]};\n margin: 0;\n background: ${Colour[\"bg\"]};\n cursor: pointer;\n box-shadow: 0 0 ${Border[\"width-010\"]} ${Border[\"width-010\"]}\n ${Colour[\"border\"]};\n border-bottom-right-radius: ${Radius[\"sm\"]};\n border-bottom-left-radius: ${Radius[\"sm\"]};\n /* Enables vertical scrolling */\n overflow-y: auto;\n /* Set a max height for the dropdown list */\n max-height: ${(props) => props.$viewportHeight}px;\n`;\n\nexport const NavItemLabel = styled.div<NavItemStyleProps>`\n ${Font[\"body-baseline-regular\"]}\n color: ${(props) =>\n props.$isSelected ? Colour[\"text-selected\"] : Colour[\"text\"]};\n`;\n\nexport const StyledTickIcon = styled(TickIcon)`\n color: ${Colour[\"icon-selected\"]};\n margin: 0 ${Spacing[\"spacing-8\"]};\n`;\n\n// -----------------------------------------------------------------------------\n// MAIN\n// -----------------------------------------------------------------------------\n\nexport const Backdrop = styled.div`\n position: fixed;\n top: 0;\n right: 0;\n left: 0;\n bottom: 0;\n background-color: ${Colour[\"overlay-strong\"]};\n z-index: -1;\n`;\n\nexport const NavWrapper = styled.nav<DropdownNavStyleProps>`\n display: block;\n position: sticky;\n top: ${(props) => props.$stickyOffset}px;\n width: 100%;\n z-index: 10;\n\n ${({ $isStickied, $sideMargin }) =>\n $isStickied &&\n css`\n ${NavSelect} {\n ${$sideMargin && `margin: 0 -${$sideMargin}px;`}\n padding: ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-16\"]};\n border-radius: ${Radius[\"none\"]};\n }\n\n ${NavItemList} {\n ${$sideMargin && `margin-left: -${$sideMargin}px;`}\n ${$sideMargin && `margin-right: -${$sideMargin}px;`}\n border-radius-bottom-left: ${Radius.sm};\n border-radius-bottom-right: ${Radius.sm};\n }\n `}\n`;\n"],"names":["NavSelectIcon","styled","ChevronDownIcon","Colour","Motion","props","$isDropdownExpanded","NavSelect","div","Spacing","Border","Radius","css","NavItem","li","$isSelected","NavItemList","ul","$viewportHeight","NavItemLabel","Font","StyledTickIcon","TickIcon","Backdrop","NavWrapper","nav","$stickyOffset","$isStickied","$sideMargin","sm"],"mappings":"iRAqCaA,EAAgBC,EAAOC,EAAmC;aAC1DC,EAAa;4BACEC,EAAO,mBAAmBA,EAAO;wBACpCC,GAAWA,EAAMC,oBAAsB,IAAM;EAGzDC,EAAYN,EAAOO,GAAuB;;kBAErCL,EAAW;eACdM,EAAQ,iBAAiBA,EAAQ;;sBAE1BC,EAAO,gBAAgBA,EAAO;UAC1CP,EAAe;qBACJQ,EAAW;MACzBN,GACCA,EAAMC,qBACNM,CAAG;yCAC8BD,EAAa;0CACZA,EAAa;;;;;sBAKjCP,EAAO,mBAAmBA,EAAO;;;;6BAI1BD,EAAO;;yBAEXQ,EAAW;;EAQvBE,EAAUZ,EAAOa,EAAqB;eACnCT,GACRA,EAAMU,YACAH,CAAG;oBACGH,EAAQ,iBAAiBA,EAAQ;oBACjCA,EAAQ;gBAEdG,CAAG;oBACGH,EAAQ,iBAAiBA,EAAQ;oBACjCA,EAAQ,iBAAiBA,EAAQ;;kBAElCJ,GACXA,EAAMU,YAAcZ,EAAO,uBAAyBA,EAAW;;;;;;;;6BAQ1CA,EAAO;;yBAEXQ,EAAW;;EAIvBK,EAAcf,EAAOgB,EAAyB;sBACrCb,EAAO,mBAAmBA,EAAO;;;iBAGtCK,EAAQ;;kBAEPN,EAAW;;sBAEPO,EAAO,gBAAgBA,EAAO;UAC1CP,EAAe;kCACSQ,EAAW;iCACZA,EAAW;;;;kBAIzBN,GAAUA,EAAMa;EAGtBC,EAAelB,EAAOO,GAAsB;MACnDY,EAAK;aACGf,GACNA,EAAMU,YAAcZ,EAAO,iBAAmBA,EAAa;EAGtDkB,EAAiBpB,EAAOqB,EAAS;
|
|
1
|
+
{"version":3,"file":"local-nav-dropdown.styles.js","sources":["../../../src/local-nav/local-nav-dropdown/local-nav-dropdown.styles.tsx"],"sourcesContent":["import { ChevronDownIcon } from \"@lifesg/react-icons/chevron-down\";\nimport { TickIcon } from \"@lifesg/react-icons/tick\";\nimport styled, { css } from \"styled-components\";\nimport { Border, Colour, Font, Motion, Radius, Spacing } from \"../../theme\";\n\n// =============================================================================\n// STYLE INTERFACES, transient props are denoted with $\n// See more https://styled-components.com/docs/api#transient-props\n// =============================================================================\ninterface DropdownNavStyleProps {\n $isStickied?: boolean;\n $stickyOffset: number;\n $sideMargin?: number;\n}\n\ninterface NavItemListStyleProps {\n $viewportHeight?: number;\n}\n\ninterface NavItemStyleProps {\n $isSelected?: boolean;\n}\ninterface DropdownExpandedProps {\n $isDropdownExpanded: boolean;\n}\n\ninterface NavIconStyleProps extends DropdownExpandedProps {}\ninterface NavLabelStyleProps extends DropdownExpandedProps {}\n\n// =============================================================================\n// STYLING\n// =============================================================================\n\n// -----------------------------------------------------------------------------\n// NAV SELECT\n// -----------------------------------------------------------------------------\n\nexport const NavSelectIcon = styled(ChevronDownIcon)<NavIconStyleProps>`\n color: ${Colour[\"icon\"]};\n transition: transform ${Motion[\"duration-250\"]} ${Motion[\"ease-default\"]};\n transform: rotate(${(props) => (props.$isDropdownExpanded ? 180 : 0)}deg);\n`;\n\nexport const NavSelect = styled.div<NavLabelStyleProps>`\n cursor: pointer;\n background: ${Colour[\"bg\"]};\n padding: ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-16\"]};\n overflow: hidden;\n box-shadow: 0 0 ${Border[\"width-010\"]} ${Border[\"width-010\"]}\n ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n ${(props) =>\n props.$isDropdownExpanded &&\n css`\n border-bottom-left-radius: ${Radius[\"none\"]};\n border-bottom-right-radius: ${Radius[\"none\"]};\n `}\n display: flex;\n justify-content: space-between;\n align-items: center;\n transition: all ${Motion[\"duration-250\"]} ${Motion[\"ease-default\"]};\n transition-property: background, border-radius, box-shadow, transform;\n\n &:focus-visible {\n outline: 2px solid ${Colour[\"focus-ring\"]};\n outline-offset: 2px;\n border-radius: ${Radius[\"sm\"]};\n }\n`;\n\n// -----------------------------------------------------------------------------\n// NAV ITEMS\n// -----------------------------------------------------------------------------\n\nexport const NavItem = styled.li<NavItemStyleProps>`\n padding: ${(props) =>\n props.$isSelected\n ? css`\n ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-8\"]} \n ${Spacing[\"spacing-12\"]} 0\n `\n : css`\n ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-8\"]}\n ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-32\"]}\n `};\n background: ${(props) =>\n props.$isSelected ? Colour[\"bg-primary-subtlest\"] : Colour[\"bg\"]};\n /* Ensures that the tick mark is positioned relative to the selected item */\n position: relative;\n display: flex;\n /* Vertically align text and tick */\n align-items: center;\n\n &:focus-visible {\n outline: 2px solid ${Colour[\"focus-ring\"]};\n outline-offset: 0px;\n border-radius: ${Radius[\"sm\"]};\n }\n`;\n\nexport const NavItemList = styled.ul<NavItemListStyleProps>`\n transition: all ${Motion[\"duration-250\"]} ${Motion[\"ease-default\"]};\n transform-origin: top;\n list-style-type: none;\n padding: 0 ${Spacing[\"spacing-8\"]};\n margin: 0;\n background: ${Colour[\"bg\"]};\n cursor: pointer;\n box-shadow: 0 0 ${Border[\"width-010\"]} ${Border[\"width-010\"]}\n ${Colour[\"border\"]};\n border-bottom-right-radius: ${Radius[\"sm\"]};\n border-bottom-left-radius: ${Radius[\"sm\"]};\n /* Enables vertical scrolling */\n overflow-y: auto;\n /* Set a max height for the dropdown list */\n max-height: ${(props) => props.$viewportHeight}px;\n`;\n\nexport const NavItemLabel = styled.div<NavItemStyleProps>`\n ${Font[\"body-baseline-regular\"]}\n color: ${(props) =>\n props.$isSelected ? Colour[\"text-selected\"] : Colour[\"text\"]};\n`;\n\nexport const TitleContainer = styled.span`\n display: flex;\n align-items: center;\n gap: ${Spacing[\"spacing-8\"]};\n flex: 1;\n`;\n\n/* Keeps the left addon aligned with the first line when the title wraps. */\nexport const LeftAddon = styled.span`\n display: inline-flex;\n align-items: center;\n align-self: flex-start;\n min-height: ${Font.Spec[\"body-lh-baseline\"]};\n`;\n\n/* Flushed right; stays vertically centred against the (possibly wrapped) title. */\nexport const RightAddon = styled.span`\n display: inline-flex;\n align-items: center;\n margin-left: auto;\n`;\n\nexport const StyledTickIcon = styled(TickIcon)`\n color: ${Colour[\"icon-selected\"]};\n margin: 0 ${Spacing[\"spacing-8\"]};\n`;\n\n// -----------------------------------------------------------------------------\n// MAIN\n// -----------------------------------------------------------------------------\n\nexport const Backdrop = styled.div`\n position: fixed;\n top: 0;\n right: 0;\n left: 0;\n bottom: 0;\n background-color: ${Colour[\"overlay-strong\"]};\n z-index: -1;\n`;\n\nexport const NavWrapper = styled.nav<DropdownNavStyleProps>`\n display: block;\n position: sticky;\n top: ${(props) => props.$stickyOffset}px;\n width: 100%;\n z-index: 10;\n\n ${({ $isStickied, $sideMargin }) =>\n $isStickied &&\n css`\n ${NavSelect} {\n ${$sideMargin && `margin: 0 -${$sideMargin}px;`}\n padding: ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-16\"]};\n border-radius: ${Radius[\"none\"]};\n }\n\n ${NavItemList} {\n ${$sideMargin && `margin-left: -${$sideMargin}px;`}\n ${$sideMargin && `margin-right: -${$sideMargin}px;`}\n border-radius-bottom-left: ${Radius.sm};\n border-radius-bottom-right: ${Radius.sm};\n }\n `}\n`;\n"],"names":["NavSelectIcon","styled","ChevronDownIcon","Colour","Motion","props","$isDropdownExpanded","NavSelect","div","Spacing","Border","Radius","css","NavItem","li","$isSelected","NavItemList","ul","$viewportHeight","NavItemLabel","Font","TitleContainer","span","LeftAddon","Spec","RightAddon","StyledTickIcon","TickIcon","Backdrop","NavWrapper","nav","$stickyOffset","$isStickied","$sideMargin","sm"],"mappings":"iRAqCaA,EAAgBC,EAAOC,EAAmC;aAC1DC,EAAa;4BACEC,EAAO,mBAAmBA,EAAO;wBACpCC,GAAWA,EAAMC,oBAAsB,IAAM;EAGzDC,EAAYN,EAAOO,GAAuB;;kBAErCL,EAAW;eACdM,EAAQ,iBAAiBA,EAAQ;;sBAE1BC,EAAO,gBAAgBA,EAAO;UAC1CP,EAAe;qBACJQ,EAAW;MACzBN,GACCA,EAAMC,qBACNM,CAAG;yCAC8BD,EAAa;0CACZA,EAAa;;;;;sBAKjCP,EAAO,mBAAmBA,EAAO;;;;6BAI1BD,EAAO;;yBAEXQ,EAAW;;EAQvBE,EAAUZ,EAAOa,EAAqB;eACnCT,GACRA,EAAMU,YACAH,CAAG;oBACGH,EAAQ,iBAAiBA,EAAQ;oBACjCA,EAAQ;gBAEdG,CAAG;oBACGH,EAAQ,iBAAiBA,EAAQ;oBACjCA,EAAQ,iBAAiBA,EAAQ;;kBAElCJ,GACXA,EAAMU,YAAcZ,EAAO,uBAAyBA,EAAW;;;;;;;;6BAQ1CA,EAAO;;yBAEXQ,EAAW;;EAIvBK,EAAcf,EAAOgB,EAAyB;sBACrCb,EAAO,mBAAmBA,EAAO;;;iBAGtCK,EAAQ;;kBAEPN,EAAW;;sBAEPO,EAAO,gBAAgBA,EAAO;UAC1CP,EAAe;kCACSQ,EAAW;iCACZA,EAAW;;;;kBAIzBN,GAAUA,EAAMa;EAGtBC,EAAelB,EAAOO,GAAsB;MACnDY,EAAK;aACGf,GACNA,EAAMU,YAAcZ,EAAO,iBAAmBA,EAAa;EAGtDkB,EAAiBpB,EAAOqB,IAAI;;;WAG9Bb,EAAQ;;EAKNc,EAAYtB,EAAOqB,IAAI;;;;kBAIlBF,EAAKI,KAAK;EAIfC,EAAaxB,EAAOqB,IAAI;;;;EAMxBI,EAAiBzB,EAAO0B,EAAS;aACjCxB,EAAO;gBACJM,EAAQ;EAOXmB,EAAW3B,EAAOO,GAAG;;;;;;wBAMVL,EAAO;;EAIlB0B,EAAa5B,EAAO6B,GAA0B;;;WAG/CzB,GAAUA,EAAM0B;;;;MAItB,EAAGC,cAAaC,iBACdD,GACApB,CAAG;cACGL;kBACI0B,GAAe,cAAcA;2BACpBxB,EAAQ,iBAAiBA,EAAQ;iCAC3BE,EAAa;;;cAGhCK;kBACIiB,GAAe,iBAAiBA;kBAChCA,GAAe,kBAAkBA;6CACNtB,EAAOuB;8CACNvB,EAAOuB;;;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as e}from"react/jsx-runtime";import
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import r from"react";import{Nav as i,NavItem as n,NavItemContent as d,TextLabel as l,TitleContainer as c,LeftAddon as a,RightAddon as o}from"./local-nav-menu.styles.js";const m=r.forwardRef((({onNavItemSelect:r,items:m,selectedItemIndex:s,id:h,"data-testid":f,className:u,renderItem:I},p)=>e(i,{ref:p,id:h,className:u,"data-testid":f||"local-nav-menu",children:m.map(((i,m)=>(({handleClick:r,isSelected:i,item:m,renderItem:s,index:h})=>{const{id:f,title:u,titleAddon:I}=m;return e(n,{id:f,$isSelected:i,children:e(d,{role:"link",onClick:r,onKeyDown:e=>((e,t)=>{const{key:r}=e;"Enter"!==r&&" "!==r||(e.preventDefault(),t(e))})(e,r),tabIndex:0,"aria-current":!!i||void 0,children:(()=>{if(s)return s(m,{selected:i});const r=e(l,{weight:i?"semibold":"regular",children:u});return I?t(c,{children:[I.left&&e(a,{children:I.left}),r,I.right&&e(o,{children:I.right})]}):r})()})},h)})({handleClick:e=>r(e,i,m),isSelected:m===s,item:i,renderItem:I,index:m})))})));export{m as LocalNavMenu};
|
|
2
2
|
//# sourceMappingURL=local-nav-menu.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-nav-menu.js","sources":["../../../src/local-nav/local-nav-menu/local-nav-menu.tsx"],"sourcesContent":["import React from \"react\";\nimport { LocalNavMenuItemComponentProps } from \"../internal-types\";\nimport { LocalNavMenuProps } from \"../types\";\nimport {\n Nav,\n NavItem,\n NavItemContent,\n TextLabel,\n} from \"./local-nav-menu.styles\";\n\n/**\n * A sidebar navigation element. The currently visible section will be highlighted.\n *\n * This component should be placed inside a container that aligns it to the side.\n * The container can also have `position: sticky` in order to make it a sticky sidebar.\n */\nconst Component = (\n {\n onNavItemSelect,\n items,\n selectedItemIndex,\n id,\n \"data-testid\": dataTestId,\n className,\n renderItem,\n }: LocalNavMenuProps,\n ref: React.Ref<HTMLUListElement>\n): JSX.Element => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const localNavMenuId = dataTestId || \"local-nav-menu\";\n\n // =============================================================================\n // EVENT HANDLERS\n // ============================================================================\n const handleNavItemKeyDown = (\n e: React.KeyboardEvent<HTMLElement>,\n handleClick: (\n e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>\n ) => void\n ) => {\n const { key } = e;\n\n if (key === \"Enter\" || key === \" \") {\n e.preventDefault();\n handleClick(e);\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n\n const renderLocalNavItem = ({\n handleClick,\n isSelected,\n item,\n renderItem,\n index,\n }: LocalNavMenuItemComponentProps) => {\n const { id, title } = item;\n\n const renderTitle = () => {\n if (renderItem) {\n return renderItem(item, { selected: isSelected });\n }\n
|
|
1
|
+
{"version":3,"file":"local-nav-menu.js","sources":["../../../src/local-nav/local-nav-menu/local-nav-menu.tsx"],"sourcesContent":["import React from \"react\";\nimport { LocalNavMenuItemComponentProps } from \"../internal-types\";\nimport { LocalNavMenuProps } from \"../types\";\nimport {\n LeftAddon,\n Nav,\n NavItem,\n NavItemContent,\n RightAddon,\n TextLabel,\n TitleContainer,\n} from \"./local-nav-menu.styles\";\n\n/**\n * A sidebar navigation element. The currently visible section will be highlighted.\n *\n * This component should be placed inside a container that aligns it to the side.\n * The container can also have `position: sticky` in order to make it a sticky sidebar.\n */\nconst Component = (\n {\n onNavItemSelect,\n items,\n selectedItemIndex,\n id,\n \"data-testid\": dataTestId,\n className,\n renderItem,\n }: LocalNavMenuProps,\n ref: React.Ref<HTMLUListElement>\n): JSX.Element => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const localNavMenuId = dataTestId || \"local-nav-menu\";\n\n // =============================================================================\n // EVENT HANDLERS\n // ============================================================================\n const handleNavItemKeyDown = (\n e: React.KeyboardEvent<HTMLElement>,\n handleClick: (\n e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>\n ) => void\n ) => {\n const { key } = e;\n\n if (key === \"Enter\" || key === \" \") {\n e.preventDefault();\n handleClick(e);\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n\n const renderLocalNavItem = ({\n handleClick,\n isSelected,\n item,\n renderItem,\n index,\n }: LocalNavMenuItemComponentProps) => {\n const { id, title, titleAddon } = item;\n\n const renderTitle = () => {\n if (renderItem) {\n return renderItem(item, { selected: isSelected });\n }\n const label = (\n <TextLabel weight={isSelected ? \"semibold\" : \"regular\"}>\n {title}\n </TextLabel>\n );\n if (!titleAddon) {\n return label;\n }\n return (\n <TitleContainer>\n {titleAddon.left && (\n <LeftAddon>{titleAddon.left}</LeftAddon>\n )}\n {label}\n {titleAddon.right && (\n <RightAddon>{titleAddon.right}</RightAddon>\n )}\n </TitleContainer>\n );\n };\n\n return (\n <NavItem id={id} key={index} $isSelected={isSelected}>\n <NavItemContent\n role=\"link\"\n onClick={handleClick}\n onKeyDown={(e) => handleNavItemKeyDown(e, handleClick)}\n tabIndex={0}\n aria-current={isSelected ? true : undefined}\n >\n {renderTitle()}\n </NavItemContent>\n </NavItem>\n );\n };\n return (\n <Nav\n ref={ref}\n id={id}\n className={className}\n data-testid={localNavMenuId}\n >\n {items.map((item, i) => {\n const isSelected = i === selectedItemIndex;\n return renderLocalNavItem({\n handleClick: (e) => onNavItemSelect(e, item, i),\n isSelected,\n item,\n renderItem,\n index: i,\n });\n })}\n </Nav>\n );\n};\n\nexport const LocalNavMenu = React.forwardRef(Component);\n"],"names":["LocalNavMenu","React","forwardRef","onNavItemSelect","items","selectedItemIndex","id","dataTestId","className","renderItem","ref","_jsx","Nav","children","map","item","i","handleClick","isSelected","index","title","titleAddon","NavItem","$isSelected","NavItemContent","role","onClick","onKeyDown","e","key","preventDefault","handleNavItemKeyDown","tabIndex","undefined","selected","label","TextLabel","weight","_jsxs","TitleContainer","left","LeftAddon","right","RightAddon","renderTitle","renderLocalNavItem"],"mappings":"2NAmBA,MA2GaA,EAAeC,EAAMC,YA3GhB,EAEVC,kBACAC,QACAC,oBACAC,KACA,cAAeC,EACfC,YACAC,cAEJC,IA6EIC,EAACC,EAAG,CACAF,IAAKA,EACLJ,GAAIA,EACJE,UAAWA,EAAS,cA3ELD,GAAc,iBA4EFM,SAE1BT,EAAMU,KAAI,CAACC,EAAMC,IAvDC,GACvBC,cACAC,aACAH,OACAN,aACAU,YAEA,MAAMb,GAAEA,EAAEc,MAAEA,EAAKC,WAAEA,GAAeN,EA2BlC,OACIJ,EAACW,EAAO,CAAChB,GAAIA,EAAEiB,YAA2BL,EAAUL,SAChDF,EAACa,EAAc,CACXC,KAAK,OACLC,QAAST,EACTU,UAAYC,GAzDC,EACzBA,EACAX,KAIA,MAAMY,IAAEA,GAAQD,EAEJ,UAARC,GAA2B,MAARA,IACnBD,EAAEE,iBACFb,EAAYW,GAChB,EA8C8BG,CAAqBH,EAAGX,GAC1Ce,SAAU,EAAC,iBACGd,QAAoBe,EAASpB,SAhCnC,MAChB,GAAIJ,EACA,OAAOA,EAAWM,EAAM,CAAEmB,SAAUhB,IAExC,MAAMiB,EACFxB,EAACyB,EAAS,CAACC,OAAQnB,EAAa,WAAa,UAASL,SACjDO,IAGT,OAAKC,EAIDiB,EAACC,EAAc,CAAA1B,SAAA,CACVQ,EAAWmB,MACR7B,EAAC8B,EAAS,CAAA5B,SAAEQ,EAAWmB,OAE1BL,EACAd,EAAWqB,OACR/B,EAACgC,EAAU,CAAA9B,SAAEQ,EAAWqB,WATzBP,CAWU,EAaZS,MARazB,EAUZ,EAYC0B,CAAmB,CACtB5B,YAAcW,GAAMzB,EAAgByB,EAAGb,EAAMC,GAC7CE,WAHeF,IAAMX,EAIrBU,OACAN,aACAU,MAAOH"}
|
|
@@ -13,6 +13,9 @@ export declare const TextLabel: import("styled-components/dist/types").IStyledCo
|
|
|
13
13
|
as?: import("styled-components").WebTarget | undefined;
|
|
14
14
|
forwardedAs?: import("styled-components").WebTarget | undefined;
|
|
15
15
|
}, "$isSelected"> & NavItemStyleProps, never>>> & string;
|
|
16
|
+
export declare const TitleContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>>> & string;
|
|
17
|
+
export declare const LeftAddon: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>>> & string;
|
|
18
|
+
export declare const RightAddon: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>>> & string;
|
|
16
19
|
export declare const NavItem: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, "$isSelected"> & NavItemStyleProps, never> & Partial<Pick<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, "$isSelected"> & NavItemStyleProps, never>>> & string;
|
|
17
20
|
export declare const NavItemContent: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>>> & string;
|
|
18
21
|
export {};
|