@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.
Files changed (94) hide show
  1. package/breadcrumb/breadcrumb.js +1 -1
  2. package/breadcrumb/breadcrumb.js.map +1 -1
  3. package/breadcrumb/breadcrumb.style.d.ts +1 -6
  4. package/breadcrumb/breadcrumb.style.js +27 -43
  5. package/breadcrumb/breadcrumb.style.js.map +1 -1
  6. package/breadcrumb/types.d.ts +2 -5
  7. package/cjs/breadcrumb/breadcrumb.js +1 -1
  8. package/cjs/breadcrumb/breadcrumb.js.map +1 -1
  9. package/cjs/breadcrumb/breadcrumb.style.js +16 -32
  10. package/cjs/breadcrumb/breadcrumb.style.js.map +1 -1
  11. package/cjs/drawer/drawer.js +1 -1
  12. package/cjs/drawer/drawer.js.map +1 -1
  13. package/cjs/drawer/drawer.styles.js +48 -31
  14. package/cjs/drawer/drawer.styles.js.map +1 -1
  15. package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.js +1 -1
  16. package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.js.map +1 -1
  17. package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js +30 -16
  18. package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js.map +1 -1
  19. package/cjs/local-nav/local-nav-menu/local-nav-menu.js +1 -1
  20. package/cjs/local-nav/local-nav-menu/local-nav-menu.js.map +1 -1
  21. package/cjs/local-nav/local-nav-menu/local-nav-menu.styles.js +25 -11
  22. package/cjs/local-nav/local-nav-menu/local-nav-menu.styles.js.map +1 -1
  23. package/cjs/menu/menu-content.js +1 -1
  24. package/cjs/menu/menu-content.js.map +1 -1
  25. package/cjs/menu/menu-content.styles.js +4 -1
  26. package/cjs/menu/menu-content.styles.js.map +1 -1
  27. package/cjs/menu/menu-item.styles.js +1 -1
  28. package/cjs/menu/menu-item.styles.js.map +1 -1
  29. package/cjs/menu/menu-link.styles.js +1 -1
  30. package/cjs/menu/menu-link.styles.js.map +1 -1
  31. package/cjs/menu/menu-section.js +1 -1
  32. package/cjs/menu/menu-section.js.map +1 -1
  33. package/cjs/menu/menu-section.styles.js +23 -9
  34. package/cjs/menu/menu-section.styles.js.map +1 -1
  35. package/cjs/navbar/navbar-items.js +1 -1
  36. package/cjs/navbar/navbar-items.js.map +1 -1
  37. package/cjs/pagination/pagination.js +1 -1
  38. package/cjs/pagination/pagination.js.map +1 -1
  39. package/cjs/shared/dropdown-list/dropdown-label.js +1 -1
  40. package/cjs/shared/dropdown-list/dropdown-label.js.map +1 -1
  41. package/cjs/shared/fade-wrapper/fade-wrapper.js +1 -1
  42. package/cjs/shared/fade-wrapper/fade-wrapper.js.map +1 -1
  43. package/drawer/drawer.d.ts +1 -1
  44. package/drawer/drawer.js +1 -1
  45. package/drawer/drawer.js.map +1 -1
  46. package/drawer/drawer.styles.d.ts +8 -1
  47. package/drawer/drawer.styles.js +46 -29
  48. package/drawer/drawer.styles.js.map +1 -1
  49. package/drawer/types.d.ts +7 -0
  50. package/input-group/types.d.ts +1 -1
  51. package/input-select/types.d.ts +1 -1
  52. package/local-nav/local-nav-dropdown/local-nav-dropdown.js +1 -1
  53. package/local-nav/local-nav-dropdown/local-nav-dropdown.js.map +1 -1
  54. package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.d.ts +3 -0
  55. package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js +42 -28
  56. package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js.map +1 -1
  57. package/local-nav/local-nav-menu/local-nav-menu.js +1 -1
  58. package/local-nav/local-nav-menu/local-nav-menu.js.map +1 -1
  59. package/local-nav/local-nav-menu/local-nav-menu.styles.d.ts +3 -0
  60. package/local-nav/local-nav-menu/local-nav-menu.styles.js +25 -11
  61. package/local-nav/local-nav-menu/local-nav-menu.styles.js.map +1 -1
  62. package/local-nav/types.d.ts +17 -0
  63. package/menu/menu-content.js +1 -1
  64. package/menu/menu-content.js.map +1 -1
  65. package/menu/menu-content.styles.d.ts +1 -0
  66. package/menu/menu-content.styles.js +17 -14
  67. package/menu/menu-content.styles.js.map +1 -1
  68. package/menu/menu-item.styles.js +1 -1
  69. package/menu/menu-item.styles.js.map +1 -1
  70. package/menu/menu-link.styles.js +1 -1
  71. package/menu/menu-link.styles.js.map +1 -1
  72. package/menu/menu-section.d.ts +1 -1
  73. package/menu/menu-section.js +1 -1
  74. package/menu/menu-section.js.map +1 -1
  75. package/menu/menu-section.styles.d.ts +9 -2
  76. package/menu/menu-section.styles.js +22 -8
  77. package/menu/menu-section.styles.js.map +1 -1
  78. package/menu/menu.d.ts +1 -1
  79. package/menu/types.d.ts +2 -2
  80. package/navbar/navbar-items.js +1 -1
  81. package/navbar/navbar-items.js.map +1 -1
  82. package/navbar/types.d.ts +1 -0
  83. package/package.json +1 -1
  84. package/pagination/pagination.js +1 -1
  85. package/pagination/pagination.js.map +1 -1
  86. package/pagination/types.d.ts +1 -0
  87. package/select-histogram/types.d.ts +1 -1
  88. package/shared/dropdown-list/dropdown-label.d.ts +2 -2
  89. package/shared/dropdown-list/dropdown-label.js +1 -1
  90. package/shared/dropdown-list/dropdown-label.js.map +1 -1
  91. package/shared/dropdown-list/types.d.ts +2 -2
  92. package/shared/fade-wrapper/fade-wrapper.js +1 -1
  93. package/shared/fade-wrapper/fade-wrapper.js.map +1 -1
  94. package/shared/fade-wrapper/types.d.ts +1 -0
