@lifesg/react-design-system 4.0.0-alpha.8 → 4.0.0-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/accordion/accordion-item.js.map +1 -1
- package/accordion/accordion.js.map +1 -1
- package/alert/alert.js.map +1 -1
- package/cjs/accordion/accordion-item.js.map +1 -1
- package/cjs/accordion/accordion.js.map +1 -1
- package/cjs/alert/alert.js.map +1 -1
- package/cjs/countdown-timer/countdown-timer.js.map +1 -1
- package/cjs/data-table/data-table.js +1 -1
- package/cjs/data-table/data-table.js.map +1 -1
- package/cjs/date-range-input/date-range-input.js.map +1 -1
- package/cjs/e-signature/e-signature-canvas.js.map +1 -1
- package/cjs/error-display/inactivity-timer.js.map +1 -1
- package/cjs/external/dompurify/dist/purify.es.js +2 -2
- package/cjs/external/dompurify/dist/purify.es.js.map +1 -1
- package/cjs/file-download/file-list-card/file-list-card.js.map +1 -1
- package/cjs/file-upload/custom-sensors.js.map +1 -1
- package/cjs/file-upload/file-list/file-list.js.map +1 -1
- package/cjs/filter/addons/filter-item-checkbox-helpers.js.map +1 -1
- package/cjs/filter/addons/filter-item-checkbox.js.map +1 -1
- package/cjs/filter/filter-item.js.map +1 -1
- package/cjs/filter/filter.js.map +1 -1
- package/cjs/form/form-textarea/form-textarea.js +1 -1
- package/cjs/form/form-textarea/form-textarea.js.map +1 -1
- package/cjs/fullscreen-image-carousel/stateful-image.js.map +1 -1
- package/cjs/histogram-slider/histogram-slider.js.map +1 -1
- package/cjs/input-range-slider/input-range-slider.js.map +1 -1
- package/cjs/input-slider/input-slider.js.map +1 -1
- package/cjs/input-textarea/textarea-counter.js.map +1 -1
- package/cjs/input-textarea/textarea.js +1 -1
- package/cjs/input-textarea/textarea.js.map +1 -1
- package/cjs/input-textarea/textarea.styles.js +1 -1
- package/cjs/input-textarea/textarea.styles.js.map +1 -1
- package/{input-textarea/textarea.styles_q77m5x.css → cjs/input-textarea/textarea.styles_6we7bs.css} +3 -1
- package/cjs/modal/index.js.map +1 -1
- package/cjs/modal-v2/modal-v2.js +1 -1
- package/cjs/modal-v2/modal-v2.js.map +1 -1
- package/cjs/modal-v2/slots/card.js +1 -1
- package/cjs/modal-v2/slots/card.js.map +1 -1
- package/cjs/modal-v2/slots/header.js +2 -0
- package/cjs/modal-v2/slots/header.js.map +1 -0
- package/cjs/modal-v2/slots/slot-styles.js +1 -1
- package/cjs/modal-v2/slots/slot-styles.js.map +1 -1
- package/cjs/modal-v2/slots/{slot-styles_13sd376.css → slot-styles_10ut1v7.css} +5 -1
- package/cjs/navbar/navbar-items.js +1 -1
- package/cjs/navbar/navbar-items.js.map +1 -1
- package/cjs/navbar/navbar-items.styles.js +1 -1
- package/cjs/navbar/navbar-items.styles.js.map +1 -1
- package/cjs/navbar/{navbar-items.styles_1i3ltot.css → navbar-items.styles_1b1zx.css} +9 -8
- package/cjs/navbar/navbar-logo-data.js +1 -1
- package/cjs/navbar/navbar-logo-data.js.map +1 -1
- package/cjs/navbar/navbar.js.map +1 -1
- package/cjs/otp-input/otp-input.js.map +1 -1
- package/cjs/overlay/overlay.js.map +1 -1
- package/cjs/pagination/pagination.js.map +1 -1
- package/cjs/phone-number-input/phone-number-input.js.map +1 -1
- package/cjs/predictive-text-input/predictive-text-input.js.map +1 -1
- package/cjs/shared/dropdown-list/dropdown-list.js.map +1 -1
- package/cjs/shared/internal-calendar/calendar-manager.js.map +1 -1
- package/cjs/shared/standalone-date-input/standalone-date-input.js.map +1 -1
- package/cjs/theme/types.js +1 -1
- package/cjs/theme/types.js.map +1 -1
- package/cjs/time-slot-bar/time-slot-bar.js.map +1 -1
- package/cjs/time-slot-bar-week/time-slot-bar-week-days.js.map +1 -1
- package/cjs/timetable/timetable.js.map +1 -1
- package/cjs/toggle/toggle-icon.js +1 -1
- package/cjs/toggle/toggle-icon.js.map +1 -1
- package/cjs/toggle/toggle-icon.styles.js +1 -1
- package/cjs/toggle/toggle-icon.styles.js.map +1 -1
- package/cjs/toggle/{toggle-icon.styles_ba71y.css → toggle-icon.styles_o6dxr3.css} +3 -2
- package/cjs/toggle/toggle.js +1 -1
- package/cjs/toggle/toggle.js.map +1 -1
- package/cjs/toggle/toggle.styles.js +1 -1
- package/cjs/toggle/toggle.styles.js.map +1 -1
- package/cjs/toggle/toggle.styles_11tmfsr.css +41 -0
- package/cjs/unit-number/unit-number-input.js.map +1 -1
- package/cjs/util/is-styled-components.js.map +1 -1
- package/cjs/util/string-helper.js +1 -1
- package/cjs/util/string-helper.js.map +1 -1
- package/cjs/util/use-event-listener.js.map +1 -1
- package/cjs/util/use-state-actions.js.map +1 -1
- package/countdown-timer/countdown-timer.js.map +1 -1
- package/data-table/data-table.js +1 -1
- package/data-table/data-table.js.map +1 -1
- package/data-table/types.d.ts +2 -2
- package/date-range-input/date-range-input.js.map +1 -1
- package/docs/component-catalog.json +1 -1
- package/e-signature/e-signature-canvas.js.map +1 -1
- package/error-display/inactivity-timer.js.map +1 -1
- package/external/dompurify/dist/purify.es.js +2 -2
- package/external/dompurify/dist/purify.es.js.map +1 -1
- package/file-download/file-list-card/file-list-card.js.map +1 -1
- package/file-upload/custom-sensors.d.ts +2 -2
- package/file-upload/custom-sensors.js.map +1 -1
- package/file-upload/file-list/file-list.js.map +1 -1
- package/filter/addons/filter-item-checkbox-helpers.js.map +1 -1
- package/filter/addons/filter-item-checkbox.js.map +1 -1
- package/filter/filter-item.js.map +1 -1
- package/filter/filter.js.map +1 -1
- package/form/form-textarea/form-textarea.js +1 -1
- package/form/form-textarea/form-textarea.js.map +1 -1
- package/fullscreen-image-carousel/stateful-image.js.map +1 -1
- package/fullscreen-image-carousel/types.d.ts +2 -2
- package/histogram-slider/histogram-slider.js.map +1 -1
- package/input-range-slider/input-range-slider.js.map +1 -1
- package/input-slider/input-slider.js.map +1 -1
- package/input-textarea/textarea-counter.js.map +1 -1
- package/input-textarea/textarea.js +1 -1
- package/input-textarea/textarea.js.map +1 -1
- package/input-textarea/textarea.styles.d.ts +2 -0
- package/input-textarea/textarea.styles.js +1 -1
- package/input-textarea/textarea.styles.js.map +1 -1
- package/{cjs/input-textarea/textarea.styles_q77m5x.css → input-textarea/textarea.styles_6we7bs.css} +3 -1
- package/input-textarea/types.d.ts +7 -0
- package/modal/index.d.ts +4 -0
- package/modal/index.js.map +1 -1
- package/modal/types.d.ts +2 -0
- package/modal-v2/modal-v2.d.ts +6 -0
- package/modal-v2/modal-v2.js +1 -1
- package/modal-v2/modal-v2.js.map +1 -1
- package/modal-v2/slots/card.js +1 -1
- package/modal-v2/slots/card.js.map +1 -1
- package/modal-v2/slots/header.d.ts +5 -0
- package/modal-v2/slots/header.js +2 -0
- package/modal-v2/slots/header.js.map +1 -0
- package/modal-v2/slots/index.d.ts +1 -0
- package/modal-v2/slots/slot-styles.d.ts +4 -0
- package/modal-v2/slots/slot-styles.js +1 -1
- package/modal-v2/slots/slot-styles.js.map +1 -1
- package/modal-v2/slots/{slot-styles_13sd376.css → slot-styles_10ut1v7.css} +5 -1
- package/modal-v2/types.d.ts +21 -0
- package/navbar/navbar-items.js +1 -1
- package/navbar/navbar-items.js.map +1 -1
- package/navbar/navbar-items.styles.d.ts +2 -1
- package/navbar/navbar-items.styles.js +1 -1
- package/navbar/navbar-items.styles.js.map +1 -1
- package/navbar/{navbar-items.styles_1i3ltot.css → navbar-items.styles_1b1zx.css} +9 -8
- package/navbar/navbar-logo-data.js +1 -1
- package/navbar/navbar-logo-data.js.map +1 -1
- package/navbar/navbar.js.map +1 -1
- package/otp-input/otp-input.js.map +1 -1
- package/overlay/overlay.js.map +1 -1
- package/package.json +1 -1
- package/pagination/pagination.js.map +1 -1
- package/phone-number-input/phone-number-input.js.map +1 -1
- package/predictive-text-input/predictive-text-input.js.map +1 -1
- package/shared/dropdown-list/dropdown-list.js.map +1 -1
- package/shared/internal-calendar/calendar-manager.js.map +1 -1
- package/shared/standalone-date-input/standalone-date-input.js.map +1 -1
- package/theme/styles/a11y-playground.css +358 -87
- package/theme/styles/bookingsg.css +391 -85
- package/theme/styles/careercompass.css +396 -90
- package/theme/styles/ccube.css +402 -45
- package/theme/styles/imda.css +348 -85
- package/theme/styles/lifesg.css +377 -87
- package/theme/styles/mylegacy.css +382 -85
- package/theme/styles/oneservice.css +349 -86
- package/theme/styles/pa.css +172 -63
- package/theme/styles/rbs.css +403 -46
- package/theme/styles/sgw-digital-lobby.css +352 -87
- package/theme/styles/smgs.css +401 -95
- package/theme/styles/spf.css +208 -99
- package/theme/styles/supportgowhere.css +387 -90
- package/theme/styles/tote-board.css +816 -0
- package/theme/types.d.ts +1 -1
- package/theme/types.js +1 -1
- package/theme/types.js.map +1 -1
- package/time-slot-bar/time-slot-bar.js.map +1 -1
- package/time-slot-bar-week/time-slot-bar-week-days.js.map +1 -1
- package/timetable/timetable.js.map +1 -1
- package/toggle/toggle-icon.d.ts +2 -1
- package/toggle/toggle-icon.js +1 -1
- package/toggle/toggle-icon.js.map +1 -1
- package/toggle/toggle-icon.styles.d.ts +1 -0
- package/toggle/toggle-icon.styles.js +1 -1
- package/toggle/toggle-icon.styles.js.map +1 -1
- package/toggle/{toggle-icon.styles_ba71y.css → toggle-icon.styles_o6dxr3.css} +3 -2
- package/toggle/toggle.js +1 -1
- package/toggle/toggle.js.map +1 -1
- package/toggle/toggle.styles.d.ts +18 -15
- package/toggle/toggle.styles.js +1 -1
- package/toggle/toggle.styles.js.map +1 -1
- package/toggle/toggle.styles_11tmfsr.css +41 -0
- package/unit-number/unit-number-input.js.map +1 -1
- package/util/is-styled-components.js.map +1 -1
- package/util/string-helper.d.ts +2 -2
- package/util/string-helper.js +1 -1
- package/util/string-helper.js.map +1 -1
- package/util/use-event-listener.js.map +1 -1
- package/util/use-state-actions.js.map +1 -1
- package/cjs/form/form-textarea/form-textarea.styles.js +0 -2
- package/cjs/form/form-textarea/form-textarea.styles.js.map +0 -1
- package/cjs/form/form-textarea/form-textarea.styles_1kneyif.css +0 -3
- package/cjs/toggle/toggle.styles_1t5qrye.css +0 -38
- package/form/form-textarea/form-textarea.styles.d.ts +0 -3
- package/form/form-textarea/form-textarea.styles.js +0 -2
- package/form/form-textarea/form-textarea.styles.js.map +0 -1
- package/form/form-textarea/form-textarea.styles_1kneyif.css +0 -3
- package/theme/styles/default.css +0 -158
- package/toggle/toggle.styles_1t5qrye.css +0 -38
|
@@ -12,3 +12,7 @@ export declare const styledClickableIcon: import("@linaria/core").LinariaClassNa
|
|
|
12
12
|
export declare const contentContainer: import("@linaria/core").LinariaClassName;
|
|
13
13
|
export declare const footerContainer: import("@linaria/core").LinariaClassName;
|
|
14
14
|
export declare const slotSpacer: import("@linaria/core").LinariaClassName;
|
|
15
|
+
export declare const headerContainer: import("@linaria/core").LinariaClassName;
|
|
16
|
+
export declare const headerTitle: import("@linaria/core").LinariaClassName;
|
|
17
|
+
export declare const headerCloseButton: import("@linaria/core").LinariaClassName;
|
|
18
|
+
export declare const headerSpacer: import("@linaria/core").LinariaClassName;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"./slot-
|
|
1
|
+
import"./slot-styles_10ut1v7.css";const s="metykyj",t="c1247joo",o="st53q25",h="c1ls09wh",l="f1s12qxk",a="s1vsayl1",m="h1adf5mq",c="hii7rdr",i="ha88pah",r="h3mtfiz";export{t as closeButtonContainer,h as contentContainer,l as footerContainer,i as headerCloseButton,m as headerContainer,r as headerSpacer,c as headerTitle,s as modalCard,a as slotSpacer,o as styledClickableIcon};
|
|
2
2
|
//# sourceMappingURL=slot-styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slot-styles.js","sources":["../../../src/modal-v2/slots/slot-styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport {\n Breakpoint,\n Colour,\n MediaQuery,\n Radius,\n Shadow,\n Spacing,\n} from \"../../theme\";\n\n// =============================================================================\n// Tokens and attributes\n// =============================================================================\nexport const slotSpacerHasCloseButtonAttribute = \"data-has-close-button\";\nconst internalSlotSpacerTokens = {\n firstChildMarginTop:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTop\",\n} as const;\n\nexport const slotSpacerTokens = {\n firstChildMarginTopWithCloseButton:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTopWithCloseButton\",\n firstChildMarginTopNoCloseButton:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTopNoCloseButton\",\n\n contentLastChildMarginBottom:\n \"--fds-internal-modalV2-slotSpacer-contentLastChildMarginBottom\",\n\n footerNotFirstChildMarginTop:\n \"--fds-internal-modalV2-slotSpacer-footerNotFirstChildMarginTop\",\n footerLastChildMarginBottom:\n \"--fds-internal-modalV2-slotSpacer-footerLastChildMarginBottom\",\n} as const;\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const modalCard = css`\n width: 40rem;\n margin: ${Spacing[\"spacing-64\"]} auto;\n background: ${Colour.bg};\n box-shadow: ${Shadow[\"xs-strong\"]};\n border-radius: ${Radius[\"lg\"]};\n\n display: flex;\n flex-direction: column-reverse;\n\n max-width: calc(100% - ${Breakpoint[\"xxl-margin\"]} * 2);\n\n ${MediaQuery.MaxWidth.xl} {\n max-width: calc(100% - ${Breakpoint[\"xl-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.lg} {\n max-width: calc(100% - ${Breakpoint[\"lg-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.md} {\n max-width: calc(100% - ${Breakpoint[\"md-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.sm} {\n max-width: calc(100% - ${Breakpoint[\"sm-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.xs} {\n max-width: calc(100% - ${Breakpoint[\"xs-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.xxs} {\n max-width: calc(100% - ${Breakpoint[\"xxs-margin\"]} * 2);\n }\n`;\n\nexport const closeButtonContainer = css`\n margin-right: ${Spacing[\"spacing-16\"]};\n margin-left: auto;\n margin-top: ${Spacing[\"spacing-16\"]};\n margin-bottom: ${Spacing[\"spacing-16\"]};\n`;\n\nexport const styledClickableIcon = css`\n padding: 0;\n color: ${Colour.icon};\n\n & svg {\n height: 2rem;\n width: 2rem;\n }\n`;\n\nexport const contentContainer = css`\n margin-right: ${Spacing[\"spacing-64\"]};\n margin-left: ${Spacing[\"spacing-64\"]};\n\n ${MediaQuery.MaxWidth.sm} {\n margin-right: ${Spacing[\"spacing-20\"]};\n margin-left: ${Spacing[\"spacing-20\"]};\n }\n`;\n\nexport const footerContainer = css`\n margin-right: ${Spacing[\"spacing-64\"]};\n margin-left: ${Spacing[\"spacing-64\"]};\n\n ${MediaQuery.MaxWidth.sm} {\n margin-right: ${Spacing[\"spacing-20\"]};\n margin-left: ${Spacing[\"spacing-20\"]};\n }\n\n display: flex;\n flex-direction: row-reverse; /* primary button on right */\n column-gap: ${Spacing[\"spacing-32\"]};\n row-gap: ${Spacing[\"spacing-16\"]};\n\n & > button {\n flex: 1;\n }\n\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n }\n`;\n\nexport const slotSpacer = css`\n ${slotSpacerTokens.contentLastChildMarginBottom}: initial;\n ${slotSpacerTokens.footerNotFirstChildMarginTop}: initial;\n ${slotSpacerTokens.footerLastChildMarginBottom}: initial;\n ${slotSpacerTokens.firstChildMarginTopWithCloseButton}: initial;\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton}: initial;\n\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton},\n ${Spacing[\"spacing-64\"]}\n );\n\n & > :where(.${contentContainer}:last-child) {\n margin-bottom: var(\n ${slotSpacerTokens.contentLastChildMarginBottom},\n ${Spacing[\"spacing-64\"]}\n );\n }\n\n & > :where(.${footerContainer}:not(:first-child)) {\n margin-top: var(\n ${slotSpacerTokens.footerNotFirstChildMarginTop},\n ${Spacing[\"spacing-32\"]}\n );\n }\n\n & > :where(.${footerContainer}:last-child) {\n margin-bottom: var(\n ${slotSpacerTokens.footerLastChildMarginBottom},\n ${Spacing[\"spacing-64\"]}\n );\n }\n\n &\n > :where(\n .${contentContainer}:first-child, .${footerContainer}:first-child\n ) {\n margin-top: var(${internalSlotSpacerTokens.firstChildMarginTop});\n }\n\n &[${slotSpacerHasCloseButtonAttribute}=\"true\"] {\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopWithCloseButton},\n 0\n );\n }\n\n &[${slotSpacerHasCloseButtonAttribute}=\"false\"] {\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton},\n ${Spacing[\"spacing-64\"]}\n );\n }\n`;\n"],"names":["modalCard","closeButtonContainer","styledClickableIcon","contentContainer","footerContainer","slotSpacer"],"mappings":"
|
|
1
|
+
{"version":3,"file":"slot-styles.js","sources":["../../../src/modal-v2/slots/slot-styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport {\n Breakpoint,\n Colour,\n Font,\n MediaQuery,\n Radius,\n Shadow,\n Spacing,\n} from \"../../theme\";\n\n// =============================================================================\n// Tokens and attributes\n// =============================================================================\nexport const slotSpacerHasCloseButtonAttribute = \"data-has-close-button\";\nconst internalSlotSpacerTokens = {\n firstChildMarginTop:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTop\",\n} as const;\n\nexport const slotSpacerTokens = {\n firstChildMarginTopWithCloseButton:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTopWithCloseButton\",\n firstChildMarginTopNoCloseButton:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTopNoCloseButton\",\n\n contentLastChildMarginBottom:\n \"--fds-internal-modalV2-slotSpacer-contentLastChildMarginBottom\",\n\n footerNotFirstChildMarginTop:\n \"--fds-internal-modalV2-slotSpacer-footerNotFirstChildMarginTop\",\n footerLastChildMarginBottom:\n \"--fds-internal-modalV2-slotSpacer-footerLastChildMarginBottom\",\n} as const;\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const modalCard = css`\n width: 40rem;\n margin: ${Spacing[\"spacing-64\"]} auto;\n background: ${Colour.bg};\n box-shadow: ${Shadow[\"xs-strong\"]};\n border-radius: ${Radius[\"lg\"]};\n\n display: flex;\n flex-direction: column-reverse;\n\n max-width: calc(100% - ${Breakpoint[\"xxl-margin\"]} * 2);\n\n ${MediaQuery.MaxWidth.xl} {\n max-width: calc(100% - ${Breakpoint[\"xl-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.lg} {\n max-width: calc(100% - ${Breakpoint[\"lg-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.md} {\n max-width: calc(100% - ${Breakpoint[\"md-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.sm} {\n max-width: calc(100% - ${Breakpoint[\"sm-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.xs} {\n max-width: calc(100% - ${Breakpoint[\"xs-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.xxs} {\n max-width: calc(100% - ${Breakpoint[\"xxs-margin\"]} * 2);\n }\n`;\n\nexport const closeButtonContainer = css`\n margin-right: ${Spacing[\"spacing-16\"]};\n margin-left: auto;\n margin-top: ${Spacing[\"spacing-16\"]};\n margin-bottom: ${Spacing[\"spacing-16\"]};\n`;\n\nexport const styledClickableIcon = css`\n padding: 0;\n color: ${Colour.icon};\n\n & svg {\n height: 2rem;\n width: 2rem;\n }\n`;\n\nexport const contentContainer = css`\n margin-right: ${Spacing[\"spacing-64\"]};\n margin-left: ${Spacing[\"spacing-64\"]};\n\n ${MediaQuery.MaxWidth.sm} {\n margin-right: ${Spacing[\"spacing-20\"]};\n margin-left: ${Spacing[\"spacing-20\"]};\n }\n`;\n\nexport const footerContainer = css`\n margin-right: ${Spacing[\"spacing-64\"]};\n margin-left: ${Spacing[\"spacing-64\"]};\n\n ${MediaQuery.MaxWidth.sm} {\n margin-right: ${Spacing[\"spacing-20\"]};\n margin-left: ${Spacing[\"spacing-20\"]};\n }\n\n display: flex;\n flex-direction: row-reverse; /* primary button on right */\n column-gap: ${Spacing[\"spacing-32\"]};\n row-gap: ${Spacing[\"spacing-16\"]};\n\n & > button {\n flex: 1;\n }\n\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n }\n`;\n\nexport const slotSpacer = css`\n ${slotSpacerTokens.contentLastChildMarginBottom}: initial;\n ${slotSpacerTokens.footerNotFirstChildMarginTop}: initial;\n ${slotSpacerTokens.footerLastChildMarginBottom}: initial;\n ${slotSpacerTokens.firstChildMarginTopWithCloseButton}: initial;\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton}: initial;\n\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton},\n ${Spacing[\"spacing-64\"]}\n );\n\n & > :where(.${contentContainer}:last-child) {\n margin-bottom: var(\n ${slotSpacerTokens.contentLastChildMarginBottom},\n ${Spacing[\"spacing-64\"]}\n );\n }\n\n & > :where(.${footerContainer}:not(:first-child)) {\n margin-top: var(\n ${slotSpacerTokens.footerNotFirstChildMarginTop},\n ${Spacing[\"spacing-32\"]}\n );\n }\n\n & > :where(.${footerContainer}:last-child) {\n margin-bottom: var(\n ${slotSpacerTokens.footerLastChildMarginBottom},\n ${Spacing[\"spacing-64\"]}\n );\n }\n\n &\n > :where(\n .${contentContainer}:first-child, .${footerContainer}:first-child\n ) {\n margin-top: var(${internalSlotSpacerTokens.firstChildMarginTop});\n }\n\n &[${slotSpacerHasCloseButtonAttribute}=\"true\"] {\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopWithCloseButton},\n 0\n );\n }\n\n &[${slotSpacerHasCloseButtonAttribute}=\"false\"] {\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton},\n ${Spacing[\"spacing-64\"]}\n );\n }\n`;\n\nexport const headerContainer = css`\n display: flex;\n align-items: center;\n padding: ${Spacing[\"spacing-16\"]};\n\n &[data-close-button-position=\"right\"] {\n flex-direction: row-reverse;\n }\n`;\n\nexport const headerTitle = css`\n ${Font[\"heading-xs-semibold\"]}\n color: ${Colour.text};\n flex: 1;\n text-align: center;\n`;\n\nexport const headerCloseButton = css`\n padding: 0;\n color: ${Colour.icon};\n flex-shrink: 0;\n\n & svg {\n height: 2rem;\n width: 2rem;\n }\n`;\n\nexport const headerSpacer = css`\n width: 2rem;\n flex-shrink: 0;\n`;\n"],"names":["modalCard","closeButtonContainer","styledClickableIcon","contentContainer","footerContainer","slotSpacer","headerContainer","headerTitle","headerCloseButton","headerSpacer"],"mappings":"gEAuCO,MAAMA,EAAS,UAqCTC,EAAoB,WAOpBC,EAAmB,UAUnBC,EAAgB,WAUhBC,EAAe,WAuBfC,EAAU,WAuDVC,EAAe,WAUfC,EAAW,UAOXC,EAAiB,UAWjBC,EAAY"}
|
|
@@ -23,4 +23,8 @@
|
|
|
23
23
|
);}.s1vsayl1[data-has-close-button="false"]{--fds-internal-modalV2-slotSpacer-firstChildMarginTop:var(
|
|
24
24
|
--fds-internal-modalV2-slotSpacer-firstChildMarginTopNoCloseButton,
|
|
25
25
|
var(--fds-spacing-64)
|
|
26
|
-
);}
|
|
26
|
+
);}
|
|
27
|
+
.h1adf5mq{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:var(--fds-spacing-16);}.h1adf5mq[data-close-button-position="right"]{-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;}
|
|
28
|
+
.hii7rdr{font-family:var(--fds-font-family-heading);font-variant:var(--fds-font-variant);font-size:var(--fds-font-heading-size-xs);font-weight:var(--fds-font-weight-semibold);line-height:var(--fds-font-heading-lh-xs);letter-spacing:var(--fds-font-heading-ls-xs);color:var(--fds-colour-text);-webkit-flex:1;-ms-flex:1;flex:1;text-align:center;}
|
|
29
|
+
.ha88pah{padding:0;color:var(--fds-colour-icon);-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}.ha88pah svg{height:2rem;width:2rem;}
|
|
30
|
+
.h3mtfiz{width:2rem;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}}
|
package/modal-v2/types.d.ts
CHANGED
|
@@ -25,6 +25,27 @@ export interface ModalCloseButtonProps extends React.HTMLAttributes<HTMLDivEleme
|
|
|
25
25
|
*/
|
|
26
26
|
"data-testid"?: string | undefined;
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Props for the `ModalV2.Header` slot.
|
|
30
|
+
*/
|
|
31
|
+
export interface ModalHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
32
|
+
/**
|
|
33
|
+
* @default "modal-header"
|
|
34
|
+
*/
|
|
35
|
+
"data-testid"?: string | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Heading text rendered in the header. Always centered regardless of
|
|
38
|
+
* `closeButtonPosition`. Omit for a close-button-only header.
|
|
39
|
+
*/
|
|
40
|
+
title?: string | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Which side of the header the close button is placed on. The title
|
|
43
|
+
* alignment adjusts automatically.
|
|
44
|
+
*
|
|
45
|
+
* @default "right"
|
|
46
|
+
*/
|
|
47
|
+
closeButtonPosition?: "left" | "right" | undefined;
|
|
48
|
+
}
|
|
28
49
|
/**
|
|
29
50
|
* Props for the `ModalV2.Content` slot.
|
|
30
51
|
*/
|
package/navbar/navbar-items.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{__rest as e}from"../_virtual/_tslib.js";import{jsx as
|
|
1
|
+
import{__rest as e}from"../_virtual/_tslib.js";import{jsx as n,Fragment as i,jsxs as r}from"react/jsx-runtime";import{ChevronUpIcon as t}from"@lifesg/react-icons/chevron-up";import a from"clsx";import{useState as l,useRef as s,useEffect as o}from"react";import{Menu as c}from"../menu/menu.js";import{ClickableIcon as d}from"../shared/clickable-icon/clickable-icon.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import{useId as m}from"../util/simple-id-generator.js";import"../util/string-helper.js";import"@react-aria/live-announcer";import{Menu as u}from"./menu.js";import{mobileWrapper as p,wrapper as h,wrapperAlignLeft as b,link as v,linkSelected as f,linkItem as g,linkItemHiddenBranding as j,linkWeightRegular as N,linkWeightSemibold as k,linkWeightBold as x,linkLabel as $,linkButton as C,chevronIcon as M,chevronIconDesktop as I,chevronIconSelected as O,subMenuExpanded as _,linkIndicator as y,linkIndicatorSelected as L,linkIconContainer as P,expandCollapseButton as w}from"./navbar-items.styles.js";const E=({items:E,selectedId:D,mobile:A=!1,hideNavBranding:B,hideLinkIndicator:F=!1,onItemClick:H})=>{const[S,T]=l(-1),[q,z]=l(!1),[G,J]=l(null),K=s(null),Q=m();o((()=>{const e=e=>{K.current&&!K.current.contains(e.target)&&(z(!1),T(-1),J(null))};return document.addEventListener("click",e,!0),()=>{document.removeEventListener("click",e,!0)}}),[]);const R=(e,n)=>i=>{var r;if(i.stopPropagation(),A&&(null===(r=e.subMenu)||void 0===r?void 0:r.length)){const e=!(S===n&&q);T(n),z(e)}H(i,e)},U=(e,n)=>{e.stopPropagation(),H(e,n),z(!1),T(-1)},V=(e,i)=>n(c.Content,{id:i,children:n(c.Section,{showDivider:!1,children:e.map(((e,i)=>n(c.Link,{href:e.href,children:e.children},`${e.id}-${i}`)))})}),W=e=>n(u,{items:e,onItemClick:U}),X=(l,s)=>{const{children:o,options:m,subMenu:u}=l,p=e(l,["children","options","subMenu"]),h=!!(null==u?void 0:u.length),b=(e=>{var n;return e.id===D||!!(null===(n=e.subMenu)||void 0===n?void 0:n.length)&&!!e.subMenu.find((e=>e.id===D))})(l),H=!A&&h&&G===s,T=A&&h&&S===s&&q,z=H||T,K=null!==G?G===s:b,U=!F&&K,X=A?`link__mobile-${s+1}`:`link__${s+1}`,Y=()=>U?n("div",{"data-testid":`${X}-indicator`,className:a(y,K&&L)}):null,Z=a(v,(e=>{switch(e){case"bold":return x;case"semibold":return k;default:return N}})(K?A?"bold":"semibold":"regular"),K&&f);return n("li",{className:a(g,B&&j),children:h?(e=>{const v=`navbar-submenu-${Q}-${l.id}`;return A?r(i,{children:[r("a",Object.assign({"data-testid":X,className:Z},p,{"aria-current":b?"page":void 0,"aria-haspopup":"menu","aria-expanded":z,onClick:R(l,s)},m,{children:[n("div",{className:$,children:o}),Y(),A&&h?n("div",{className:P,children:n(d,{"data-testid":`${X}-expand-collapse-button`,className:a(w,T&&_),focusHighlight:!1,focusOutline:"browser","aria-label":T?"Collapse":"Expand",children:n(t,{className:a(M,K&&O)})})}):null]})),T&&W(u)]}):n(c,{position:e?"bottom-end":"bottom",customOffset:0,menuContent:V(u,v),triggerOnFocus:!0,isModal:!1,onPopoverAppear:()=>J(s),onPopoverDismiss:()=>{J((e=>e===s?null:e))},children:r("button",Object.assign({type:"button",tabIndex:0,"data-testid":X,className:a(Z,C),"aria-haspopup":"menu","aria-expanded":z},m,{children:[n("div",{className:$,children:o}),Y(),n(t,{className:a(M,I,K&&O,H&&_)})]}))})})(s===E.length-1):r("a",Object.assign({tabIndex:0,"data-testid":X,className:Z},p,{"aria-current":b?"page":void 0,onClick:R(l,s)},m,{children:[n("div",{className:$,children:o}),Y()]}))},s)},Y=()=>E.map(((e,i)=>{var r;return"component"===e.itemType?n("li",{children:null!==(r=e.children)&&void 0!==r?r:null},i):X(e,i)}));return E&&E.length>0?n("ul",A?{ref:K,className:p,children:Y()}:{ref:K,className:a(h,B&&b),children:Y()}):n(i,{})};export{E as NavbarItems};
|
|
2
2
|
//# sourceMappingURL=navbar-items.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navbar-items.js","sources":["../../src/navbar/navbar-items.tsx"],"sourcesContent":["import { ChevronUpIcon } from \"@lifesg/react-icons/chevron-up\";\nimport clsx from \"clsx\";\nimport type React from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { Menu as DesktopMenu } from \"../menu\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport type { TypographyWeight } from \"../typography\";\nimport { useId } from \"../util\";\nimport { Menu as MobileMenu } from \"./menu\";\nimport * as styles from \"./navbar-items.styles\";\nimport type {\n NavItemCommonProps,\n NavItemLinkProps,\n NavItemProps,\n} from \"./types\";\n\nconst getLinkWeightClass = (weight: TypographyWeight) => {\n switch (weight) {\n case \"bold\":\n return styles.linkWeightBold;\n case \"semibold\":\n return styles.linkWeightSemibold;\n case \"regular\":\n default:\n return styles.linkWeightRegular;\n }\n};\n\ninterface Props<T> {\n items: NavItemProps<T>[];\n selectedId?: string | undefined;\n /** toggle for mobile or desktop view */\n mobile?: boolean | undefined;\n hideNavBranding?: boolean | undefined;\n /** hide the selected LinkIndicator */\n hideLinkIndicator?: boolean | undefined;\n onItemClick: (\n event: React.MouseEvent<HTMLAnchorElement>,\n item: NavItemProps<T> | NavItemCommonProps<T>\n ) => void;\n}\n\nexport const NavbarItems = <T,>({\n items,\n selectedId,\n mobile = false,\n hideNavBranding,\n hideLinkIndicator = false,\n onItemClick,\n}: Props<T>): JSX.Element => {\n // =============================================================================\n // CONST, STATE, REFS\n // =============================================================================\n const [selectedIndex, setSelectedIndex] = useState<number>(-1);\n const [showSubMenu, setShowSubMenu] = useState<boolean>(false);\n const [openSubMenuIndex, setOpenSubMenuIndex] = useState<number | null>(\n null\n );\n const listRef = useRef<HTMLUListElement>(null);\n const instanceId = useId();\n\n // =============================================================================\n // HELPERS\n // =============================================================================\n const resetAll = () => {\n setShowSubMenu(false);\n setSelectedIndex(-1);\n setOpenSubMenuIndex(null);\n };\n\n const closeMobileSubMenu = () => {\n setShowSubMenu(false);\n setSelectedIndex(-1);\n };\n\n const checkSelected = (item: NavItemLinkProps<T>): boolean => {\n if (item.id === selectedId) return true;\n if (item.subMenu?.length) {\n return !!item.subMenu.find((s) => s.id === selectedId);\n }\n return false;\n };\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n listRef.current &&\n !listRef.current.contains(event.target as Node)\n ) {\n resetAll();\n }\n };\n document.addEventListener(\"click\", handleClickOutside, true);\n return () => {\n document.removeEventListener(\"click\", handleClickOutside, true);\n };\n }, []);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleLinkClick = (item: NavItemLinkProps<T>, index: number) => {\n return (event: React.MouseEvent<HTMLAnchorElement>) => {\n event.stopPropagation();\n\n // mobile expands inline when link has submenu\n if (mobile && item.subMenu?.length) {\n const nextExpanded = !(selectedIndex === index && showSubMenu);\n setSelectedIndex(index);\n setShowSubMenu(nextExpanded);\n }\n\n onItemClick(event, item);\n };\n };\n\n const handleMobileSubLinkClick = (\n event: React.MouseEvent<HTMLAnchorElement>,\n item: NavItemCommonProps<T>\n ) => {\n event.stopPropagation();\n onItemClick(event, item);\n closeMobileSubMenu();\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderDesktopSubMenu = (\n subMenu: NavItemCommonProps<T>[],\n subMenuId: string\n ) => (\n <DesktopMenu.Content id={subMenuId}>\n <DesktopMenu.Section showDivider={false}>\n {subMenu.map((item, subIndex) => (\n <DesktopMenu.Link\n key={`${item.id}-${subIndex}`}\n href={item.href}\n >\n {item.children}\n </DesktopMenu.Link>\n ))}\n </DesktopMenu.Section>\n </DesktopMenu.Content>\n );\n\n const renderMobileSubMenu = (subMenu: NavItemCommonProps<T>[]) => (\n <MobileMenu items={subMenu} onItemClick={handleMobileSubLinkClick} />\n );\n\n const renderLinkItem = (item: NavItemLinkProps<T>, index: number) => {\n const { children, options, subMenu, ...otherItemAttrs } = item;\n\n const hasSubMenu = !!subMenu?.length;\n\n const isRouteSelected = checkSelected(item);\n\n // desktop popover open state\n const isDesktopExpanded =\n !mobile && hasSubMenu && openSubMenuIndex === index;\n\n // mobile inline expanded state\n const isMobileExpanded =\n mobile && hasSubMenu && selectedIndex === index && showSubMenu;\n\n const isExpanded = isDesktopExpanded || isMobileExpanded;\n\n const selected =\n openSubMenuIndex !== null\n ? openSubMenuIndex === index\n : isRouteSelected;\n\n const showIndicator = !hideLinkIndicator && selected;\n\n const textWeight: TypographyWeight = selected\n ? mobile\n ? \"bold\"\n : \"semibold\"\n : \"regular\";\n\n const testId = mobile\n ? `link__mobile-${index + 1}`\n : `link__${index + 1}`;\n\n const renderIndicator = () =>\n showIndicator ? (\n <div\n data-testid={`${testId}-indicator`}\n className={clsx(\n styles.linkIndicator,\n selected && styles.linkIndicatorSelected\n )}\n />\n ) : null;\n\n const renderMobileChevron = () =>\n mobile && hasSubMenu ? (\n <div className={styles.linkIconContainer}>\n <ClickableIcon\n data-testid={`${testId}-expand-collapse-button`}\n className={clsx(\n styles.expandCollapseButton,\n isMobileExpanded &&\n styles.expandCollapseButtonExpanded\n )}\n focusHighlight={false}\n focusOutline=\"browser\"\n aria-label={isMobileExpanded ? \"Collapse\" : \"Expand\"}\n >\n <ChevronUpIcon\n className={clsx(\n styles.chevronIcon,\n selected && styles.chevronIconSelected\n )}\n />\n </ClickableIcon>\n </div>\n ) : null;\n\n const linkClassName = clsx(\n styles.link,\n getLinkWeightClass(textWeight),\n selected && styles.linkSelected\n );\n\n const renderLink = () => (\n <a\n tabIndex={0}\n data-testid={testId}\n className={linkClassName}\n {...otherItemAttrs}\n aria-current={isRouteSelected ? \"page\" : undefined}\n onClick={handleLinkClick(item, index)}\n {...options}\n >\n <div className={styles.linkLabel}>{children}</div>\n {renderIndicator()}\n </a>\n );\n\n const renderLinkWithSubmenu = () => {\n const subMenuId = `navbar-submenu-${instanceId}-${item.id}`;\n\n if (mobile) {\n return (\n <>\n <a\n data-testid={testId}\n className={linkClassName}\n {...otherItemAttrs}\n aria-current={isRouteSelected ? \"page\" : undefined}\n aria-haspopup=\"menu\"\n aria-expanded={isExpanded}\n onClick={handleLinkClick(item, index)}\n {...options}\n >\n <div className={styles.linkLabel}>{children}</div>\n {renderIndicator()}\n {renderMobileChevron()}\n </a>\n\n {isMobileExpanded && renderMobileSubMenu(subMenu!)}\n </>\n );\n }\n\n return (\n <DesktopMenu\n position=\"bottom\"\n customOffset={0}\n menuContent={renderDesktopSubMenu(subMenu!, subMenuId)}\n triggerOnFocus\n isModal={false}\n onPopoverAppear={() => setOpenSubMenuIndex(index)}\n onPopoverDismiss={() => {\n setOpenSubMenuIndex((prev) =>\n prev === index ? null : prev\n );\n }}\n >\n <button\n type=\"button\"\n tabIndex={0}\n data-testid={testId}\n className={clsx(linkClassName, styles.linkButton)}\n aria-haspopup=\"menu\"\n aria-expanded={isExpanded}\n {...options}\n >\n <div className={styles.linkLabel}>{children}</div>\n {renderIndicator()}\n </button>\n </DesktopMenu>\n );\n };\n\n return (\n <li\n key={index}\n className={clsx(\n styles.linkItem,\n hideNavBranding && styles.linkItemHiddenBranding\n )}\n >\n {hasSubMenu ? renderLinkWithSubmenu() : renderLink()}\n </li>\n );\n };\n\n const renderItems = () =>\n items.map((item, index) => {\n switch (item.itemType) {\n case \"component\": {\n return <li key={index}>{item.children ?? null}</li>;\n }\n case \"link\":\n default: {\n return renderLinkItem(item as NavItemLinkProps<T>, index);\n }\n }\n });\n\n if (items && items.length > 0) {\n return mobile ? (\n <ul ref={listRef} className={styles.mobileWrapper}>\n {renderItems()}\n </ul>\n ) : (\n <ul\n ref={listRef}\n className={clsx(\n styles.wrapper,\n hideNavBranding && styles.wrapperAlignLeft\n )}\n >\n {renderItems()}\n </ul>\n );\n }\n\n return <></>;\n};\n"],"names":["NavbarItems","items","selectedId","mobile","hideNavBranding","hideLinkIndicator","onItemClick","selectedIndex","setSelectedIndex","useState","showSubMenu","setShowSubMenu","openSubMenuIndex","setOpenSubMenuIndex","listRef","useRef","instanceId","useId","useEffect","handleClickOutside","event","current","contains","target","document","addEventListener","removeEventListener","handleLinkClick","item","index","stopPropagation","_a","subMenu","length","nextExpanded","handleMobileSubLinkClick","renderDesktopSubMenu","subMenuId","_jsx","DesktopMenu","Content","id","children","Section","showDivider","map","subIndex","Link","href","renderMobileSubMenu","MobileMenu","renderLinkItem","options","otherItemAttrs","__rest","hasSubMenu","isRouteSelected","find","s","checkSelected","isMobileExpanded","isExpanded","selected","showIndicator","testId","renderIndicator","className","clsx","styles.linkIndicator","styles.linkIndicatorSelected","linkClassName","styles.link","weight","styles.linkWeightBold","styles.linkWeightSemibold","styles.linkWeightRegular","getLinkWeightClass","styles.linkSelected","styles.linkItem","styles.linkItemHiddenBranding","_jsxs","_Fragment","Object","assign","undefined","onClick","styles.linkLabel","styles.linkIconContainer","ClickableIcon","styles.expandCollapseButton","styles.expandCollapseButtonExpanded","focusHighlight","focusOutline","ChevronUpIcon","styles.chevronIcon","styles.chevronIconSelected","position","customOffset","menuContent","triggerOnFocus","isModal","onPopoverAppear","onPopoverDismiss","prev","type","tabIndex","styles.linkButton","renderLinkWithSubmenu","renderItems","itemType","ref","styles.mobileWrapper","styles.wrapper","styles.wrapperAlignLeft"],"mappings":"qgCAiBA,MA0BaA,EAAc,EACvBC,QACAC,aACAC,UAAS,EACTC,kBACAC,qBAAoB,EACpBC,kBAKA,MAAOC,EAAeC,GAAoBC,GAAiB,IACpDC,EAAaC,GAAkBF,GAAkB,IACjDG,EAAkBC,GAAuBJ,EAC5C,MAEEK,EAAUC,EAAyB,MACnCC,EAAaC,IAwBnBC,GAAU,KACN,MAAMC,EAAsBC,IAEpBN,EAAQO,UACPP,EAAQO,QAAQC,SAASF,EAAMG,UAtBxCZ,GAAe,GACfH,GAAiB,GACjBK,EAAoB,MAuBhB,EAGJ,OADAW,SAASC,iBAAiB,QAASN,GAAoB,GAChD,KACHK,SAASE,oBAAoB,QAASP,GAAoB,EAAK,CAClE,GACF,IAKH,MAAMQ,EAAkB,CAACC,EAA2BC,IACxCT,UAIJ,GAHAA,EAAMU,kBAGF3B,IAAsB,QAAZ4B,EAAAH,EAAKI,eAAO,IAAAD,OAAA,EAAAA,EAAEE,QAAQ,CAChC,MAAMC,IAAiB3B,IAAkBsB,GAASnB,GAClDF,EAAiBqB,GACjBlB,EAAeuB,EACnB,CAEA5B,EAAYc,EAAOQ,EAAK,EAI1BO,EAA2B,CAC7Bf,EACAQ,KAEAR,EAAMU,kBACNxB,EAAYc,EAAOQ,GAlDnBjB,GAAe,GACfH,GAAiB,EAkDG,EAMlB4B,EAAuB,CACzBJ,EACAK,IAEAC,EAACC,EAAYC,QAAO,CAACC,GAAIJ,EAASK,SAC9BJ,EAACC,EAAYI,QAAO,CAACC,aAAa,EAAKF,SAClCV,EAAQa,KAAI,CAACjB,EAAMkB,IAChBR,EAACC,EAAYQ,KAAI,CAEbC,KAAMpB,EAAKoB,KAAIN,SAEdd,EAAKc,UAHD,GAAGd,EAAKa,MAAMK,WAUjCG,EAAuBjB,GACzBM,EAACY,GAAWjD,MAAO+B,EAAS1B,YAAa6B,IAGvCgB,EAAiB,CAACvB,EAA2BC,KAC/C,MAAMa,SAAEA,EAAQU,QAAEA,EAAOpB,QAAEA,GAA+BJ,EAAnByB,EAAcC,EAAK1B,EAApD,CAAA,WAAA,UAAA,YAEA2B,KAAevB,aAAO,EAAPA,EAASC,QAExBuB,EAhFY,CAAC5B,UACnB,OAAIA,EAAKa,KAAOvC,MACA,UAAZ0B,EAAKI,eAAO,IAAAD,OAAA,EAAAA,EAAEE,WACLL,EAAKI,QAAQyB,MAAMC,GAAMA,EAAEjB,KAAOvC,GAEnC,EA2EYyD,CAAc/B,GAOhCgC,EACFzD,GAAUoD,GAAchD,IAAkBsB,GAASnB,EAEjDmD,GAND1D,GAAUoD,GAAc3C,IAAqBiB,GAMV+B,EAElCE,EACmB,OAArBlD,EACMA,IAAqBiB,EACrB2B,EAEJO,GAAiB1D,GAAqByD,EAQtCE,EAAS7D,EACT,gBAAgB0B,EAAQ,IACxB,SAASA,EAAQ,IAEjBoC,EAAkB,IACpBF,EACIzB,EAAA,MAAA,CAAA,cACiB,GAAG0B,cAChBE,UAAWC,EACPC,EACAN,GAAYO,KAGpB,KA0BFC,EAAgBH,EAClBI,EA5Me,CAACC,IACxB,OAAQA,GACJ,IAAK,OACD,OAAOC,EACX,IAAK,WACD,OAAOC,EAEX,QACI,OAAOC,IAqMPC,CA/CiCd,EAC/B3D,EACI,OACA,WACJ,WA4CF2D,GAAYe,GA0EhB,OACIvC,EAAA,KAAA,CAEI4B,UAAWC,EACPW,EACA1E,GAAmB2E,GACtBrC,SAEAa,EAhEqB,MAC1B,MAAMlB,EAAY,kBAAkBrB,KAAcY,EAAKa,KAEvD,OAAItC,EAEI6E,EAAAC,EAAA,CAAAvC,SAAA,CACIsC,EAAA,IAAAE,OAAAC,OAAA,CAAA,cACiBnB,EACbE,UAAWI,GACPjB,EAAc,CAAA,eACJG,EAAkB,YAAS4B,EAAS,gBACpC,OAAM,gBACLvB,EACfwB,QAAS1D,EAAgBC,EAAMC,IAC3BuB,EAAO,CAAAV,SAAA,CAEXJ,EAAA,MAAA,CAAK4B,UAAWoB,EAAgB5C,SAAGA,IAClCuB,IA7DjB9D,GAAUoD,EACNjB,EAAA,MAAA,CAAK4B,UAAWqB,EAAwB7C,SACpCJ,EAACkD,EAAa,CAAA,cACG,GAAGxB,2BAChBE,UAAWC,EACPsB,EACA7B,GACI8B,GAERC,gBAAgB,EAChBC,aAAa,UAAS,aACVhC,EAAmB,WAAa,SAAQlB,SAEpDJ,EAACuD,EAAa,CACV3B,UAAWC,EACP2B,EACAhC,GAAYiC,SAK5B,SA4CSnC,GAAoBX,EAAoBjB,MAMjDM,EAACC,GACGyD,SAAS,SACTC,aAAc,EACdC,YAAa9D,EAAqBJ,EAAUK,GAC5C8D,kBACAC,SAAS,EACTC,gBAAiB,IAAMxF,EAAoBgB,GAC3CyE,iBAAkB,KACdzF,GAAqB0F,GACjBA,IAAS1E,EAAQ,KAAO0E,GAC3B,EACJ7D,SAEDsC,0BACIwB,KAAK,SACLC,SAAU,EAAC,cACEzC,EACbE,UAAWC,EAAKG,EAAeoC,mBACjB,OAAM,gBACL7C,GACXT,aAEJd,EAAA,MAAA,CAAK4B,UAAWoB,EAAgB5C,SAAGA,IAClCuB,SAEK,EAYA0C,GA9ElB3B,EAAA,IAAAE,OAAAC,OAAA,CACIsB,SAAU,EAAC,cACEzC,EACbE,UAAWI,GACPjB,EAAc,CAAA,eACJG,EAAkB,YAAS4B,EACzCC,QAAS1D,EAAgBC,EAAMC,IAC3BuB,EAAO,CAAAV,SAAA,CAEXJ,EAAA,MAAA,CAAK4B,UAAWoB,EAAgB5C,SAAGA,IAClCuB,SA8DIpC,EAOJ,EAIP+E,EAAc,IAChB3G,EAAM4C,KAAI,CAACjB,EAAMC,WACb,MACS,cADDD,EAAKiF,SAEEvE,EAAA,KAAA,CAAAI,iBAAiBX,EAAAH,EAAKc,wBAAY,MAAzBb,GAITsB,EAAevB,EAA6BC,MAKnE,OAAI5B,GAASA,EAAMgC,OAAS,EAEpBK,EAAA,KADGnC,EACH,CAAI2G,IAAKhG,EAASoD,UAAW6C,EAAoBrE,SAC5CkE,MAIDE,IAAKhG,EACLoD,UAAWC,EACP6C,EACA5G,GAAmB6G,YAGtBL,MAKNtE,OAAK"}
|
|
1
|
+
{"version":3,"file":"navbar-items.js","sources":["../../src/navbar/navbar-items.tsx"],"sourcesContent":["import { ChevronUpIcon } from \"@lifesg/react-icons/chevron-up\";\nimport clsx from \"clsx\";\nimport type React from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { Menu as DesktopMenu } from \"../menu\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport type { TypographyWeight } from \"../typography\";\nimport { useId } from \"../util\";\nimport { Menu as MobileMenu } from \"./menu\";\nimport * as styles from \"./navbar-items.styles\";\nimport type {\n NavItemCommonProps,\n NavItemLinkProps,\n NavItemProps,\n} from \"./types\";\n\nconst getLinkWeightClass = (weight: TypographyWeight) => {\n switch (weight) {\n case \"bold\":\n return styles.linkWeightBold;\n case \"semibold\":\n return styles.linkWeightSemibold;\n case \"regular\":\n default:\n return styles.linkWeightRegular;\n }\n};\n\ninterface Props<T> {\n items: NavItemProps<T>[];\n selectedId?: string | undefined;\n /** toggle for mobile or desktop view */\n mobile?: boolean | undefined;\n hideNavBranding?: boolean | undefined;\n /** hide the selected LinkIndicator */\n hideLinkIndicator?: boolean | undefined;\n onItemClick: (\n event: React.MouseEvent<HTMLAnchorElement>,\n item: NavItemProps<T> | NavItemCommonProps<T>\n ) => void;\n}\n\nexport const NavbarItems = <T,>({\n items,\n selectedId,\n mobile = false,\n hideNavBranding,\n hideLinkIndicator = false,\n onItemClick,\n}: Props<T>): JSX.Element => {\n // =============================================================================\n // CONST, STATE, REFS\n // =============================================================================\n const [selectedIndex, setSelectedIndex] = useState<number>(-1);\n const [showSubMenu, setShowSubMenu] = useState<boolean>(false);\n const [openSubMenuIndex, setOpenSubMenuIndex] = useState<number | null>(\n null\n );\n const listRef = useRef<HTMLUListElement>(null);\n const instanceId = useId();\n\n // =============================================================================\n // HELPERS\n // =============================================================================\n const resetAll = () => {\n setShowSubMenu(false);\n setSelectedIndex(-1);\n setOpenSubMenuIndex(null);\n };\n\n const closeMobileSubMenu = () => {\n setShowSubMenu(false);\n setSelectedIndex(-1);\n };\n\n const checkSelected = (item: NavItemLinkProps<T>): boolean => {\n if (item.id === selectedId) return true;\n if (item.subMenu?.length) {\n return !!item.subMenu.find((s) => s.id === selectedId);\n }\n return false;\n };\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n listRef.current &&\n !listRef.current.contains(event.target as Node)\n ) {\n resetAll();\n }\n };\n document.addEventListener(\"click\", handleClickOutside, true);\n return () => {\n document.removeEventListener(\"click\", handleClickOutside, true);\n };\n }, []);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleLinkClick = (item: NavItemLinkProps<T>, index: number) => {\n return (event: React.MouseEvent<HTMLAnchorElement>) => {\n event.stopPropagation();\n\n // mobile expands inline when link has submenu\n if (mobile && item.subMenu?.length) {\n const nextExpanded = !(selectedIndex === index && showSubMenu);\n setSelectedIndex(index);\n setShowSubMenu(nextExpanded);\n }\n\n onItemClick(event, item);\n };\n };\n\n const handleMobileSubLinkClick = (\n event: React.MouseEvent<HTMLAnchorElement>,\n item: NavItemCommonProps<T>\n ) => {\n event.stopPropagation();\n onItemClick(event, item);\n closeMobileSubMenu();\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderDesktopSubMenu = (\n subMenu: NavItemCommonProps<T>[],\n subMenuId: string\n ) => (\n <DesktopMenu.Content id={subMenuId}>\n <DesktopMenu.Section showDivider={false}>\n {subMenu.map((item, subIndex) => (\n <DesktopMenu.Link\n key={`${item.id}-${subIndex}`}\n href={item.href}\n >\n {item.children}\n </DesktopMenu.Link>\n ))}\n </DesktopMenu.Section>\n </DesktopMenu.Content>\n );\n\n const renderMobileSubMenu = (subMenu: NavItemCommonProps<T>[]) => (\n <MobileMenu items={subMenu} onItemClick={handleMobileSubLinkClick} />\n );\n\n const renderLinkItem = (item: NavItemLinkProps<T>, index: number) => {\n const { children, options, subMenu, ...otherItemAttrs } = item;\n\n const hasSubMenu = !!subMenu?.length;\n\n const isRouteSelected = checkSelected(item);\n\n // desktop popover open state\n const isDesktopExpanded =\n !mobile && hasSubMenu && openSubMenuIndex === index;\n\n // mobile inline expanded state\n const isMobileExpanded =\n mobile && hasSubMenu && selectedIndex === index && showSubMenu;\n\n const isExpanded = isDesktopExpanded || isMobileExpanded;\n\n const selected =\n openSubMenuIndex !== null\n ? openSubMenuIndex === index\n : isRouteSelected;\n\n const showIndicator = !hideLinkIndicator && selected;\n\n const textWeight: TypographyWeight = selected\n ? mobile\n ? \"bold\"\n : \"semibold\"\n : \"regular\";\n\n const testId = mobile\n ? `link__mobile-${index + 1}`\n : `link__${index + 1}`;\n\n const renderIndicator = () =>\n showIndicator ? (\n <div\n data-testid={`${testId}-indicator`}\n className={clsx(\n styles.linkIndicator,\n selected && styles.linkIndicatorSelected\n )}\n />\n ) : null;\n\n const renderMobileChevron = () =>\n mobile && hasSubMenu ? (\n <div className={styles.linkIconContainer}>\n <ClickableIcon\n data-testid={`${testId}-expand-collapse-button`}\n className={clsx(\n styles.expandCollapseButton,\n isMobileExpanded && styles.subMenuExpanded\n )}\n focusHighlight={false}\n focusOutline=\"browser\"\n aria-label={isMobileExpanded ? \"Collapse\" : \"Expand\"}\n >\n <ChevronUpIcon\n className={clsx(\n styles.chevronIcon,\n selected && styles.chevronIconSelected\n )}\n />\n </ClickableIcon>\n </div>\n ) : null;\n\n const linkClassName = clsx(\n styles.link,\n getLinkWeightClass(textWeight),\n selected && styles.linkSelected\n );\n\n const renderLink = () => (\n <a\n tabIndex={0}\n data-testid={testId}\n className={linkClassName}\n {...otherItemAttrs}\n aria-current={isRouteSelected ? \"page\" : undefined}\n onClick={handleLinkClick(item, index)}\n {...options}\n >\n <div className={styles.linkLabel}>{children}</div>\n {renderIndicator()}\n </a>\n );\n\n const renderLinkWithSubmenu = (isLastItem: boolean) => {\n const subMenuId = `navbar-submenu-${instanceId}-${item.id}`;\n\n if (mobile) {\n return (\n <>\n <a\n data-testid={testId}\n className={linkClassName}\n {...otherItemAttrs}\n aria-current={isRouteSelected ? \"page\" : undefined}\n aria-haspopup=\"menu\"\n aria-expanded={isExpanded}\n onClick={handleLinkClick(item, index)}\n {...options}\n >\n <div className={styles.linkLabel}>{children}</div>\n {renderIndicator()}\n {renderMobileChevron()}\n </a>\n\n {isMobileExpanded && renderMobileSubMenu(subMenu!)}\n </>\n );\n }\n\n return (\n <DesktopMenu\n position={isLastItem ? \"bottom-end\" : \"bottom\"}\n customOffset={0}\n menuContent={renderDesktopSubMenu(subMenu!, subMenuId)}\n triggerOnFocus\n isModal={false}\n onPopoverAppear={() => setOpenSubMenuIndex(index)}\n onPopoverDismiss={() => {\n setOpenSubMenuIndex((prev) =>\n prev === index ? null : prev\n );\n }}\n >\n <button\n type=\"button\"\n tabIndex={0}\n data-testid={testId}\n className={clsx(linkClassName, styles.linkButton)}\n aria-haspopup=\"menu\"\n aria-expanded={isExpanded}\n {...options}\n >\n <div className={styles.linkLabel}>{children}</div>\n {renderIndicator()}\n <ChevronUpIcon\n className={clsx(\n styles.chevronIcon,\n styles.chevronIconDesktop,\n selected && styles.chevronIconSelected,\n isDesktopExpanded && styles.subMenuExpanded\n )}\n />\n </button>\n </DesktopMenu>\n );\n };\n\n return (\n <li\n key={index}\n className={clsx(\n styles.linkItem,\n hideNavBranding && styles.linkItemHiddenBranding\n )}\n >\n {hasSubMenu\n ? renderLinkWithSubmenu(index === items.length - 1)\n : renderLink()}\n </li>\n );\n };\n\n const renderItems = () =>\n items.map((item, index) => {\n switch (item.itemType) {\n case \"component\": {\n return <li key={index}>{item.children ?? null}</li>;\n }\n case \"link\":\n default: {\n return renderLinkItem(item as NavItemLinkProps<T>, index);\n }\n }\n });\n\n if (items && items.length > 0) {\n return mobile ? (\n <ul ref={listRef} className={styles.mobileWrapper}>\n {renderItems()}\n </ul>\n ) : (\n <ul\n ref={listRef}\n className={clsx(\n styles.wrapper,\n hideNavBranding && styles.wrapperAlignLeft\n )}\n >\n {renderItems()}\n </ul>\n );\n }\n\n return <></>;\n};\n"],"names":["NavbarItems","items","selectedId","mobile","hideNavBranding","hideLinkIndicator","onItemClick","selectedIndex","setSelectedIndex","useState","showSubMenu","setShowSubMenu","openSubMenuIndex","setOpenSubMenuIndex","listRef","useRef","instanceId","useId","useEffect","handleClickOutside","event","current","contains","target","document","addEventListener","removeEventListener","handleLinkClick","item","index","stopPropagation","_a","subMenu","length","nextExpanded","handleMobileSubLinkClick","renderDesktopSubMenu","subMenuId","_jsx","DesktopMenu","Content","id","children","Section","showDivider","map","subIndex","Link","href","renderMobileSubMenu","MobileMenu","renderLinkItem","options","otherItemAttrs","__rest","hasSubMenu","isRouteSelected","find","s","checkSelected","isDesktopExpanded","isMobileExpanded","isExpanded","selected","showIndicator","testId","renderIndicator","className","clsx","styles.linkIndicator","styles.linkIndicatorSelected","linkClassName","styles.link","weight","styles.linkWeightBold","styles.linkWeightSemibold","styles.linkWeightRegular","getLinkWeightClass","styles.linkSelected","styles.linkItem","styles.linkItemHiddenBranding","isLastItem","_jsxs","_Fragment","Object","assign","undefined","onClick","styles.linkLabel","styles.linkIconContainer","ClickableIcon","styles.expandCollapseButton","styles.subMenuExpanded","focusHighlight","focusOutline","ChevronUpIcon","styles.chevronIcon","styles.chevronIconSelected","position","customOffset","menuContent","triggerOnFocus","isModal","onPopoverAppear","onPopoverDismiss","prev","type","tabIndex","styles.linkButton","styles.chevronIconDesktop","renderLinkWithSubmenu","renderItems","itemType","ref","styles.mobileWrapper","styles.wrapper","styles.wrapperAlignLeft"],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@ export declare const linkIndicator: import("@linaria/core").LinariaClassName;
|
|
|
14
14
|
export declare const linkIndicatorSelected: import("@linaria/core").LinariaClassName;
|
|
15
15
|
export declare const linkIconContainer: import("@linaria/core").LinariaClassName;
|
|
16
16
|
export declare const expandCollapseButton: import("@linaria/core").LinariaClassName;
|
|
17
|
-
export declare const expandCollapseButtonExpanded: import("@linaria/core").LinariaClassName;
|
|
18
17
|
export declare const chevronIcon: import("@linaria/core").LinariaClassName;
|
|
18
|
+
export declare const chevronIconDesktop: import("@linaria/core").LinariaClassName;
|
|
19
|
+
export declare const subMenuExpanded: import("@linaria/core").LinariaClassName;
|
|
19
20
|
export declare const chevronIconSelected: import("@linaria/core").LinariaClassName;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"./navbar-items.
|
|
1
|
+
import"./navbar-items.styles_1b1zx.css";const s="w1ndf2sj",l="w177nfye",n="mw9gug8",c="l18t6f3m",e="lsn8o0d",o="l1o3p4yu",r="lkwvsmx",t="l1kp5n19",x="lqgrg2a",a="l1p7dxu8",f="l1xfqf3s",m="lsc0hr8",p="lnocj2s",u="l5qfat1",g="l1p9u80z",w="ej7h5do",d="c160mxwv",k="c1s8ur0k",v="s178e7hk",_="c1euxgs0";export{d as chevronIcon,k as chevronIconDesktop,_ as chevronIconSelected,w as expandCollapseButton,o as link,f as linkButton,g as linkIconContainer,p as linkIndicator,u as linkIndicatorSelected,c as linkItem,e as linkItemHiddenBranding,m as linkLabel,r as linkSelected,a as linkWeightBold,t as linkWeightRegular,x as linkWeightSemibold,n as mobileWrapper,v as subMenuExpanded,s as wrapper,l as wrapperAlignLeft};
|
|
2
2
|
//# sourceMappingURL=navbar-items.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navbar-items.styles.js","sources":["../../src/navbar/navbar-items.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Colour, ComponentToken, Font, MediaQuery } from \"../theme\";\n\n// =============================================================================\n// WRAPPER\n// =============================================================================\n\nexport const wrapper = css`\n display: flex;\n list-style: none;\n position: relative;\n\n ${MediaQuery.MaxWidth.lg} {\n display: none;\n }\n`;\n\nexport const wrapperAlignLeft = css`\n margin-right: auto;\n`;\n\nexport const mobileWrapper = css`\n display: none;\n list-style: none;\n\n ${MediaQuery.MaxWidth.lg} {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n`;\n\n// =============================================================================\n// LINK ITEMS\n// =============================================================================\nexport const linkItem = css`\n display: flex;\n margin: 0 1rem;\n &:first-child {\n margin-left: 0;\n }\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: column;\n padding: 0.125rem 0;\n width: 100%;\n margin-left: 0rem;\n }\n`;\n\nexport const linkItemHiddenBranding = css`\n // negative margin to preserve touch target size for link\n &:first-child {\n margin-left: -0.5rem;\n }\n\n ${MediaQuery.MaxWidth.lg} {\n &:first-child {\n margin-left: 0rem;\n }\n }\n`;\n\nexport const link = css`\n display: flex;\n position: relative;\n align-items: center;\n text-align: center;\n color: ${ComponentToken.Navbar[\"link-colour-text\"]};\n height: 100%;\n\n &:active,\n &:hover,\n &:focus,\n &:focus-within {\n color: ${ComponentToken.Navbar[\"link-colour-text-hover\"]};\n }\n\n ${MediaQuery.MaxWidth.lg} {\n width: 100%;\n padding: 0.5rem 1rem;\n text-align: left;\n
|
|
1
|
+
{"version":3,"file":"navbar-items.styles.js","sources":["../../src/navbar/navbar-items.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Colour, ComponentToken, Font, MediaQuery } from \"../theme\";\n\n// =============================================================================\n// WRAPPER\n// =============================================================================\n\nexport const wrapper = css`\n display: flex;\n list-style: none;\n position: relative;\n\n ${MediaQuery.MaxWidth.lg} {\n display: none;\n }\n`;\n\nexport const wrapperAlignLeft = css`\n margin-right: auto;\n`;\n\nexport const mobileWrapper = css`\n display: none;\n list-style: none;\n\n ${MediaQuery.MaxWidth.lg} {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n`;\n\n// =============================================================================\n// LINK ITEMS\n// =============================================================================\nexport const linkItem = css`\n display: flex;\n margin: 0 1rem;\n &:first-child {\n margin-left: 0;\n }\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: column;\n padding: 0.125rem 0;\n width: 100%;\n margin-left: 0rem;\n }\n`;\n\nexport const linkItemHiddenBranding = css`\n // negative margin to preserve touch target size for link\n &:first-child {\n margin-left: -0.5rem;\n }\n\n ${MediaQuery.MaxWidth.lg} {\n &:first-child {\n margin-left: 0rem;\n }\n }\n`;\n\nexport const link = css`\n display: flex;\n position: relative;\n align-items: center;\n text-align: center;\n color: ${ComponentToken.Navbar[\"link-colour-text\"]};\n height: 100%;\n gap: 0.5rem;\n\n &:active,\n &:hover,\n &:focus,\n &:focus-within {\n color: ${ComponentToken.Navbar[\"link-colour-text-hover\"]};\n }\n\n ${MediaQuery.MaxWidth.lg} {\n width: 100%;\n padding: 0.5rem 1rem;\n text-align: left;\n }\n`;\n\nexport const linkSelected = css`\n &:active,\n &:hover,\n &:focus {\n color: ${ComponentToken.Navbar[\"link-colour-text-selected-hover\"]};\n }\n`;\n\nexport const linkWeightRegular = css`\n ${Font[\"body-md-regular\"]}\n`;\n\nexport const linkWeightSemibold = css`\n ${Font[\"body-md-semibold\"]}\n`;\n\nexport const linkWeightBold = css`\n ${Font[\"body-md-bold\"]}\n`;\n\nexport const linkButton = css`\n background: none;\n border: 0;\n padding: 0;\n cursor: pointer;\n text-align: left;\n margin: 0;\n box-shadow: none;\n font: inherit;\n color: inherit;\n gap: 8px;\n`;\n\nexport const linkLabel = css`\n flex: 1;\n\n overflow: hidden;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 3;\n white-space: pre-wrap;\n`;\n\nexport const linkIndicator = css`\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 0.25rem;\n background-color: ${Colour[\"border-selected\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n left: 0;\n right: unset;\n top: 0;\n bottom: 0;\n height: 100%;\n width: 0.25rem;\n }\n`;\n\nexport const linkIndicatorSelected = css`\n .${link}:active &,\n .${link}:hover &,\n .${link}:focus & {\n background-color: ${Colour[\"border-selected-hover\"]};\n }\n`;\n\nexport const linkIconContainer = css`\n margin-right: -0.5rem;\n`;\n\nexport const expandCollapseButton = css`\n padding: 0.5rem;\n margin: auto 0.25rem auto 0;\n`;\n\nexport const chevronIcon = css`\n height: 1.25rem;\n width: 1.25rem;\n color: ${Colour.icon};\n transition: transform 300ms ease-in-out;\n transform: rotate(180deg);\n\n .${link}:active &,\n .${link}:hover &,\n .${link}:focus & {\n color: ${Colour[\"icon-hover\"]};\n }\n`;\n\nexport const chevronIconDesktop = css`\n height: 1.125rem;\n width: 1.125rem;\n`;\n\nexport const subMenuExpanded = css`\n transform: rotate(0deg);\n`;\n\nexport const chevronIconSelected = css`\n .${link}:active &,\n .${link}:hover &,\n .${link}:focus & {\n color: ${Colour[\"icon-selected-hover\"]};\n }\n`;\n"],"names":["wrapper","wrapperAlignLeft","mobileWrapper","linkItem","linkItemHiddenBranding","link","linkSelected","linkWeightRegular","linkWeightSemibold","linkWeightBold","linkButton","linkLabel","linkIndicator","linkIndicatorSelected","linkIconContainer","expandCollapseButton","chevronIcon","chevronIconDesktop","subMenuExpanded","chevronIconSelected"],"mappings":"8DAQO,MAAMA,EAAO,WAUPC,EAAgB,WAIhBC,EAAa,UAcbC,EAAQ,WAeRC,EAAsB,UAatBC,EAAI,WAuBJC,EAAY,UAQZC,EAAiB,WAIjBC,EAAkB,UAIlBC,EAAc,WAIdC,EAAU,WAaVC,EAAS,UAUTC,EAAa,UAkBbC,EAAqB,UAQrBC,EAAiB,WAIjBC,EAAoB,UAKpBC,EAAW,WAcXC,EAAkB,WAKlBC,EAAe,WAIfC,EAAmB"}
|
|
@@ -3,17 +3,18 @@
|
|
|
3
3
|
.mw9gug8{display:none;list-style:none;}:where(body.fds-breakpoint-lg-max) .mw9gug8{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;overflow:hidden;}
|
|
4
4
|
.l18t6f3m{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin:0 1rem;}.l18t6f3m:first-child{margin-left:0;}:where(body.fds-breakpoint-lg-max) .l18t6f3m{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding:0.125rem 0;width:100%;margin-left:0rem;}
|
|
5
5
|
.lsn8o0d:first-child{margin-left:-0.5rem;}:where(body.fds-breakpoint-lg-max) .lsn8o0d:first-child{margin-left:0rem;}
|
|
6
|
-
.l1o3p4yu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;position:relative;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;text-align:center;color:var(--fds-navbar-link-colour-text);height:100%;}.l1o3p4yu:active,.l1o3p4yu:hover,.l1o3p4yu:focus,.l1o3p4yu:focus-within{color:var(--fds-navbar-link-colour-text-hover);}:where(body.fds-breakpoint-lg-max) .l1o3p4yu{width:100%;padding:0.5rem 1rem;text-align:left
|
|
6
|
+
.l1o3p4yu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;position:relative;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;text-align:center;color:var(--fds-navbar-link-colour-text);height:100%;gap:0.5rem;}.l1o3p4yu:active,.l1o3p4yu:hover,.l1o3p4yu:focus,.l1o3p4yu:focus-within{color:var(--fds-navbar-link-colour-text-hover);}:where(body.fds-breakpoint-lg-max) .l1o3p4yu{width:100%;padding:0.5rem 1rem;text-align:left;}
|
|
7
7
|
.lkwvsmx:active,.lkwvsmx:hover,.lkwvsmx:focus{color:var(--fds-navbar-link-colour-text-selected-hover);}
|
|
8
8
|
.l1kp5n19{font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-body-size-md);font-weight:var(--fds-font-weight-regular);line-height:var(--fds-font-body-lh-md);letter-spacing:var(--fds-font-body-ls-md);}
|
|
9
9
|
.lqgrg2a{font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-body-size-md);font-weight:var(--fds-font-weight-semibold);line-height:var(--fds-font-body-lh-md);letter-spacing:var(--fds-font-body-ls-md);}
|
|
10
10
|
.l1p7dxu8{font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-body-size-md);font-weight:var(--fds-font-weight-bold);line-height:var(--fds-font-body-lh-md);letter-spacing:var(--fds-font-body-ls-md);}
|
|
11
|
-
.l1xfqf3s{background:none;border:0;padding:0;cursor:pointer;text-align:left;margin:0;box-shadow:none;font:inherit;color:inherit;}
|
|
12
|
-
.lsc0hr8{-webkit-flex:1;-ms-flex:1;flex:1;
|
|
11
|
+
.l1xfqf3s{background:none;border:0;padding:0;cursor:pointer;text-align:left;margin:0;box-shadow:none;font:inherit;color:inherit;gap:8px;}
|
|
12
|
+
.lsc0hr8{-webkit-flex:1;-ms-flex:1;flex:1;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;white-space:pre-wrap;}
|
|
13
13
|
.lnocj2s{position:absolute;bottom:0;left:0;right:0;height:0.25rem;background-color:var(--fds-colour-border-selected);}:where(body.fds-breakpoint-lg-max) .lnocj2s{left:0;right:unset;top:0;bottom:0;height:100%;width:0.25rem;}
|
|
14
14
|
.l1o3p4yu:active .l5qfat1,.l1o3p4yu:hover .l5qfat1,.l1o3p4yu:focus .l5qfat1{background-color:var(--fds-colour-border-selected-hover);}
|
|
15
|
-
.l1p9u80z{
|
|
16
|
-
.ej7h5do{padding:0.5rem
|
|
17
|
-
.
|
|
18
|
-
.c1s8ur0k{height:1.
|
|
19
|
-
.
|
|
15
|
+
.l1p9u80z{margin-right:-0.5rem;}
|
|
16
|
+
.ej7h5do{padding:0.5rem;margin:auto 0.25rem auto 0;}
|
|
17
|
+
.c160mxwv{height:1.25rem;width:1.25rem;color:var(--fds-colour-icon);-webkit-transition:-webkit-transform 300ms ease-in-out;transition:transform 300ms ease-in-out;-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg);}.l1o3p4yu:active .c160mxwv,.l1o3p4yu:hover .c160mxwv,.l1o3p4yu:focus .c160mxwv{color:var(--fds-colour-icon-hover);}
|
|
18
|
+
.c1s8ur0k{height:1.125rem;width:1.125rem;}
|
|
19
|
+
.s178e7hk{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg);}
|
|
20
|
+
.l1o3p4yu:active .c1euxgs0,.l1o3p4yu:hover .c1euxgs0,.l1o3p4yu:focus .c1euxgs0{color:var(--fds-colour-icon-selected-hover);}}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const s={primary:{brandName:"LifeSG",logoSrc:"https://assets.life.gov.sg/lifesg/logo-lifesg.svg"}},e={primary:{brandName:"BookingSG",logoSrc:"https://www.booking.gov.sg/logo.svg"}},
|
|
1
|
+
const s={primary:{brandName:"LifeSG",logoSrc:"https://assets.life.gov.sg/lifesg/logo-lifesg.svg"}},e={primary:{brandName:"BookingSG",logoSrc:"https://www.booking.gov.sg/logo.svg"}},o={primary:{brandName:"CCube",logoSrc:"https://assets.life.gov.sg/ccube/logo-ccube.svg"}},g={primary:{brandName:"IMDA",logoSrc:"https://assets.life.gov.sg/react-design-system/img/logo/imda-logo.svg"}},r={primary:{brandName:"MyLegacy",logoSrc:"https://mylegacy.life.gov.sg/images/site-logo.png"}},a={primary:{brandName:"SPF",logoSrc:"https://assets.life.gov.sg/react-design-system/img/logo/spf-logo.png"}},t={primary:{brandName:"SupportGoWhere",logoSrc:"https://assets.life.gov.sg/react-design-system/img/logo/sgw-logo.png"}},i={primary:{brandName:"Tote Board",logoSrc:"https://assets.life.gov.sg/react-design-system/img/logo/tote-board-logo.svg"}},l=l=>{switch(l){case"bookingsg":return e;case"mylegacy":return r;case"ccube":return o;case"spf":return a;case"supportgowhere":case"sgw-digital-lobby":return t;case"imda":return g;case"tote-board":return i;default:return s}};export{l as getDefaultResourceLogo};
|
|
2
2
|
//# sourceMappingURL=navbar-logo-data.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navbar-logo-data.js","sources":["../../src/navbar/navbar-logo-data.ts"],"sourcesContent":["import type { ThemeType } from \"../theme/types\";\nimport type { NavbarResourcesProps } from \"./types\";\n\nconst DEFAULT_RESOURCES_LOGO: NavbarResourcesProps = {\n primary: {\n brandName: \"LifeSG\",\n logoSrc: \"https://assets.life.gov.sg/lifesg/logo-lifesg.svg\",\n },\n};\n\nconst BOOKINGSG_RESOURCES_LOGO: NavbarResourcesProps = {\n primary: {\n brandName: \"BookingSG\",\n logoSrc: \"https://www.booking.gov.sg/logo.svg\",\n },\n};\n\nconst CCUBE_RESOURCES_LOGO: NavbarResourcesProps = {\n primary: {\n brandName: \"CCube\",\n logoSrc: \"https://assets.life.gov.sg/ccube/logo-ccube.svg\",\n },\n};\n\nconst IMDA_RESOURCE_LOGO: NavbarResourcesProps = {\n primary: {\n brandName: \"IMDA\",\n logoSrc:\n \"https://assets.life.gov.sg/react-design-system/img/logo/imda-logo.svg\",\n },\n};\n\nconst MYLEGACY_RESOURCES_LOGO: NavbarResourcesProps = {\n primary: {\n brandName: \"MyLegacy\",\n logoSrc: \"https://mylegacy.life.gov.sg/images/site-logo.png\",\n },\n};\n\nconst SPF_RESOURCE_LOGO: NavbarResourcesProps = {\n primary: {\n brandName: \"SPF\",\n logoSrc:\n \"https://assets.life.gov.sg/react-design-system/img/logo/spf-logo.png\",\n },\n};\n\nconst SUPPORTGOWHERE_RESOURCE_LOGO: NavbarResourcesProps = {\n primary: {\n brandName: \"SupportGoWhere\",\n logoSrc:\n \"https://assets.life.gov.sg/react-design-system/img/logo/sgw-logo.png\",\n },\n};\n\nexport const getDefaultResourceLogo = (resourceScheme?: ThemeType) => {\n switch (resourceScheme) {\n case \"bookingsg\":\n return BOOKINGSG_RESOURCES_LOGO;\n case \"mylegacy\":\n return MYLEGACY_RESOURCES_LOGO;\n case \"ccube\":\n return CCUBE_RESOURCES_LOGO;\n case \"spf\":\n return SPF_RESOURCE_LOGO;\n case \"supportgowhere\":\n case \"sgw-digital-lobby\":\n return SUPPORTGOWHERE_RESOURCE_LOGO;\n case \"imda\":\n return IMDA_RESOURCE_LOGO;\n default:\n return DEFAULT_RESOURCES_LOGO;\n }\n};\n"],"names":["DEFAULT_RESOURCES_LOGO","primary","brandName","logoSrc","BOOKINGSG_RESOURCES_LOGO","CCUBE_RESOURCES_LOGO","IMDA_RESOURCE_LOGO","MYLEGACY_RESOURCES_LOGO","SPF_RESOURCE_LOGO","SUPPORTGOWHERE_RESOURCE_LOGO","getDefaultResourceLogo","resourceScheme"],"mappings":"AAGA,MAAMA,EAA+C,CACjDC,QAAS,CACLC,UAAW,SACXC,QAAS,sDAIXC,EAAiD,CACnDH,QAAS,CACLC,UAAW,YACXC,QAAS,wCAIXE,EAA6C,CAC/CJ,QAAS,CACLC,UAAW,QACXC,QAAS,oDAIXG,EAA2C,CAC7CL,QAAS,CACLC,UAAW,OACXC,QACI,0EAINI,EAAgD,CAClDN,QAAS,CACLC,UAAW,WACXC,QAAS,sDAIXK,EAA0C,CAC5CP,QAAS,CACLC,UAAW,MACXC,QACI,yEAINM,EAAqD,CACvDR,QAAS,CACLC,UAAW,iBACXC,QACI,
|
|
1
|
+
{"version":3,"file":"navbar-logo-data.js","sources":["../../src/navbar/navbar-logo-data.ts"],"sourcesContent":["import type { ThemeType } from \"../theme/types\";\nimport type { NavbarResourcesProps } from \"./types\";\n\nconst DEFAULT_RESOURCES_LOGO: NavbarResourcesProps = {\n primary: {\n brandName: \"LifeSG\",\n logoSrc: \"https://assets.life.gov.sg/lifesg/logo-lifesg.svg\",\n },\n};\n\nconst BOOKINGSG_RESOURCES_LOGO: NavbarResourcesProps = {\n primary: {\n brandName: \"BookingSG\",\n logoSrc: \"https://www.booking.gov.sg/logo.svg\",\n },\n};\n\nconst CCUBE_RESOURCES_LOGO: NavbarResourcesProps = {\n primary: {\n brandName: \"CCube\",\n logoSrc: \"https://assets.life.gov.sg/ccube/logo-ccube.svg\",\n },\n};\n\nconst IMDA_RESOURCE_LOGO: NavbarResourcesProps = {\n primary: {\n brandName: \"IMDA\",\n logoSrc:\n \"https://assets.life.gov.sg/react-design-system/img/logo/imda-logo.svg\",\n },\n};\n\nconst MYLEGACY_RESOURCES_LOGO: NavbarResourcesProps = {\n primary: {\n brandName: \"MyLegacy\",\n logoSrc: \"https://mylegacy.life.gov.sg/images/site-logo.png\",\n },\n};\n\nconst SPF_RESOURCE_LOGO: NavbarResourcesProps = {\n primary: {\n brandName: \"SPF\",\n logoSrc:\n \"https://assets.life.gov.sg/react-design-system/img/logo/spf-logo.png\",\n },\n};\n\nconst SUPPORTGOWHERE_RESOURCE_LOGO: NavbarResourcesProps = {\n primary: {\n brandName: \"SupportGoWhere\",\n logoSrc:\n \"https://assets.life.gov.sg/react-design-system/img/logo/sgw-logo.png\",\n },\n};\n\nconst TOTEBOARD_RESOURCES_LOGO: NavbarResourcesProps = {\n primary: {\n brandName: \"Tote Board\",\n logoSrc:\n \"https://assets.life.gov.sg/react-design-system/img/logo/tote-board-logo.svg\",\n },\n};\n\nexport const getDefaultResourceLogo = (resourceScheme?: ThemeType) => {\n switch (resourceScheme) {\n case \"bookingsg\":\n return BOOKINGSG_RESOURCES_LOGO;\n case \"mylegacy\":\n return MYLEGACY_RESOURCES_LOGO;\n case \"ccube\":\n return CCUBE_RESOURCES_LOGO;\n case \"spf\":\n return SPF_RESOURCE_LOGO;\n case \"supportgowhere\":\n case \"sgw-digital-lobby\":\n return SUPPORTGOWHERE_RESOURCE_LOGO;\n case \"imda\":\n return IMDA_RESOURCE_LOGO;\n case \"tote-board\":\n return TOTEBOARD_RESOURCES_LOGO;\n default:\n return DEFAULT_RESOURCES_LOGO;\n }\n};\n"],"names":["DEFAULT_RESOURCES_LOGO","primary","brandName","logoSrc","BOOKINGSG_RESOURCES_LOGO","CCUBE_RESOURCES_LOGO","IMDA_RESOURCE_LOGO","MYLEGACY_RESOURCES_LOGO","SPF_RESOURCE_LOGO","SUPPORTGOWHERE_RESOURCE_LOGO","TOTEBOARD_RESOURCES_LOGO","getDefaultResourceLogo","resourceScheme"],"mappings":"AAGA,MAAMA,EAA+C,CACjDC,QAAS,CACLC,UAAW,SACXC,QAAS,sDAIXC,EAAiD,CACnDH,QAAS,CACLC,UAAW,YACXC,QAAS,wCAIXE,EAA6C,CAC/CJ,QAAS,CACLC,UAAW,QACXC,QAAS,oDAIXG,EAA2C,CAC7CL,QAAS,CACLC,UAAW,OACXC,QACI,0EAINI,EAAgD,CAClDN,QAAS,CACLC,UAAW,WACXC,QAAS,sDAIXK,EAA0C,CAC5CP,QAAS,CACLC,UAAW,MACXC,QACI,yEAINM,EAAqD,CACvDR,QAAS,CACLC,UAAW,iBACXC,QACI,yEAINO,EAAiD,CACnDT,QAAS,CACLC,UAAW,aACXC,QACI,gFAICQ,EAA0BC,IACnC,OAAQA,GACJ,IAAK,YACD,OAAOR,EACX,IAAK,WACD,OAAOG,EACX,IAAK,QACD,OAAOF,EACX,IAAK,MACD,OAAOG,EACX,IAAK,iBACL,IAAK,oBACD,OAAOC,EACX,IAAK,OACD,OAAOH,EACX,IAAK,aACD,OAAOI,EACX,QACI,OAAOV"}
|
package/navbar/navbar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navbar.js","sources":["../../src/navbar/navbar.tsx"],"sourcesContent":["import { MenuIcon } from \"@lifesg/react-icons/menu\";\nimport clsx from \"clsx\";\nimport type React from \"react\";\nimport {\n forwardRef,\n useContext,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\n\nimport { Layout } from \"../layout\";\nimport { Masthead } from \"../masthead/masthead\";\nimport { Overlay } from \"../overlay/overlay\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport {\n Breakpoint,\n parsePxOrRemValue,\n useResolvedBreakpointToken,\n} from \"../theme\";\nimport { ThemeContext } from \"../theme/theme-provider/context\";\nimport { Brand } from \"./brand\";\nimport { Drawer } from \"./drawer\";\nimport * as styles from \"./navbar.styles\";\nimport { NavbarActionButtons } from \"./navbar-action-buttons\";\nimport { NavbarHelper } from \"./navbar-helper\";\nimport { NavbarItems } from \"./navbar-items\";\nimport { getDefaultResourceLogo } from \"./navbar-logo-data\";\nimport type {\n BrandType,\n DrawerDismissalMethod,\n NavbarActionButtonsProps,\n NavbarButtonProps,\n NavbarDrawerApi,\n NavbarDrawerHandle,\n NavbarProps,\n NavItemCommonProps,\n NavItemProps,\n} from \"./types\";\n\nconst Component = <T,>(\n {\n items,\n className,\n id,\n selectedId,\n compress = false,\n fixed = true,\n resources,\n hideNavElements = false,\n hideNavBranding = false,\n hideLinkIndicator = false,\n drawerDismissalExclusions: blockDrawerDismissalMethods = [],\n actionButtons,\n onItemClick,\n onActionButtonClick,\n onBrandClick,\n masthead = true,\n layout = \"default\",\n headerLabel = \"Main navigation menu\",\n drawerLabel,\n ...otherProps\n }: NavbarProps<T>,\n ref: React.Ref<NavbarDrawerHandle>\n) => {\n // =============================================================================\n // CONST, STATE, REFS\n // =============================================================================\n const [showDrawer, setShowDrawer] = useState<boolean>(false);\n const [showOverlay, setShowOverlay] = useState<boolean>(false);\n const mobileMenuRef = useRef<HTMLButtonElement>(null);\n const isStretch = layout === \"stretch\";\n const elementRef = useRef<HTMLDivElement>(null);\n const theme = useContext(ThemeContext);\n const defaultResource = getDefaultResourceLogo(theme?.theme);\n const tabletWidth = parsePxOrRemValue(\n useResolvedBreakpointToken(Breakpoint[\"lg-max\"])\n );\n\n const primary = resources?.primary || defaultResource.primary;\n const secondary = resources?.secondary;\n\n useImperativeHandle(\n ref,\n () =>\n Object.assign<HTMLDivElement, NavbarDrawerApi>(\n elementRef.current!,\n {\n dismissDrawer: () => {\n dismissDrawer();\n },\n }\n ),\n [showDrawer]\n );\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n handleResize();\n window.addEventListener(\"resize\", handleResize);\n\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n };\n }, []);\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const dismissDrawer = () => {\n setShowDrawer(false);\n setTimeout(() => {\n setShowOverlay(false);\n }, 550); // For drawer animation to complete + buffer\n };\n\n const shouldDismissDrawer = (dismissalMethod: DrawerDismissalMethod) => {\n return (\n showDrawer &&\n blockDrawerDismissalMethods.indexOf(dismissalMethod) === -1\n );\n };\n\n const hasCollapsibleActionButtons = (\n actionButtons: NavbarActionButtonsProps\n ) => {\n const drawerActionButtons =\n actionButtons.mobile || actionButtons.desktop;\n if (drawerActionButtons) {\n return (\n drawerActionButtons.length &&\n drawerActionButtons.some(\n (actionButton) => !actionButton.uncollapsible\n )\n );\n }\n\n return false;\n };\n\n // =============================================================================\n // EVENT HANDLER\n // =============================================================================\n const handleResize = () => {\n if (window.innerWidth <= tabletWidth && showDrawer) {\n dismissDrawer();\n }\n };\n\n const handleBrandClick = (\n _event: React.MouseEvent<HTMLAnchorElement>,\n type: BrandType\n ) => {\n if (onBrandClick) {\n onBrandClick(type);\n }\n\n if (shouldDismissDrawer(\"brand-click\")) {\n dismissDrawer();\n }\n };\n\n const handleNavItemClick = <K extends T>(\n event: React.MouseEvent<HTMLAnchorElement>,\n item: NavItemProps<K> | NavItemCommonProps<K>\n ) => {\n if (NavbarHelper.isNavItemCommon(item) && item.onClick) {\n item.onClick(event);\n } else if (onItemClick) {\n event.preventDefault();\n onItemClick(item);\n }\n\n if (\n NavbarHelper.isNavItemLink(item) &&\n !item.subMenu &&\n shouldDismissDrawer(\"item-click\")\n ) {\n dismissDrawer();\n }\n };\n\n const handleActionButtonClick = (\n event: React.MouseEvent<HTMLButtonElement> | React.MouseEvent<Element>,\n actionButton: NavbarButtonProps\n ) => {\n if (\n (actionButton.type === \"button\" ||\n actionButton.type === \"download\") &&\n actionButton.args?.onClick\n ) {\n actionButton.args.onClick(\n event as React.MouseEvent<HTMLButtonElement>\n );\n } else if (onActionButtonClick) {\n event.preventDefault();\n onActionButtonClick(actionButton);\n }\n\n if (shouldDismissDrawer(\"item-click\")) {\n dismissDrawer();\n }\n };\n\n const handleMobileMenuButtonClick = () => {\n setShowDrawer(true);\n setShowOverlay(true);\n };\n\n const handleDrawerClose = () => {\n if (shouldDismissDrawer(\"close-button-click\")) {\n dismissDrawer();\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n\n const renderDrawer = () => (\n <Overlay\n show={showOverlay}\n enableOverlayClick\n onOverlayClick={handleDrawerClose}\n >\n <Drawer\n show={showDrawer}\n resources={{ primary, secondary }}\n onClose={handleDrawerClose}\n onBrandClick={handleBrandClick}\n actionButtons={actionButtons}\n hideNavBranding={hideNavBranding}\n mobileMenuRef={mobileMenuRef}\n drawerLabel={drawerLabel}\n >\n <NavbarItems\n items={items.mobile || items.desktop}\n onItemClick={handleNavItemClick}\n selectedId={selectedId}\n mobile\n hideLinkIndicator={hideLinkIndicator}\n />\n <NavbarActionButtons\n actionButtons={actionButtons}\n onActionButtonClick={handleActionButtonClick}\n mobile\n />\n </Drawer>\n </Overlay>\n );\n\n const renderBrand = () => (\n <div\n className={clsx(\n styles.navBrandContainer,\n compress\n ? styles.navBrandContainerCompressed\n : styles.navBrandContainerFull,\n styles.navBrandContainerResponsive\n )}\n data-id=\"brand-container\"\n >\n {primary && (\n <Brand\n resources={primary}\n onClick={handleBrandClick}\n data-id=\"brand-primary\"\n data-testid=\"main__brand\"\n type=\"primary\"\n />\n )}\n {secondary && (\n <>\n <div\n className={clsx(\n styles.navSeparator,\n compress\n ? styles.navSeparatorCompressed\n : styles.navSeparatorFull,\n styles.navSeparatorResponsive\n )}\n />\n <Brand\n resources={secondary}\n onClick={handleBrandClick}\n data-id=\"brand-secondary\"\n data-testid=\"main__brand-secondary\"\n type=\"secondary\"\n />\n </>\n )}\n </div>\n );\n\n const renderMobileMenuButton = () => {\n const drawerItems = items.mobile || items.desktop;\n if (\n (drawerItems && drawerItems.length > 0) ||\n (actionButtons && hasCollapsibleActionButtons(actionButtons))\n ) {\n return (\n <ClickableIcon\n ref={mobileMenuRef}\n className={styles.mobileMenuButton}\n aria-label={showDrawer ? \"Close nav menu\" : \"Open nav menu\"}\n aria-expanded={showDrawer}\n data-testid=\"button__mobile-menu\"\n onClick={handleMobileMenuButtonClick}\n focusHighlight={true}\n >\n <MenuIcon className={styles.mobileMenuIcon} />\n </ClickableIcon>\n );\n }\n\n return null;\n };\n\n const renderNavbar = () => {\n return (\n <Layout.Content stretch={isStretch}>\n <nav\n className={clsx(\n styles.nav,\n compress && styles.navCompressed,\n theme?.mode === \"dark\" && styles.navDark\n )}\n aria-label={headerLabel}\n >\n {!hideNavBranding && renderBrand()}\n {!hideNavElements && (\n <div\n className={clsx(\n styles.navElementsContainer,\n !hideNavBranding &&\n styles.navElementsContainerWithBranding\n )}\n >\n <NavbarItems\n items={items.desktop}\n onItemClick={handleNavItemClick}\n selectedId={selectedId}\n hideNavBranding={hideNavBranding}\n hideLinkIndicator={hideLinkIndicator}\n />\n <NavbarActionButtons\n actionButtons={actionButtons}\n onActionButtonClick={handleActionButtonClick}\n />\n {renderMobileMenuButton()}\n </div>\n )}\n </nav>\n\n {!hideNavElements && renderDrawer()}\n </Layout.Content>\n );\n };\n\n return (\n <div\n ref={elementRef}\n className={clsx(\n styles.wrapper,\n fixed ? styles.wrapperFixed : styles.wrapperRelative,\n theme?.mode === \"dark\"\n ? styles.wrapperDark\n : styles.wrapperLight,\n className\n )}\n id={id || \"navbar-wrapper\"}\n data-testid={otherProps[\"data-testid\"] || \"navbar-wrapper\"}\n >\n {masthead && <Masthead stretch={isStretch} />}\n {renderNavbar()}\n </div>\n );\n};\n\n// @catalog\n/**\n * The main site navigation bar with desktop and mobile drawer views.\n *\n * Use `Navbar` to render the primary navigation header. It displays brand\n * logos, navigation items, and action buttons in a desktop bar, and\n * automatically collapses items into a slide-in drawer for mobile viewports.\n */\nexport const Navbar = forwardRef(Component);\n"],"names":["Navbar","forwardRef","_a","ref","items","className","id","selectedId","compress","fixed","resources","hideNavElements","hideNavBranding","hideLinkIndicator","drawerDismissalExclusions","blockDrawerDismissalMethods","actionButtons","onItemClick","onActionButtonClick","onBrandClick","masthead","layout","headerLabel","drawerLabel","otherProps","__rest","showDrawer","setShowDrawer","useState","showOverlay","setShowOverlay","mobileMenuRef","useRef","isStretch","elementRef","theme","useContext","ThemeContext","defaultResource","getDefaultResourceLogo","tabletWidth","parsePxOrRemValue","useResolvedBreakpointToken","Breakpoint","primary","secondary","useImperativeHandle","Object","assign","current","dismissDrawer","useEffect","handleResize","window","addEventListener","removeEventListener","setTimeout","shouldDismissDrawer","dismissalMethod","indexOf","innerWidth","handleBrandClick","_event","type","handleNavItemClick","event","item","NavbarHelper","isNavItemCommon","onClick","preventDefault","isNavItemLink","subMenu","handleActionButtonClick","actionButton","args","handleMobileMenuButtonClick","handleDrawerClose","renderMobileMenuButton","drawerItems","mobile","desktop","length","drawerActionButtons","some","uncollapsible","hasCollapsibleActionButtons","_jsx","ClickableIcon","styles.mobileMenuButton","focusHighlight","children","MenuIcon","styles.mobileMenuIcon","_jsxs","clsx","styles.wrapper","styles.wrapperFixed","styles.wrapperRelative","mode","styles.wrapperDark","styles.wrapperLight","Masthead","stretch","Layout","Content","styles.nav","styles.navCompressed","styles.navDark","styles.navBrandContainer","styles.navBrandContainerCompressed","styles.navBrandContainerFull","styles.navBrandContainerResponsive","Brand","_Fragment","styles.navSeparator","styles.navSeparatorCompressed","styles.navSeparatorFull","styles.navSeparatorResponsive","styles.navElementsContainer","styles.navElementsContainerWithBranding","NavbarItems","NavbarActionButtons","Overlay","show","enableOverlayClick","onOverlayClick","Drawer","onClose"],"mappings":"s4DAyCA,MA6VaA,EAASC,GA7VJ,CACdC,EAsBAC,KAtBA,IAAAC,MACIA,EAAKC,UACLA,EAASC,GACTA,EAAEC,WACFA,EAAUC,SACVA,GAAW,EAAKC,MAChBA,GAAQ,EAAIC,UACZA,EAASC,gBACTA,IAAkB,EAAKC,gBACvBA,IAAkB,EAAKC,kBACvBA,IAAoB,EACpBC,0BAA2BC,GAA8B,GAAEC,cAC3DA,GAAaC,YACbA,GAAWC,oBACXA,GAAmBC,aACnBA,GAAYC,SACZA,IAAW,EAAIC,OACfA,GAAS,UAASC,YAClBA,GAAc,uBAAsBC,YACpCA,IAAWrB,EACRsB,GAAUC,EAAAvB,EApBjB,+QA2BA,MAAOwB,GAAYC,IAAiBC,GAAkB,IAC/CC,GAAaC,IAAkBF,GAAkB,GAClDG,GAAgBC,EAA0B,MAC1CC,GAAuB,YAAXZ,GACZa,GAAaF,EAAuB,MACpCG,GAAQC,EAAWC,GACnBC,GAAkBC,EAAuBJ,cAAK,EAALA,GAAOA,OAChDK,GAAcC,EAChBC,EAA2BC,EAAW,YAGpCC,IAAUlC,aAAS,EAATA,EAAWkC,UAAWN,GAAgBM,QAChDC,GAAYnC,aAAS,EAATA,EAAWmC,UAE7BC,EACI3C,GACA,IACI4C,OAAOC,OACHd,GAAWe,QACX,CACIC,cAAe,KACXA,IAAe,KAI/B,CAACxB,KAMLyB,GAAU,KACNC,KACAC,OAAOC,iBAAiB,SAAUF,IAE3B,KACHC,OAAOE,oBAAoB,SAAUH,GAAa,IAEvD,IAKH,MAAMF,GAAgB,KAClBvB,IAAc,GACd6B,YAAW,KACP1B,IAAe,EAAM,GACtB,IAAI,EAGL2B,GAAuBC,GAErBhC,KACyD,IAAzDX,GAA4B4C,QAAQD,GAwBtCN,GAAe,KACbC,OAAOO,YAAcpB,IAAed,IACpCwB,IACJ,EAGEW,GAAmB,CACrBC,EACAC,KAEI5C,IACAA,GAAa4C,GAGbN,GAAoB,gBACpBP,IACJ,EAGEc,GAAqB,CACvBC,EACAC,KAEIC,EAAaC,gBAAgBF,IAASA,EAAKG,QAC3CH,EAAKG,QAAQJ,GACNhD,KACPgD,EAAMK,iBACNrD,GAAYiD,IAIZC,EAAaI,cAAcL,KAC1BA,EAAKM,SACNf,GAAoB,eAEpBP,IACJ,EAGEuB,GAA0B,CAC5BR,EACAS,WAG2B,WAAtBA,EAAaX,MACY,aAAtBW,EAAaX,gBACjB7D,EAAAwE,EAAaC,2BAAMN,SAKZnD,KACP+C,EAAMK,iBACNpD,GAAoBwD,IALpBA,EAAaC,KAAKN,QACdJ,GAOJR,GAAoB,eACpBP,IACJ,EAGE0B,GAA8B,KAChCjD,IAAc,GACdG,IAAe,EAAK,EAGlB+C,GAAoB,KAClBpB,GAAoB,uBACpBP,IACJ,EAkFE4B,GAAyB,KAC3B,MAAMC,EAAc3E,EAAM4E,QAAU5E,EAAM6E,QAC1C,OACKF,GAAeA,EAAYG,OAAS,GACpClE,IA/K2B,CAChCA,IAEA,MAAMmE,EACFnE,EAAcgE,QAAUhE,EAAciE,QAC1C,QAAIE,GAEIA,EAAoBD,QACpBC,EAAoBC,MACfV,IAAkBA,EAAaW,eAKhC,EAiKUC,CAA4BtE,IAG1CuE,EAACC,EAAa,CACVrF,IAAK4B,GACL1B,UAAWoF,eACC/D,GAAa,iBAAmB,gCAC7BA,GAAU,cACb,sBACZ2C,QAASO,GACTc,gBAAgB,EAAIC,SAEpBJ,EAACK,EAAQ,CAACvF,UAAWwF,MAK1B,IAAI,EA4Cf,OACIC,EAAA,MAAA,CACI3F,IAAK+B,GACL7B,UAAW0F,EACPC,EACAvF,EAAQwF,EAAsBC,EACd,UAAhB/D,cAAK,EAALA,GAAOgE,MACDC,EACAC,EACNhG,GAEJC,GAAIA,GAAM,iBAAgB,cACbkB,GAAW,gBAAkB,iBAAgBmE,SAAA,CAEzDvE,IAAYmE,EAACe,EAAQ,CAACC,QAAStE,KArDhC6D,EAACU,EAAOC,QAAO,CAACF,QAAStE,GAAS0D,SAAA,CAC9BG,EAAA,MAAA,CACIzF,UAAW0F,EACPW,EACAlG,GAAYmG,EACI,UAAhBxE,cAAK,EAALA,GAAOgE,OAAmBS,GAC7B,aACWtF,GAAWqE,SAAA,EAErB/E,IA7EdkF,EAAA,MAAA,CACIzF,UAAW0F,EACPc,EACArG,EACMsG,EACAC,EACNC,GACH,UACO,4BAEPpE,IACG2C,EAAC0B,GACGvG,UAAWkC,GACXyB,QAASR,GAAgB,UACjB,8BACI,cACZE,KAAK,YAGZlB,IACGiD,EAAAoB,EAAA,CAAAvB,SAAA,CACIJ,EAAA,MAAA,CACIlF,UAAW0F,EACPoB,EACA3G,EACM4G,EACAC,EACNC,KAGR/B,EAAC0B,EAAK,CACFvG,UAAWmC,GACXwB,QAASR,GAAgB,UACjB,gCACI,wBACZE,KAAK,qBA2CPpD,IACEmF,EAAA,MAAA,CACIzF,UAAW0F,EACPwB,GACC3G,IACG4G,GACP7B,SAAA,CAEDJ,EAACkC,EAAW,CACRrH,MAAOA,EAAM6E,QACbhE,YAAa+C,GACbzD,WAAYA,EACZK,gBAAiBA,GACjBC,kBAAmBA,KAEvB0E,EAACmC,EAAmB,CAChB1G,cAAeA,GACfE,oBAAqBuD,KAExBK,YAKXnE,IAtIV4E,EAACoC,EAAO,CACJC,KAAM/F,GACNgG,sBACAC,eAAgBjD,GAAiBc,SAEjCG,EAACiC,EAAM,CACHH,KAAMlG,GACNhB,UAAW,CAAEkC,WAASC,cACtBmF,QAASnD,GACT1D,aAAc0C,GACd7C,cAAeA,GACfJ,gBAAiBA,GACjBmB,cAAeA,GACfR,YAAaA,aAEbgE,EAACkC,EAAW,CACRrH,MAAOA,EAAM4E,QAAU5E,EAAM6E,QAC7BhE,YAAa+C,GACbzD,WAAYA,EACZyE,UACAnE,kBAAmBA,KAEvB0E,EAACmC,EAAmB,CAChB1G,cAAeA,GACfE,oBAAqBuD,GACrBO,QAAM,cAkIZ"}
|
|
1
|
+
{"version":3,"file":"navbar.js","sources":["../../src/navbar/navbar.tsx"],"sourcesContent":["import { MenuIcon } from \"@lifesg/react-icons/menu\";\nimport clsx from \"clsx\";\nimport type React from \"react\";\nimport {\n forwardRef,\n useContext,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\n\nimport { Layout } from \"../layout\";\nimport { Masthead } from \"../masthead/masthead\";\nimport { Overlay } from \"../overlay/overlay\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport {\n Breakpoint,\n parsePxOrRemValue,\n useResolvedBreakpointToken,\n} from \"../theme\";\nimport { ThemeContext } from \"../theme/theme-provider/context\";\nimport { Brand } from \"./brand\";\nimport { Drawer } from \"./drawer\";\nimport * as styles from \"./navbar.styles\";\nimport { NavbarActionButtons } from \"./navbar-action-buttons\";\nimport { NavbarHelper } from \"./navbar-helper\";\nimport { NavbarItems } from \"./navbar-items\";\nimport { getDefaultResourceLogo } from \"./navbar-logo-data\";\nimport type {\n BrandType,\n DrawerDismissalMethod,\n NavbarActionButtonsProps,\n NavbarButtonProps,\n NavbarDrawerApi,\n NavbarDrawerHandle,\n NavbarProps,\n NavItemCommonProps,\n NavItemProps,\n} from \"./types\";\n\nconst Component = <T,>(\n {\n items,\n className,\n id,\n selectedId,\n compress = false,\n fixed = true,\n resources,\n hideNavElements = false,\n hideNavBranding = false,\n hideLinkIndicator = false,\n drawerDismissalExclusions: blockDrawerDismissalMethods = [],\n actionButtons,\n onItemClick,\n onActionButtonClick,\n onBrandClick,\n masthead = true,\n layout = \"default\",\n headerLabel = \"Main navigation menu\",\n drawerLabel,\n ...otherProps\n }: NavbarProps<T>,\n ref: React.Ref<NavbarDrawerHandle>\n) => {\n // =============================================================================\n // CONST, STATE, REFS\n // =============================================================================\n const [showDrawer, setShowDrawer] = useState<boolean>(false);\n const [showOverlay, setShowOverlay] = useState<boolean>(false);\n const mobileMenuRef = useRef<HTMLButtonElement>(null);\n const isStretch = layout === \"stretch\";\n const elementRef = useRef<HTMLDivElement>(null);\n const theme = useContext(ThemeContext);\n const defaultResource = getDefaultResourceLogo(theme?.theme);\n const tabletWidth = parsePxOrRemValue(\n useResolvedBreakpointToken(Breakpoint[\"lg-max\"])\n );\n\n const primary = resources?.primary || defaultResource.primary;\n const secondary = resources?.secondary;\n\n useImperativeHandle(\n ref,\n () =>\n Object.assign<HTMLDivElement, NavbarDrawerApi>(\n elementRef.current!,\n {\n dismissDrawer: () => {\n dismissDrawer();\n },\n }\n ),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [showDrawer]\n );\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n handleResize();\n window.addEventListener(\"resize\", handleResize);\n\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const dismissDrawer = () => {\n setShowDrawer(false);\n setTimeout(() => {\n setShowOverlay(false);\n }, 550); // For drawer animation to complete + buffer\n };\n\n const shouldDismissDrawer = (dismissalMethod: DrawerDismissalMethod) => {\n return (\n showDrawer &&\n blockDrawerDismissalMethods.indexOf(dismissalMethod) === -1\n );\n };\n\n const hasCollapsibleActionButtons = (\n actionButtons: NavbarActionButtonsProps\n ) => {\n const drawerActionButtons =\n actionButtons.mobile || actionButtons.desktop;\n if (drawerActionButtons) {\n return (\n drawerActionButtons.length &&\n drawerActionButtons.some(\n (actionButton) => !actionButton.uncollapsible\n )\n );\n }\n\n return false;\n };\n\n // =============================================================================\n // EVENT HANDLER\n // =============================================================================\n const handleResize = () => {\n if (window.innerWidth <= tabletWidth && showDrawer) {\n dismissDrawer();\n }\n };\n\n const handleBrandClick = (\n _event: React.MouseEvent<HTMLAnchorElement>,\n type: BrandType\n ) => {\n if (onBrandClick) {\n onBrandClick(type);\n }\n\n if (shouldDismissDrawer(\"brand-click\")) {\n dismissDrawer();\n }\n };\n\n const handleNavItemClick = <K extends T>(\n event: React.MouseEvent<HTMLAnchorElement>,\n item: NavItemProps<K> | NavItemCommonProps<K>\n ) => {\n if (NavbarHelper.isNavItemCommon(item) && item.onClick) {\n item.onClick(event);\n } else if (onItemClick) {\n event.preventDefault();\n onItemClick(item);\n }\n\n if (\n NavbarHelper.isNavItemLink(item) &&\n !item.subMenu &&\n shouldDismissDrawer(\"item-click\")\n ) {\n dismissDrawer();\n }\n };\n\n const handleActionButtonClick = (\n event: React.MouseEvent<HTMLButtonElement> | React.MouseEvent<Element>,\n actionButton: NavbarButtonProps\n ) => {\n if (\n (actionButton.type === \"button\" ||\n actionButton.type === \"download\") &&\n actionButton.args?.onClick\n ) {\n actionButton.args.onClick(\n event as React.MouseEvent<HTMLButtonElement>\n );\n } else if (onActionButtonClick) {\n event.preventDefault();\n onActionButtonClick(actionButton);\n }\n\n if (shouldDismissDrawer(\"item-click\")) {\n dismissDrawer();\n }\n };\n\n const handleMobileMenuButtonClick = () => {\n setShowDrawer(true);\n setShowOverlay(true);\n };\n\n const handleDrawerClose = () => {\n if (shouldDismissDrawer(\"close-button-click\")) {\n dismissDrawer();\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n\n const renderDrawer = () => (\n <Overlay\n show={showOverlay}\n enableOverlayClick\n onOverlayClick={handleDrawerClose}\n >\n <Drawer\n show={showDrawer}\n resources={{ primary, secondary }}\n onClose={handleDrawerClose}\n onBrandClick={handleBrandClick}\n actionButtons={actionButtons}\n hideNavBranding={hideNavBranding}\n mobileMenuRef={mobileMenuRef}\n drawerLabel={drawerLabel}\n >\n <NavbarItems\n items={items.mobile || items.desktop}\n onItemClick={handleNavItemClick}\n selectedId={selectedId}\n mobile\n hideLinkIndicator={hideLinkIndicator}\n />\n <NavbarActionButtons\n actionButtons={actionButtons}\n onActionButtonClick={handleActionButtonClick}\n mobile\n />\n </Drawer>\n </Overlay>\n );\n\n const renderBrand = () => (\n <div\n className={clsx(\n styles.navBrandContainer,\n compress\n ? styles.navBrandContainerCompressed\n : styles.navBrandContainerFull,\n styles.navBrandContainerResponsive\n )}\n data-id=\"brand-container\"\n >\n {primary && (\n <Brand\n resources={primary}\n onClick={handleBrandClick}\n data-id=\"brand-primary\"\n data-testid=\"main__brand\"\n type=\"primary\"\n />\n )}\n {secondary && (\n <>\n <div\n className={clsx(\n styles.navSeparator,\n compress\n ? styles.navSeparatorCompressed\n : styles.navSeparatorFull,\n styles.navSeparatorResponsive\n )}\n />\n <Brand\n resources={secondary}\n onClick={handleBrandClick}\n data-id=\"brand-secondary\"\n data-testid=\"main__brand-secondary\"\n type=\"secondary\"\n />\n </>\n )}\n </div>\n );\n\n const renderMobileMenuButton = () => {\n const drawerItems = items.mobile || items.desktop;\n if (\n (drawerItems && drawerItems.length > 0) ||\n (actionButtons && hasCollapsibleActionButtons(actionButtons))\n ) {\n return (\n <ClickableIcon\n ref={mobileMenuRef}\n className={styles.mobileMenuButton}\n aria-label={showDrawer ? \"Close nav menu\" : \"Open nav menu\"}\n aria-expanded={showDrawer}\n data-testid=\"button__mobile-menu\"\n onClick={handleMobileMenuButtonClick}\n focusHighlight={true}\n >\n <MenuIcon className={styles.mobileMenuIcon} />\n </ClickableIcon>\n );\n }\n\n return null;\n };\n\n const renderNavbar = () => {\n return (\n <Layout.Content stretch={isStretch}>\n <nav\n className={clsx(\n styles.nav,\n compress && styles.navCompressed,\n theme?.mode === \"dark\" && styles.navDark\n )}\n aria-label={headerLabel}\n >\n {!hideNavBranding && renderBrand()}\n {!hideNavElements && (\n <div\n className={clsx(\n styles.navElementsContainer,\n !hideNavBranding &&\n styles.navElementsContainerWithBranding\n )}\n >\n <NavbarItems\n items={items.desktop}\n onItemClick={handleNavItemClick}\n selectedId={selectedId}\n hideNavBranding={hideNavBranding}\n hideLinkIndicator={hideLinkIndicator}\n />\n <NavbarActionButtons\n actionButtons={actionButtons}\n onActionButtonClick={handleActionButtonClick}\n />\n {renderMobileMenuButton()}\n </div>\n )}\n </nav>\n\n {!hideNavElements && renderDrawer()}\n </Layout.Content>\n );\n };\n\n return (\n <div\n ref={elementRef}\n className={clsx(\n styles.wrapper,\n fixed ? styles.wrapperFixed : styles.wrapperRelative,\n theme?.mode === \"dark\"\n ? styles.wrapperDark\n : styles.wrapperLight,\n className\n )}\n id={id || \"navbar-wrapper\"}\n data-testid={otherProps[\"data-testid\"] || \"navbar-wrapper\"}\n >\n {masthead && <Masthead stretch={isStretch} />}\n {renderNavbar()}\n </div>\n );\n};\n\n// @catalog\n/**\n * The main site navigation bar with desktop and mobile drawer views.\n *\n * Use `Navbar` to render the primary navigation header. It displays brand\n * logos, navigation items, and action buttons in a desktop bar, and\n * automatically collapses items into a slide-in drawer for mobile viewports.\n */\nexport const Navbar = forwardRef(Component);\n"],"names":["Navbar","forwardRef","_a","ref","items","className","id","selectedId","compress","fixed","resources","hideNavElements","hideNavBranding","hideLinkIndicator","drawerDismissalExclusions","blockDrawerDismissalMethods","actionButtons","onItemClick","onActionButtonClick","onBrandClick","masthead","layout","headerLabel","drawerLabel","otherProps","__rest","showDrawer","setShowDrawer","useState","showOverlay","setShowOverlay","mobileMenuRef","useRef","isStretch","elementRef","theme","useContext","ThemeContext","defaultResource","getDefaultResourceLogo","tabletWidth","parsePxOrRemValue","useResolvedBreakpointToken","Breakpoint","primary","secondary","useImperativeHandle","Object","assign","current","dismissDrawer","useEffect","handleResize","window","addEventListener","removeEventListener","setTimeout","shouldDismissDrawer","dismissalMethod","indexOf","innerWidth","handleBrandClick","_event","type","handleNavItemClick","event","item","NavbarHelper","isNavItemCommon","onClick","preventDefault","isNavItemLink","subMenu","handleActionButtonClick","actionButton","args","handleMobileMenuButtonClick","handleDrawerClose","renderMobileMenuButton","drawerItems","mobile","desktop","length","drawerActionButtons","some","uncollapsible","hasCollapsibleActionButtons","_jsx","ClickableIcon","styles.mobileMenuButton","focusHighlight","children","MenuIcon","styles.mobileMenuIcon","_jsxs","clsx","styles.wrapper","styles.wrapperFixed","styles.wrapperRelative","mode","styles.wrapperDark","styles.wrapperLight","Masthead","stretch","Layout","Content","styles.nav","styles.navCompressed","styles.navDark","styles.navBrandContainer","styles.navBrandContainerCompressed","styles.navBrandContainerFull","styles.navBrandContainerResponsive","Brand","_Fragment","styles.navSeparator","styles.navSeparatorCompressed","styles.navSeparatorFull","styles.navSeparatorResponsive","styles.navElementsContainer","styles.navElementsContainerWithBranding","NavbarItems","NavbarActionButtons","Overlay","show","enableOverlayClick","onOverlayClick","Drawer","onClose"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"otp-input.js","sources":["../../src/otp-input/otp-input.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport type React from \"react\";\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\n\nimport { Button } from \"../button\";\nimport { FormErrorMessage } from \"../form/form-label\";\nimport { Input } from \"../input\";\nimport { VisuallyHidden } from \"../shared/accessibility\";\nimport { Typography } from \"../typography\";\nimport { StringHelper, useId } from \"../util\";\nimport * as styles from \"./otp-input.styles\";\nimport type { OtpInputProps, OtpInputRef } from \"./types\";\nimport { stripOtpFromAutofill, validateUserInput } from \"./utils\";\n\nconst Component = (\n {\n id,\n value = [],\n \"data-testid\": dataTestId,\n className,\n cooldownDuration,\n actionButtonProps,\n errorMessage,\n numOfInput,\n prefix,\n onChange,\n onCooldownStart,\n onCooldownEnd,\n otpOnly,\n onCountdownChange,\n ...otherProps\n }: OtpInputProps,\n ref: React.Ref<OtpInputRef>\n) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const {\n disabled,\n onClick,\n styleType = \"secondary\",\n ...otherCtaProps\n } = actionButtonProps ?? {};\n\n const inputRefs = useRef<(HTMLInputElement | null)[]>([]);\n const onChangeRef = useRef(onChange);\n\n const [otpValues, setOtpValues] = useState<string[]>(\n new Array(numOfInput).fill(\"\")\n );\n const [countDown, setCountDown] = useState<number>(cooldownDuration);\n const [lastCtaTimestamp, setLastCtaTimestamp] = useState<Date>(new Date());\n const internalId = useId();\n\n const hasError = !!errorMessage;\n const errorId = `${internalId}-error`;\n const timerId = `${internalId}-timer`;\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n inputRefs?.current[0]?.focus();\n document.addEventListener(\"paste\", handlePaste);\n return () => document.removeEventListener(\"paste\", handlePaste);\n }, []);\n\n useEffect(() => {\n if (cooldownDuration !== 0) {\n if (onCooldownStart) onCooldownStart();\n const cleanup = beginCountdown();\n\n return () => cleanup();\n }\n }, [lastCtaTimestamp]);\n\n useImperativeHandle(ref, () => ({\n startCooldown: () => {\n setLastCtaTimestamp(new Date());\n setCountDown(cooldownDuration);\n },\n }));\n\n useEffect(() => {\n onChangeRef.current = onChange;\n }, [onChange]);\n\n useEffect(() => {\n if (value.length === numOfInput) {\n setOtpValues(value);\n }\n }, [value]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleInputFullValue = (incomingValue: string) => {\n if (incomingValue && validateUserInput(incomingValue, numOfInput)) {\n const incomingValueArr = incomingValue.split(\"\");\n setOtpValues(incomingValueArr);\n if (onChangeRef.current) {\n onChangeRef.current(incomingValueArr);\n }\n\n return true;\n }\n\n return false;\n };\n\n const handleChange =\n (index: number) => (event: React.ChangeEvent<HTMLInputElement>) => {\n const eventValue = event.target.value;\n\n /* handle autofill */\n const fieldIsEmpty = otpValues.every((num) => num === \"\");\n const autofillOtp = stripOtpFromAutofill(\n eventValue,\n numOfInput,\n prefix\n );\n if (fieldIsEmpty && handleInputFullValue(autofillOtp)) {\n return;\n }\n\n /* handle normal input */\n const value = eventValue.replace(/[^0-9]/g, \"\");\n if (validateUserInput(value)) {\n const newOtpValues = [...otpValues];\n\n newOtpValues[index] = value.substring(value.length - 1);\n inputRefs.current[index + 1]?.focus();\n\n setOtpValues(newOtpValues);\n\n if (onChange) {\n onChange(newOtpValues);\n }\n }\n };\n\n const handleKeyDown =\n (index: number) => (event: React.KeyboardEvent<HTMLInputElement>) => {\n const { key, code } = event;\n\n if (key === \"Backspace\" || code === \"Backspace\") {\n const newOtpValues = [...otpValues];\n if (newOtpValues[index] !== \"\") {\n newOtpValues[index] = \"\";\n } else if (index !== 0) {\n newOtpValues[index - 1] = \"\";\n inputRefs.current[index - 1]?.focus();\n }\n\n setOtpValues(newOtpValues);\n\n if (onChange) {\n onChange(newOtpValues);\n }\n } else if (event.code === \"ArrowRight\") {\n inputRefs.current[index + 1]?.focus();\n } else if (event.code === \"ArrowLeft\") {\n inputRefs.current[index - 1]?.focus();\n }\n };\n\n const handlePaste = (event: ClipboardEvent): void => {\n if (!event.clipboardData) return;\n\n const pastedValue = event.clipboardData.getData(\"text\");\n const autofillOtp = stripOtpFromAutofill(\n pastedValue,\n numOfInput,\n prefix\n );\n if (!handleInputFullValue(autofillOtp)) {\n event.preventDefault();\n }\n };\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n setOtpValues(new Array(numOfInput).fill(\"\"));\n\n if (!isWithinCooldown()) {\n setLastCtaTimestamp(new Date());\n setCountDown(cooldownDuration);\n }\n\n if (onClick) {\n onClick(event);\n }\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const isWithinCooldown = (): boolean => {\n const currentTime = Date.now();\n const coolDownInMilliseconds = cooldownDuration * 1000;\n\n return (\n currentTime < lastCtaTimestamp.valueOf() + coolDownInMilliseconds\n );\n };\n\n const beginCountdown = () => {\n const interval = setInterval(() => {\n const currentTime = Date.now();\n const coolDownInMilliseconds = cooldownDuration * 1000;\n\n const timer = Math.ceil(\n (lastCtaTimestamp.valueOf() +\n coolDownInMilliseconds -\n currentTime) /\n 1000\n );\n setCountDown(timer);\n if (timer <= 0) {\n if (onCooldownEnd) onCooldownEnd();\n clearInterval(interval);\n } else if (onCountdownChange) {\n onCountdownChange(timer);\n }\n }, 1000);\n\n return () => {\n clearInterval(interval);\n };\n };\n\n const generateId = (index: number, name: string, prefix?: string) => {\n return prefix\n ? `${prefix}-${name}-${index + 1}`\n : `${name}-${index + 1}`;\n };\n\n const displaySeconds = (time: number) => {\n return `${time} second${time === 1 ? \"\" : \"s\"}`;\n };\n\n const getCTALabelProps = (): Partial<\n React.HTMLAttributes<HTMLButtonElement>\n > => {\n return otherCtaProps.children\n ? { children: otherCtaProps.children }\n : {\n children:\n countDown > 0\n ? `Resend OTP in ${displaySeconds(countDown)}`\n : \"Resend OTP\",\n // use a fixed label to avoid repeated screen reader updates when the button is focused\n \"aria-label\":\n countDown > 0\n ? `Resend OTP in ${displaySeconds(cooldownDuration)}`\n : \"Resend OTP\",\n // use a secondary element to reflect the latest countdown\n \"aria-describedby\": timerId,\n };\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n return (\n <div\n id={id}\n data-testid={dataTestId}\n className={clsx(styles.wrapper, className)}\n >\n <div\n className={styles.inputContainer}\n role=\"group\"\n aria-label={`${numOfInput}-digit OTP input field`}\n >\n {prefix && (\n <Typography.BodyBL\n as=\"span\"\n className={styles.prefix}\n data-testid=\"otp-prefix\"\n weight=\"semibold\"\n >\n <VisuallyHidden>O T P prefix</VisuallyHidden>\n {`${prefix.value} ${prefix.separator}`}\n </Typography.BodyBL>\n )}\n {otpValues.map((data, index) => {\n return (\n <Input\n className={styles.inputField}\n id={generateId(index, \"otp-input\", id)}\n data-testid={generateId(\n index,\n \"otp-input\",\n dataTestId\n )}\n aria-label={`${StringHelper.formatOrdinal(\n index + 1\n )} digit`}\n aria-invalid={hasError}\n aria-describedby={hasError ? errorId : undefined}\n key={index}\n ref={(el) => (inputRefs.current[index] = el)}\n type=\"text\"\n inputMode=\"numeric\"\n value={data}\n error={hasError}\n onChange={handleChange(index)}\n onKeyDown={handleKeyDown(index)}\n autoComplete=\"off\"\n {...otherProps}\n />\n );\n })}\n </div>\n {errorMessage && (\n <FormErrorMessage id={errorId} data-testid=\"otp-error-message\">\n {errorMessage}\n </FormErrorMessage>\n )}\n {/* visually hidden elements need to be rendered before the button so that Voiceover/Chrome doesn't skip the button */}\n <VisuallyHidden role=\"timer\" id={timerId}>\n {displaySeconds(countDown)} remaining\n </VisuallyHidden>\n <VisuallyHidden aria-live=\"polite\">\n {countDown > 0 ? \"\" : \"Ready to resend OTP\"}\n </VisuallyHidden>\n {!otpOnly && (\n <Button\n className={styles.ctaButton}\n styleType={styleType}\n type=\"button\"\n sizeType=\"small\"\n {...otherCtaProps}\n onClick={handleClick}\n disabled={disabled || isWithinCooldown()}\n {...getCTALabelProps()}\n />\n )}\n </div>\n );\n};\n\n// @catalog\n/**\n * A field composed of individual inputs for a numeric one-time password\n * with an in-built countdown mechanism.\n *\n * Use `OtpInput` when users must enter the one-time password (OTP)\n * for multi-factored authentication methods.\n */\nexport const OtpInput = forwardRef(Component);\n"],"names":["OtpInput","forwardRef","_a","ref","id","value","dataTestId","className","cooldownDuration","actionButtonProps","errorMessage","numOfInput","prefix","onChange","onCooldownStart","onCooldownEnd","otpOnly","onCountdownChange","otherProps","__rest","_b","disabled","onClick","styleType","otherCtaProps","inputRefs","useRef","onChangeRef","otpValues","setOtpValues","useState","Array","fill","countDown","setCountDown","lastCtaTimestamp","setLastCtaTimestamp","Date","internalId","useId","hasError","errorId","timerId","useEffect","current","focus","document","addEventListener","handlePaste","removeEventListener","cleanup","beginCountdown","useImperativeHandle","startCooldown","length","handleInputFullValue","incomingValue","validateUserInput","incomingValueArr","split","handleChange","index","event","eventValue","target","fieldIsEmpty","every","num","autofillOtp","stripOtpFromAutofill","replace","newOtpValues","substring","handleKeyDown","key","code","_c","clipboardData","pastedValue","getData","preventDefault","isWithinCooldown","currentTime","now","coolDownInMilliseconds","valueOf","interval","setInterval","timer","Math","ceil","clearInterval","generateId","name","displaySeconds","time","_jsxs","clsx","styles.wrapper","children","styles.inputContainer","role","Typography","BodyBL","as","styles.prefix","weight","_jsx","VisuallyHidden","separator","map","data","Input","Object","assign","styles.inputField","StringHelper","formatOrdinal","undefined","el","type","inputMode","error","onKeyDown","autoComplete","FormErrorMessage","Button","styles.ctaButton","sizeType"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"otp-input.js","sources":["../../src/otp-input/otp-input.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport type React from \"react\";\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\n\nimport { Button } from \"../button\";\nimport { FormErrorMessage } from \"../form/form-label\";\nimport { Input } from \"../input\";\nimport { VisuallyHidden } from \"../shared/accessibility\";\nimport { Typography } from \"../typography\";\nimport { StringHelper, useId } from \"../util\";\nimport * as styles from \"./otp-input.styles\";\nimport type { OtpInputProps, OtpInputRef } from \"./types\";\nimport { stripOtpFromAutofill, validateUserInput } from \"./utils\";\n\nconst Component = (\n {\n id,\n value = [],\n \"data-testid\": dataTestId,\n className,\n cooldownDuration,\n actionButtonProps,\n errorMessage,\n numOfInput,\n prefix,\n onChange,\n onCooldownStart,\n onCooldownEnd,\n otpOnly,\n onCountdownChange,\n ...otherProps\n }: OtpInputProps,\n ref: React.Ref<OtpInputRef>\n) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const {\n disabled,\n onClick,\n styleType = \"secondary\",\n ...otherCtaProps\n } = actionButtonProps ?? {};\n\n const inputRefs = useRef<(HTMLInputElement | null)[]>([]);\n const onChangeRef = useRef(onChange);\n\n const [otpValues, setOtpValues] = useState<string[]>(\n new Array(numOfInput).fill(\"\")\n );\n const [countDown, setCountDown] = useState<number>(cooldownDuration);\n const [lastCtaTimestamp, setLastCtaTimestamp] = useState<Date>(new Date());\n const internalId = useId();\n\n const hasError = !!errorMessage;\n const errorId = `${internalId}-error`;\n const timerId = `${internalId}-timer`;\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n inputRefs?.current[0]?.focus();\n document.addEventListener(\"paste\", handlePaste);\n return () => document.removeEventListener(\"paste\", handlePaste);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n if (cooldownDuration !== 0) {\n if (onCooldownStart) onCooldownStart();\n const cleanup = beginCountdown();\n\n return () => cleanup();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [lastCtaTimestamp]);\n\n useImperativeHandle(ref, () => ({\n startCooldown: () => {\n setLastCtaTimestamp(new Date());\n setCountDown(cooldownDuration);\n },\n }));\n\n useEffect(() => {\n onChangeRef.current = onChange;\n }, [onChange]);\n\n useEffect(() => {\n if (value.length === numOfInput) {\n setOtpValues(value);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleInputFullValue = (incomingValue: string) => {\n if (incomingValue && validateUserInput(incomingValue, numOfInput)) {\n const incomingValueArr = incomingValue.split(\"\");\n setOtpValues(incomingValueArr);\n if (onChangeRef.current) {\n onChangeRef.current(incomingValueArr);\n }\n\n return true;\n }\n\n return false;\n };\n\n const handleChange =\n (index: number) => (event: React.ChangeEvent<HTMLInputElement>) => {\n const eventValue = event.target.value;\n\n /* handle autofill */\n const fieldIsEmpty = otpValues.every((num) => num === \"\");\n const autofillOtp = stripOtpFromAutofill(\n eventValue,\n numOfInput,\n prefix\n );\n if (fieldIsEmpty && handleInputFullValue(autofillOtp)) {\n return;\n }\n\n /* handle normal input */\n const value = eventValue.replace(/[^0-9]/g, \"\");\n if (validateUserInput(value)) {\n const newOtpValues = [...otpValues];\n\n newOtpValues[index] = value.substring(value.length - 1);\n inputRefs.current[index + 1]?.focus();\n\n setOtpValues(newOtpValues);\n\n if (onChange) {\n onChange(newOtpValues);\n }\n }\n };\n\n const handleKeyDown =\n (index: number) => (event: React.KeyboardEvent<HTMLInputElement>) => {\n const { key, code } = event;\n\n if (key === \"Backspace\" || code === \"Backspace\") {\n const newOtpValues = [...otpValues];\n if (newOtpValues[index] !== \"\") {\n newOtpValues[index] = \"\";\n } else if (index !== 0) {\n newOtpValues[index - 1] = \"\";\n inputRefs.current[index - 1]?.focus();\n }\n\n setOtpValues(newOtpValues);\n\n if (onChange) {\n onChange(newOtpValues);\n }\n } else if (event.code === \"ArrowRight\") {\n inputRefs.current[index + 1]?.focus();\n } else if (event.code === \"ArrowLeft\") {\n inputRefs.current[index - 1]?.focus();\n }\n };\n\n const handlePaste = (event: ClipboardEvent): void => {\n if (!event.clipboardData) return;\n\n const pastedValue = event.clipboardData.getData(\"text\");\n const autofillOtp = stripOtpFromAutofill(\n pastedValue,\n numOfInput,\n prefix\n );\n if (!handleInputFullValue(autofillOtp)) {\n event.preventDefault();\n }\n };\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n setOtpValues(new Array(numOfInput).fill(\"\"));\n\n if (!isWithinCooldown()) {\n setLastCtaTimestamp(new Date());\n setCountDown(cooldownDuration);\n }\n\n if (onClick) {\n onClick(event);\n }\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const isWithinCooldown = (): boolean => {\n const currentTime = Date.now();\n const coolDownInMilliseconds = cooldownDuration * 1000;\n\n return (\n currentTime < lastCtaTimestamp.valueOf() + coolDownInMilliseconds\n );\n };\n\n const beginCountdown = () => {\n const interval = setInterval(() => {\n const currentTime = Date.now();\n const coolDownInMilliseconds = cooldownDuration * 1000;\n\n const timer = Math.ceil(\n (lastCtaTimestamp.valueOf() +\n coolDownInMilliseconds -\n currentTime) /\n 1000\n );\n setCountDown(timer);\n if (timer <= 0) {\n if (onCooldownEnd) onCooldownEnd();\n clearInterval(interval);\n } else if (onCountdownChange) {\n onCountdownChange(timer);\n }\n }, 1000);\n\n return () => {\n clearInterval(interval);\n };\n };\n\n const generateId = (index: number, name: string, prefix?: string) => {\n return prefix\n ? `${prefix}-${name}-${index + 1}`\n : `${name}-${index + 1}`;\n };\n\n const displaySeconds = (time: number) => {\n return `${time} second${time === 1 ? \"\" : \"s\"}`;\n };\n\n const getCTALabelProps = (): Partial<\n React.HTMLAttributes<HTMLButtonElement>\n > => {\n return otherCtaProps.children\n ? { children: otherCtaProps.children }\n : {\n children:\n countDown > 0\n ? `Resend OTP in ${displaySeconds(countDown)}`\n : \"Resend OTP\",\n // use a fixed label to avoid repeated screen reader updates when the button is focused\n \"aria-label\":\n countDown > 0\n ? `Resend OTP in ${displaySeconds(cooldownDuration)}`\n : \"Resend OTP\",\n // use a secondary element to reflect the latest countdown\n \"aria-describedby\": timerId,\n };\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n return (\n <div\n id={id}\n data-testid={dataTestId}\n className={clsx(styles.wrapper, className)}\n >\n <div\n className={styles.inputContainer}\n role=\"group\"\n aria-label={`${numOfInput}-digit OTP input field`}\n >\n {prefix && (\n <Typography.BodyBL\n as=\"span\"\n className={styles.prefix}\n data-testid=\"otp-prefix\"\n weight=\"semibold\"\n >\n <VisuallyHidden>O T P prefix</VisuallyHidden>\n {`${prefix.value} ${prefix.separator}`}\n </Typography.BodyBL>\n )}\n {otpValues.map((data, index) => {\n return (\n <Input\n className={styles.inputField}\n id={generateId(index, \"otp-input\", id)}\n data-testid={generateId(\n index,\n \"otp-input\",\n dataTestId\n )}\n aria-label={`${StringHelper.formatOrdinal(\n index + 1\n )} digit`}\n aria-invalid={hasError}\n aria-describedby={hasError ? errorId : undefined}\n key={index}\n ref={(el) => (inputRefs.current[index] = el)}\n type=\"text\"\n inputMode=\"numeric\"\n value={data}\n error={hasError}\n onChange={handleChange(index)}\n onKeyDown={handleKeyDown(index)}\n autoComplete=\"off\"\n {...otherProps}\n />\n );\n })}\n </div>\n {errorMessage && (\n <FormErrorMessage id={errorId} data-testid=\"otp-error-message\">\n {errorMessage}\n </FormErrorMessage>\n )}\n {/* visually hidden elements need to be rendered before the button so that Voiceover/Chrome doesn't skip the button */}\n <VisuallyHidden role=\"timer\" id={timerId}>\n {displaySeconds(countDown)} remaining\n </VisuallyHidden>\n <VisuallyHidden aria-live=\"polite\">\n {countDown > 0 ? \"\" : \"Ready to resend OTP\"}\n </VisuallyHidden>\n {!otpOnly && (\n <Button\n className={styles.ctaButton}\n styleType={styleType}\n type=\"button\"\n sizeType=\"small\"\n {...otherCtaProps}\n onClick={handleClick}\n disabled={disabled || isWithinCooldown()}\n {...getCTALabelProps()}\n />\n )}\n </div>\n );\n};\n\n// @catalog\n/**\n * A field composed of individual inputs for a numeric one-time password\n * with an in-built countdown mechanism.\n *\n * Use `OtpInput` when users must enter the one-time password (OTP)\n * for multi-factored authentication methods.\n */\nexport const OtpInput = forwardRef(Component);\n"],"names":["OtpInput","forwardRef","_a","ref","id","value","dataTestId","className","cooldownDuration","actionButtonProps","errorMessage","numOfInput","prefix","onChange","onCooldownStart","onCooldownEnd","otpOnly","onCountdownChange","otherProps","__rest","_b","disabled","onClick","styleType","otherCtaProps","inputRefs","useRef","onChangeRef","otpValues","setOtpValues","useState","Array","fill","countDown","setCountDown","lastCtaTimestamp","setLastCtaTimestamp","Date","internalId","useId","hasError","errorId","timerId","useEffect","current","focus","document","addEventListener","handlePaste","removeEventListener","cleanup","beginCountdown","useImperativeHandle","startCooldown","length","handleInputFullValue","incomingValue","validateUserInput","incomingValueArr","split","handleChange","index","event","eventValue","target","fieldIsEmpty","every","num","autofillOtp","stripOtpFromAutofill","replace","newOtpValues","substring","handleKeyDown","key","code","_c","clipboardData","pastedValue","getData","preventDefault","isWithinCooldown","currentTime","now","coolDownInMilliseconds","valueOf","interval","setInterval","timer","Math","ceil","clearInterval","generateId","name","displaySeconds","time","_jsxs","clsx","styles.wrapper","children","styles.inputContainer","role","Typography","BodyBL","as","styles.prefix","weight","_jsx","VisuallyHidden","separator","map","data","Input","Object","assign","styles.inputField","StringHelper","formatOrdinal","undefined","el","type","inputMode","error","onKeyDown","autoComplete","FormErrorMessage","Button","styles.ctaButton","sizeType"],"mappings":"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"}
|