@@ -1,4 +1,4 @@
1
- import i,{css as t}from"styled-components";import{ClickableIcon as o}from"../shared/clickable-icon/clickable-icon.js";import{Motion as a,Colour as e,Shadow as n,Radius as d,MediaQuery as r,Spacing as s,Font as l,Border as p}from"../theme/index.js";import{Typography as c}from"../typography/typography.js";const g=t`
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: ${a["duration-800"]};
11
- transition-timing-function: ${a["ease-entrance"]};
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: ${a["duration-800"]};
18
- transition-timing-function: ${a["ease-exit"]};
17
+ transition-duration: ${o["duration-800"]};
18
+ transition-timing-function: ${o["ease-exit"]};
19
19
  right: -100%;
20
20
  visibility: hidden;
21
21
  }
22
- `,h=i.div`
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: ${e.bg};
30
+ background-color: ${a.bg};
31
31
  box-shadow: ${n["lg-subtle"]};
32
32
 
33
- ${g}
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
- ${r.MaxWidth.xl} {
40
+ ${s.MaxWidth.xl} {
41
41
  width: 50%;
42
42
  min-width: 700px;
43
43
  }
44
44
 
45
- ${r.MaxWidth.lg} {
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: ${s["spacing-16"]};
56
- padding: ${s["spacing-32"]} ${s["spacing-16"]}
57
- ${s["spacing-16"]}
58
- calc(${l.Spec["heading-lh-md"]} + ${s["spacing-32"]});
59
- background-color: ${e.bg};
60
- border-bottom: ${p["width-010"]} ${p.solid} ${e.border};
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
- ${r.MaxWidth.lg} {
63
- gap: ${s["spacing-8"]};
64
- padding: ${s["spacing-32"]} ${s["spacing-20"]}
65
- ${s["spacing-16"]}
66
- calc(${l.Spec["heading-lh-md"]} + ${s["spacing-24"]});
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
- `,m=i(o)`
69
- color: ${e.icon};
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: ${s["spacing-32"]};
73
- left: ${s["spacing-16"]};
89
+ top: ${r["spacing-32"]};
90
+ left: ${r["spacing-16"]};
74
91
  &:active,
75
92
  &:focus {
76
- color: ${e["icon-hover"]};
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(c.HeadingMD)`
100
+ `,b=i(h.HeadingMD)`
84
101
  text-overflow: ellipsis;
85
102
  overflow: hidden;
86
103
  white-space: nowrap;
87
- `,f=i.div`
104
+ `,u=i.div`
88
105
  flex: 1;
89
106
  overflow-y: auto;
90
- `;export{m as CloseButton,h as Container,f as Content,$ as Header,b as Heading};
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`\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 ${MediaQuery.MaxWidth.lg} {\n gap: ${Spacing[\"spacing-8\"]};\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 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","CloseButton","ClickableIcon","icon","Heading","Typography","HeadingMD","Content"],"mappings":"iTA0BA,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,GAAG;;;;WAIrBU,EAAQ;eACJA,EAAQ,iBAAiBA,EAAQ;UACtCA,EAAQ;eACHC,EAAKC,KAAK,sBAAsBF,EAAQ;wBAC/BT,EAAOC;qBACVW,EAAO,gBAAgBA,EAAOC,SAASb,EAAOc;;MAE7DV,EAAWC,SAASE;eACXE,EAAQ;mBACJA,EAAQ,iBAAiBA,EAAQ;cACtCA,EAAQ;mBACHC,EAAKC,KAAK,sBAAsBF,EAAQ;;EAI9CM,EAAcjB,EAAOkB,EAAc;aACnChB,EAAOiB;;;WAGTR,EAAQ;YACPA,EAAQ;;;iBAGHT,EAAO;;;;kBAINU,EAAKC,KAAK;iBACXD,EAAKC,KAAK;;EAIdO,EAAUpB,EAAOqB,EAAWC,UAAU;;;;EAMtCC,EAAUvB,EAAOC,GAAG;;;"}
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
  }
@@ -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;
@@ -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 w,NavItem as h,StyledTickIcon as f,NavItemLabel as v}from"./local-nav-dropdown.styles.js";const y=r.forwardRef((({defaultLabel:r,stickyOffset:y=0,onNavItemSelect:x,items:k,selectedItemIndex:D,id:$,"data-testid":E,className:I,renderItem:L},C)=>{const j=i(null),S=i(null),B=i(null),z=i([]),[A,H]=o(!1),[K,M]=o(!1),[N,O]=o(0),[R,T]=o(0),[W,U]=o(0),[q,F]=o(0),G=E||"local-nav-dropdown",J=c();d(C,(()=>B.current));const P="number"==typeof D&&D>=0&&A?k[D].title:r;l((()=>{if(S.current){const e=S.current.getBoundingClientRect().height;T(e)}}),[]),l((()=>(Q(),()=>{V("remove")})),[]),l((()=>{V(K&&A?"add":"remove")}),[K,A]),l((()=>{O(window.innerHeight);const e=()=>{O(window.innerHeight)};return window.addEventListener("resize",e),()=>window.removeEventListener("resize",e)}),[]),l((()=>{const e=new IntersectionObserver((e=>{const[t]=e;H(!t.isIntersecting)}),{threshold:1,rootMargin:`-${y}px 0px 0px 0px`});return j.current&&e.observe(j.current),()=>e.disconnect()}),[y]),l((()=>{const e=()=>{const e=null==B?void 0:B.current;if(e){const t=e.getBoundingClientRect(),n=document.body.clientWidth-t.right,r=t.left,i=Math.max(n,r);U(i)}};return e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}}),[]),l((()=>{var e;K&&(null===(e=z.current[q])||void 0===e||e.focus())}),[K,q]);const Q=()=>{if(!document.getElementById(g)){const e=document.createElement("style");e.id=g;const t=document.documentElement.clientWidth,n=window.innerWidth-t;e.innerHTML=`\n\t\t\t\t.${b} {\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.${b}::-webkit-scrollbar {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\t`,document.body.appendChild(e)}},V=e=>{const t=document.body.classList.contains(b);"add"!==e||t?"remove"===e&&t&&document.body.classList.remove(b):document.body.classList.add(b)},X=(e,t)=>{const{key:n}=e;"Enter"!==n&&" "!==n||(e.preventDefault(),t(e))};return e(t,{children:[n("span",{ref:j,"data-testid":"sticky-ref"}),e(a,{$isStickied:A,$sideMargin:W,$stickyOffset:y,ref:B,id:$,"data-testid":G,className:I,children:[e(p,{ref:S,role:"button",onClick:()=>{M((e=>!e))},onKeyDown:e=>{const{key:t}=e;"ArrowDown"===t?(e.preventDefault(),K||M(!0),F(0)):"ArrowUp"===t?(e.preventDefault(),K||M(!0),F(k.length-1)):"Enter"===t||" "===t?(e.preventDefault(),M(!0),F(0)):("Tab"===t||"Escape"===t)&&M(!1)},"data-testid":`${G}-label`,$isDropdownExpanded:K,"aria-haspopup":"true","aria-expanded":K,"aria-controls":J,tabIndex:0,children:[n(s.BodyBL,{weight:"semibold",children:P}),n(u,{$isDropdownExpanded:K})]}),K&&n(m,{id:J,role:"menu",onKeyDown:e=>{var t;const{key:n}=e;if("ArrowDown"===n){e.preventDefault();const t=(q+1)%k.length;F(t)}else if("ArrowUp"===n){e.preventDefault();const t=q>0?q-1:k.length-1;F(t)}else"Tab"===n?M(!1):"Escape"===n&&(M(!1),null===(t=S.current)||void 0===t||t.focus())},"data-testid":`${G}-dropdown-list`,$viewportHeight:N-R-y,children:k.map(((t,r)=>(({handleClick:t,isSelected:r,item:i,renderItem:o,index:d})=>{const{id:l,title:s}=i;return o?n("li",{id:l,role:"menuitem",onClick:t,onKeyDown:e=>X(e,t),"aria-current":!!r||void 0,tabIndex:-1,ref:e=>{z.current[d]=e},children:o(i,{selected:r,stickied:A})},d):e(h,{id:l,role:"menuitem",$isSelected:r&&A,onClick:t,onKeyDown:e=>X(e,t),"aria-current":!!r||void 0,tabIndex:-1,ref:e=>{z.current[d]=e},children:[r&&n(f,{}),n(v,{$isSelected:r,children:s})]},d)})({handleClick:e=>((e,t,n)=>{x&&x(e,t,n),M(!1)})(e,t,r),isSelected:r===D,item:t,renderItem:L,index:r})))}),K&&A&&n(w,{onClick:()=>{M(!1)}})]})]})})),g="lifesg-ds-local-nav-dropdown-stylesheet",b="lifesg-ds-local-nav-dropdown-open";export{y as LocalNavDropdown};
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":"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"}
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 o}from"@lifesg/react-icons/tick";import t,{css as e}from"styled-components";import{Colour as r,Motion as s,Spacing as n,Border as a,Radius as d,Font as $}from"../../theme/index.js";const l=t(i)`
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 ${s["duration-250"]} ${s["ease-default"]};
3
+ transition: transform ${n["duration-250"]} ${n["ease-default"]};
4
4
  transform: rotate(${i=>i.$isDropdownExpanded?180:0}deg);
5
- `,c=t.div`
5
+ `,p=t.div`
6
6
  cursor: pointer;
7
7
  background: ${r.bg};
8
- padding: ${n["spacing-12"]} ${n["spacing-16"]};
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&&e`
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 ${s["duration-250"]} ${s["ease-default"]};
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
- `,p=t.li`
29
- padding: ${i=>i.$isSelected?e`
30
- ${n["spacing-12"]} ${n["spacing-8"]}
31
- ${n["spacing-12"]} 0
32
- `:e`
33
- ${n["spacing-12"]} ${n["spacing-8"]}
34
- ${n["spacing-12"]} ${n["spacing-32"]}
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 ${s["duration-250"]} ${s["ease-default"]};
49
+ transition: all ${n["duration-250"]} ${n["ease-default"]};
50
50
  transform-origin: top;
51
51
  list-style-type: none;
52
- padding: 0 ${n["spacing-8"]};
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
- `,b=t.div`
65
- ${$["body-baseline-regular"]}
64
+ `,m=t.div`
65
+ ${l["body-baseline-regular"]}
66
66
  color: ${i=>i.$isSelected?r["text-selected"]:r.text};
67
- `,m=t(o)`
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 ${n["spacing-8"]};
70
- `,u=t.div`
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
- `,f=t.nav`
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:o})=>i&&e`
86
- ${c} {
87
- ${o&&`margin: 0 -${o}px;`}
88
- padding: ${n["spacing-12"]} ${n["spacing-16"]};
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
- ${o&&`margin-left: -${o}px;`}
94
- ${o&&`margin-right: -${o}px;`}
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{u as Backdrop,p as NavItem,b as NavItemLabel,g as NavItemList,c as NavSelect,l as NavSelectIcon,f as NavWrapper,m as StyledTickIcon};
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;aACjCnB,EAAO;gBACJM,EAAQ;EAOXc,EAAWtB,EAAOO,GAAG;;;;;;wBAMVL,EAAO;;EAIlBqB,EAAavB,EAAOwB,GAA0B;;;WAG/CpB,GAAUA,EAAMqB;;;;MAItB,EAAGC,cAAaC,iBACdD,GACAf,CAAG;cACGL;kBACIqB,GAAe,cAAcA;2BACpBnB,EAAQ,iBAAiBA,EAAQ;iCAC3BE,EAAa;;;cAGhCK;kBACIY,GAAe,iBAAiBA;kBAChCA,GAAe,kBAAkBA;6CACNjB,EAAOkB;8CACNlB,EAAOkB;;;"}
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 t from"react";import{Nav as r,NavItem as i,NavItemContent as n,TextLabel as d}from"./local-nav-menu.styles.js";const l=t.forwardRef((({onNavItemSelect:t,items:l,selectedItemIndex:a,id:c,"data-testid":m,className:o,renderItem:s},f)=>e(r,{ref:f,id:c,className:o,"data-testid":m||"local-nav-menu",children:l.map(((r,l)=>(({handleClick:t,isSelected:r,item:l,renderItem:a,index:c})=>{const{id:m,title:o}=l;return e(i,{id:m,$isSelected:r,children:e(n,{role:"link",onClick:t,onKeyDown:e=>((e,t)=>{const{key:r}=e;"Enter"!==r&&" "!==r||(e.preventDefault(),t(e))})(e,t),tabIndex:0,"aria-current":!!r||void 0,children:a?a(l,{selected:r}):e(d,{weight:r?"semibold":"regular",children:o})})},c)})({handleClick:e=>t(e,r,l),isSelected:l===a,item:r,renderItem:s,index:l})))})));export{l as LocalNavMenu};
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 return (\n <TextLabel weight={isSelected ? \"semibold\" : \"regular\"}>\n {title}\n </TextLabel>\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","NavItem","$isSelected","NavItemContent","role","onClick","onKeyDown","e","key","preventDefault","handleNavItemKeyDown","tabIndex","undefined","selected","TextLabel","weight","renderLocalNavItem"],"mappings":"8JAgBA,MA6FaA,EAAeC,EAAMC,YA7FhB,EAEVC,kBACAC,QACAC,oBACAC,KACA,cAAeC,EACfC,YACAC,cAEJC,IA+DIC,EAACC,EAAG,CACAF,IAAKA,EACLJ,GAAIA,EACJE,UAAWA,EAAS,cA7DLD,GAAc,iBA8DFM,SAE1BT,EAAMU,KAAI,CAACC,EAAMC,IAzCC,GACvBC,cACAC,aACAH,OACAN,aACAU,YAEA,MAAMb,GAAEA,EAAEc,MAAEA,GAAUL,EAatB,OACIJ,EAACU,EAAO,CAACf,GAAIA,EAAEgB,YAA2BJ,EAAUL,SAChDF,EAACY,EAAc,CACXC,KAAK,OACLC,QAASR,EACTS,UAAYC,GA3CC,EACzBA,EACAV,KAIA,MAAMW,IAAEA,GAAQD,EAEJ,UAARC,GAA2B,MAARA,IACnBD,EAAEE,iBACFZ,EAAYU,GAChB,EAgC8BG,CAAqBH,EAAGV,GAC1Cc,SAAU,EAAC,iBACGb,QAAoBc,EAASnB,SAjB/CJ,EACOA,EAAWM,EAAM,CAAEkB,SAAUf,IAGpCP,EAACuB,GAAUC,OAAQjB,EAAa,WAAa,mBACxCE,OAMaD,EAUZ,EAYCiB,CAAmB,CACtBnB,YAAcU,GAAMxB,EAAgBwB,EAAGZ,EAAMC,GAC7CE,WAHeF,IAAMX,EAIrBU,OACAN,aACAU,MAAOH"}
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 {};