@reykjavik/hanna-react 0.10.84 → 0.10.85
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/AccordionList.d.ts +2 -2
- package/AccordionList.js +5 -5
- package/ActionCards.d.ts +2 -2
- package/ActionCards.js +4 -4
- package/Alert.d.ts +1 -1
- package/Alert.js +6 -6
- package/ArticleCards.d.ts +1 -1
- package/ArticleCards.js +2 -2
- package/ArticleCarousel/_ArticleCarouselCard.d.ts +2 -2
- package/ArticleCarousel/_ArticleCarouselCard.js +7 -7
- package/ArticleCarousel.d.ts +3 -3
- package/ArticleCarousel.js +3 -3
- package/ArticleMeta.js +2 -2
- package/BasicTable.d.ts +1 -1
- package/BasicTable.js +2 -2
- package/BgBox.d.ts +1 -1
- package/BgBox.js +3 -3
- package/Bling.js +2 -2
- package/BlockQuote.d.ts +1 -1
- package/BlockQuote.js +2 -2
- package/BreadCrumbs.js +2 -2
- package/ButtonBack.d.ts +1 -1
- package/ButtonBack.js +2 -2
- package/ButtonPrimary.d.ts +1 -1
- package/ButtonPrimary.js +2 -2
- package/ButtonSecondary.d.ts +1 -1
- package/ButtonSecondary.js +2 -2
- package/ButtonTertiary.d.ts +1 -1
- package/ButtonTertiary.js +2 -2
- package/CHANGELOG.md +7 -0
- package/Carousel.d.ts +2 -2
- package/Carousel.js +2 -2
- package/CenterColumn.d.ts +1 -1
- package/CenterColumn.js +2 -2
- package/Checkbox.d.ts +1 -1
- package/Checkbox.js +2 -2
- package/CheckboxButton.d.ts +1 -1
- package/CheckboxButton.js +2 -2
- package/CheckboxButtonsGroup.d.ts +1 -1
- package/CheckboxButtonsGroup.js +3 -3
- package/CheckboxGroup.d.ts +1 -1
- package/CheckboxGroup.js +3 -3
- package/CityBlock.d.ts +4 -4
- package/CityBlock.js +4 -4
- package/ContactBubble.d.ts +1 -1
- package/ContactBubble.js +6 -6
- package/ContentArticle.d.ts +4 -4
- package/ContentArticle.js +14 -14
- package/ContentImage.d.ts +1 -1
- package/ContentImage.js +2 -2
- package/Datepicker.d.ts +1 -1
- package/Datepicker.js +2 -2
- package/ExtraLinks.d.ts +2 -2
- package/ExtraLinks.js +6 -6
- package/FeatureList.d.ts +1 -1
- package/FeatureList.js +4 -4
- package/FileInput.d.ts +2 -2
- package/FileInput.js +4 -4
- package/Foonote.d.ts +1 -1
- package/Foonote.js +2 -2
- package/FooterBadges.js +2 -2
- package/Form.d.ts +1 -1
- package/FormField.d.ts +1 -1
- package/FormField.js +4 -4
- package/Gallery/_GalleryItem.d.ts +1 -1
- package/Gallery/_GalleryItem.js +7 -7
- package/Gallery/_GalleryModal.d.ts +1 -1
- package/Gallery/_GalleryModal.js +4 -4
- package/Gallery/_GalleryModalContext.d.ts +2 -2
- package/Gallery/_GalleryModalItem.d.ts +1 -1
- package/Gallery/_GalleryModalItem.js +2 -2
- package/Gallery.d.ts +4 -4
- package/Gallery.js +7 -7
- package/GridBlocks.d.ts +3 -3
- package/GridBlocks.js +8 -8
- package/Heading.d.ts +1 -1
- package/HeroBlock.d.ts +3 -3
- package/HeroBlock.js +8 -8
- package/Illustration.d.ts +1 -1
- package/Illustration.js +2 -2
- package/ImageCards.d.ts +2 -2
- package/ImageCards.js +4 -4
- package/InfoBlock.d.ts +1 -1
- package/InfoBlock.js +2 -2
- package/InfoHero.d.ts +3 -3
- package/InfoHero.js +10 -10
- package/IslandBlock.d.ts +4 -4
- package/IslandBlock.js +4 -4
- package/IslandPageBlock.d.ts +4 -4
- package/IslandPageBlock.js +4 -4
- package/LabeledTextBlock.d.ts +2 -2
- package/LabeledTextBlock.js +4 -4
- package/Layout.d.ts +1 -1
- package/Layout.js +13 -13
- package/MainMenu/_Auxiliary.d.ts +1 -1
- package/MainMenu/_Auxiliary.js +2 -2
- package/MainMenu/_PrimaryPanel.js +2 -2
- package/MainMenu.d.ts +3 -3
- package/MainMenu.js +15 -13
- package/MiniMetrics.d.ts +2 -2
- package/MiniMetrics.js +4 -4
- package/NameCard.js +4 -4
- package/NameCards.d.ts +1 -1
- package/NameCards.js +2 -2
- package/NewsHero.d.ts +2 -2
- package/NewsHero.js +7 -7
- package/PageFilter.d.ts +1 -1
- package/PageFilter.js +4 -4
- package/PageHeading.d.ts +1 -1
- package/PageHeading.js +2 -2
- package/Picture.d.ts +1 -1
- package/Picture.js +2 -2
- package/PullQuote.d.ts +1 -1
- package/PullQuote.js +2 -2
- package/RadioButtonsGroup.d.ts +1 -1
- package/RadioButtonsGroup.js +4 -4
- package/RadioGroup.d.ts +2 -2
- package/RadioGroup.js +4 -4
- package/RelatedLinks.js +2 -2
- package/RowBlock.d.ts +1 -1
- package/RowBlock.js +2 -2
- package/SearchInput.d.ts +1 -1
- package/SearchInput.js +2 -2
- package/SearchResults/_SearchResultsItem.js +4 -4
- package/SearchResults.d.ts +2 -2
- package/SearchResults.js +7 -7
- package/SeenEffect.d.ts +1 -1
- package/SeenEffect.js +3 -3
- package/Selectbox.d.ts +2 -2
- package/Selectbox.js +2 -2
- package/ShareButtons.d.ts +1 -1
- package/ShareButtons.js +2 -2
- package/SiteSearchAutocomplete.js +2 -2
- package/SiteSearchCurtain.js +2 -2
- package/SiteSearchInput.d.ts +2 -2
- package/SiteSearchInput.js +2 -2
- package/SubHeading.d.ts +2 -2
- package/SubHeading.js +2 -2
- package/Tabs.d.ts +2 -2
- package/Tabs.js +4 -4
- package/TagPill.d.ts +1 -1
- package/TagPill.js +3 -3
- package/TextBlock.d.ts +2 -2
- package/TextBlock.js +2 -2
- package/TextButton.d.ts +1 -1
- package/TextButton.js +2 -2
- package/TextInput.d.ts +1 -1
- package/TextInput.js +2 -2
- package/VerticalTabsTOC.d.ts +1 -1
- package/VerticalTabsTOC.js +2 -2
- package/WizardLayout.d.ts +1 -1
- package/WizardLayout.js +8 -8
- package/WizardLayoutClose.d.ts +1 -1
- package/WizardLayoutClose.js +2 -2
- package/_abstract/_AbstractCarousel.d.ts +2 -2
- package/_abstract/_AbstractCarousel.js +6 -6
- package/_abstract/_Blings.d.ts +1 -1
- package/_abstract/_Blings.js +2 -2
- package/_abstract/_Block.d.ts +3 -3
- package/_abstract/_Block.js +6 -6
- package/_abstract/_Button.js +2 -2
- package/_abstract/_CardList.d.ts +1 -1
- package/_abstract/_CardList.js +4 -4
- package/_abstract/_Image.js +2 -2
- package/_abstract/_Quote.js +2 -2
- package/_abstract/_TogglerGroup.d.ts +2 -2
- package/_abstract/_TogglerGroup.js +2 -2
- package/_abstract/_TogglerGroupField.d.ts +3 -3
- package/_abstract/_TogglerGroupField.js +4 -4
- package/assets.d.ts +2 -2
- package/esm/AccordionList.d.ts +25 -0
- package/esm/AccordionList.js +32 -0
- package/esm/ActionCards.d.ts +6 -0
- package/esm/ActionCards.js +9 -0
- package/esm/Alert.d.ts +48 -0
- package/esm/Alert.js +90 -0
- package/esm/ArticleCards.d.ts +8 -0
- package/esm/ArticleCards.js +4 -0
- package/esm/ArticleCarousel/_ArticleCarouselCard.d.ts +28 -0
- package/esm/ArticleCarousel/_ArticleCarouselCard.js +24 -0
- package/esm/ArticleCarousel.d.ts +12 -0
- package/esm/ArticleCarousel.js +8 -0
- package/esm/ArticleMeta.d.ts +10 -0
- package/esm/ArticleMeta.js +19 -0
- package/esm/Attention.d.ts +7 -0
- package/esm/Attention.js +4 -0
- package/esm/BasicTable.d.ts +14 -0
- package/esm/BasicTable.js +29 -0
- package/esm/BgBox.d.ts +8 -0
- package/esm/BgBox.js +9 -0
- package/esm/Bling.d.ts +81 -0
- package/esm/Bling.js +44 -0
- package/esm/BlockBreak.d.ts +2 -0
- package/esm/BlockBreak.js +6 -0
- package/esm/BlockQuote.d.ts +4 -0
- package/esm/BlockQuote.js +4 -0
- package/esm/BreadCrumbs.d.ts +11 -0
- package/esm/BreadCrumbs.js +28 -0
- package/esm/ButtonBack.d.ts +7 -0
- package/esm/ButtonBack.js +4 -0
- package/esm/ButtonBar.d.ts +17 -0
- package/esm/ButtonBar.js +15 -0
- package/esm/ButtonPrimary.d.ts +7 -0
- package/esm/ButtonPrimary.js +4 -0
- package/esm/ButtonSecondary.d.ts +7 -0
- package/esm/ButtonSecondary.js +4 -0
- package/esm/ButtonTertiary.d.ts +12 -0
- package/esm/ButtonTertiary.js +15 -0
- package/esm/Carousel.d.ts +4 -0
- package/esm/Carousel.js +4 -0
- package/esm/CarouselStepper.d.ts +4 -0
- package/esm/CarouselStepper.js +4 -0
- package/esm/CenterColumn.d.ts +7 -0
- package/esm/CenterColumn.js +7 -0
- package/esm/Checkbox.d.ts +4 -0
- package/esm/Checkbox.js +4 -0
- package/esm/CheckboxButton.d.ts +4 -0
- package/esm/CheckboxButton.js +4 -0
- package/esm/CheckboxButtonsGroup.d.ts +12 -0
- package/esm/CheckboxButtonsGroup.js +13 -0
- package/esm/CheckboxGroup.d.ts +10 -0
- package/esm/CheckboxGroup.js +7 -0
- package/esm/CityBlock.d.ts +21 -0
- package/esm/CityBlock.js +18 -0
- package/esm/ContactBubble.d.ts +58 -0
- package/esm/ContactBubble.js +152 -0
- package/esm/ContentArticle.d.ts +16 -0
- package/esm/ContentArticle.js +24 -0
- package/esm/ContentImage.d.ts +8 -0
- package/esm/ContentImage.js +18 -0
- package/esm/Datepicker.d.ts +40 -0
- package/esm/Datepicker.js +78 -0
- package/esm/ExtraLinks.d.ts +18 -0
- package/esm/ExtraLinks.js +24 -0
- package/esm/FeatureList.d.ts +12 -0
- package/esm/FeatureList.js +16 -0
- package/esm/FieldGroup.d.ts +10 -0
- package/esm/FieldGroup.js +9 -0
- package/esm/FileInput/_FileInput.utils.d.ts +36 -0
- package/esm/FileInput/_FileInput.utils.js +69 -0
- package/esm/FileInput/_FileInputFileList.d.ts +11 -0
- package/esm/FileInput/_FileInputFileList.js +19 -0
- package/esm/FileInput.d.ts +48 -0
- package/esm/FileInput.js +130 -0
- package/esm/Foonote.d.ts +12 -0
- package/esm/Foonote.js +7 -0
- package/esm/FooterBadges.d.ts +9 -0
- package/esm/FooterBadges.js +12 -0
- package/esm/FooterInfo.d.ts +20 -0
- package/esm/FooterInfo.js +12 -0
- package/esm/Footnote.d.ts +6 -0
- package/esm/Footnote.js +3 -0
- package/esm/Form.d.ts +7 -0
- package/esm/Form.js +10 -0
- package/esm/FormField.d.ts +65 -0
- package/esm/FormField.js +92 -0
- package/esm/Gallery/_GalleryItem.d.ts +7 -0
- package/esm/Gallery/_GalleryItem.js +19 -0
- package/esm/Gallery/_GalleryModal.d.ts +6 -0
- package/esm/Gallery/_GalleryModal.js +53 -0
- package/esm/Gallery/_GalleryModalContext.d.ts +9 -0
- package/esm/Gallery/_GalleryModalContext.js +2 -0
- package/esm/Gallery/_GalleryModalItem.d.ts +2 -0
- package/esm/Gallery/_GalleryModalItem.js +11 -0
- package/esm/Gallery.d.ts +17 -0
- package/esm/Gallery.js +27 -0
- package/esm/GridBlocks.d.ts +26 -0
- package/esm/GridBlocks.js +24 -0
- package/esm/Heading.d.ts +22 -0
- package/esm/Heading.js +19 -0
- package/esm/HeroBlock.d.ts +19 -0
- package/esm/HeroBlock.js +21 -0
- package/esm/IframeBlock.d.ts +28 -0
- package/esm/IframeBlock.js +26 -0
- package/esm/Illustration.d.ts +10 -0
- package/esm/Illustration.js +8 -0
- package/esm/ImageCards.d.ts +10 -0
- package/esm/ImageCards.js +12 -0
- package/esm/InfoBlock.d.ts +13 -0
- package/esm/InfoBlock.js +13 -0
- package/esm/InfoHero.d.ts +18 -0
- package/esm/InfoHero.js +83 -0
- package/esm/IslandBlock.d.ts +25 -0
- package/esm/IslandBlock.js +16 -0
- package/esm/IslandPageBlock.d.ts +24 -0
- package/esm/IslandPageBlock.js +16 -0
- package/esm/LabeledTextBlock.d.ts +11 -0
- package/esm/LabeledTextBlock.js +14 -0
- package/esm/Layout.d.ts +32 -0
- package/esm/Layout.js +56 -0
- package/esm/MainMenu/_Auxiliary.d.ts +6 -0
- package/esm/MainMenu/_Auxiliary.js +13 -0
- package/esm/MainMenu/_PrimaryPanel.d.ts +29 -0
- package/esm/MainMenu/_PrimaryPanel.js +22 -0
- package/esm/MainMenu.d.ts +62 -0
- package/esm/MainMenu.js +221 -0
- package/esm/MiniMetrics.d.ts +8 -0
- package/esm/MiniMetrics.js +12 -0
- package/esm/Modal.d.ts +8 -0
- package/esm/Modal.js +14 -0
- package/esm/NameCard.d.ts +64 -0
- package/esm/NameCard.js +82 -0
- package/esm/NameCards.d.ts +6 -0
- package/esm/NameCards.js +7 -0
- package/esm/NewsHero.d.ts +14 -0
- package/esm/NewsHero.js +86 -0
- package/esm/PageFilter.d.ts +16 -0
- package/esm/PageFilter.js +15 -0
- package/esm/PageHeading.d.ts +10 -0
- package/esm/PageHeading.js +12 -0
- package/esm/Picture.d.ts +7 -0
- package/esm/Picture.js +8 -0
- package/esm/ProcessOverview.d.ts +13 -0
- package/esm/ProcessOverview.js +17 -0
- package/esm/PullQuote.d.ts +4 -0
- package/esm/PullQuote.js +4 -0
- package/esm/RadioButtonsGroup.d.ts +12 -0
- package/esm/RadioButtonsGroup.js +14 -0
- package/esm/RadioGroup.d.ts +16 -0
- package/esm/RadioGroup.js +8 -0
- package/esm/RelatedLinks.d.ts +20 -0
- package/esm/RelatedLinks.js +26 -0
- package/esm/RowBlock.d.ts +12 -0
- package/esm/RowBlock.js +9 -0
- package/esm/RowBlockColumn.d.ts +8 -0
- package/esm/RowBlockColumn.js +11 -0
- package/esm/SearchInput.d.ts +18 -0
- package/esm/SearchInput.js +23 -0
- package/esm/SearchResults/_SearchResultsItem.d.ts +18 -0
- package/esm/SearchResults/_SearchResultsItem.js +14 -0
- package/esm/SearchResults.d.ts +37 -0
- package/esm/SearchResults.js +108 -0
- package/esm/SeenEffect.d.ts +4 -0
- package/esm/SeenEffect.js +9 -0
- package/esm/Selectbox.d.ts +11 -0
- package/esm/Selectbox.js +40 -0
- package/esm/ShareButtons.d.ts +9 -0
- package/esm/ShareButtons.js +56 -0
- package/esm/Sharpie.d.ts +23 -0
- package/esm/Sharpie.js +22 -0
- package/esm/SiteSearchAutocomplete.d.ts +40 -0
- package/esm/SiteSearchAutocomplete.js +48 -0
- package/esm/SiteSearchCurtain.d.ts +6 -0
- package/esm/SiteSearchCurtain.js +28 -0
- package/esm/SiteSearchInput.d.ts +24 -0
- package/esm/SiteSearchInput.js +30 -0
- package/esm/Skeleton.d.ts +25 -0
- package/esm/Skeleton.js +30 -0
- package/esm/SubHeading.d.ts +10 -0
- package/esm/SubHeading.js +13 -0
- package/esm/Tabs.d.ts +35 -0
- package/esm/Tabs.js +94 -0
- package/esm/TagPill.d.ts +25 -0
- package/esm/TagPill.js +34 -0
- package/esm/TextBlock.d.ts +15 -0
- package/esm/TextBlock.js +15 -0
- package/esm/TextButton.d.ts +9 -0
- package/esm/TextButton.js +9 -0
- package/esm/TextInput.d.ts +16 -0
- package/esm/TextInput.js +32 -0
- package/esm/Tooltip.d.ts +7 -0
- package/esm/Tooltip.js +58 -0
- package/esm/VSpacer.d.ts +22 -0
- package/esm/VSpacer.js +41 -0
- package/esm/VerticalTabsTOC.d.ts +14 -0
- package/esm/VerticalTabsTOC.js +68 -0
- package/esm/WizardLayout.d.ts +15 -0
- package/esm/WizardLayout.js +30 -0
- package/esm/WizardLayoutClose.d.ts +3 -0
- package/esm/WizardLayoutClose.js +4 -0
- package/esm/WizardStepper.d.ts +36 -0
- package/esm/WizardStepper.js +26 -0
- package/esm/_abstract/_AbstractCarousel.d.ts +29 -0
- package/esm/_abstract/_AbstractCarousel.js +108 -0
- package/esm/_abstract/_Blings.d.ts +11 -0
- package/esm/_abstract/_Blings.js +11 -0
- package/esm/_abstract/_Block.d.ts +21 -0
- package/esm/_abstract/_Block.js +23 -0
- package/esm/_abstract/_Button.d.ts +40 -0
- package/esm/_abstract/_Button.js +36 -0
- package/esm/_abstract/_CardList.d.ts +34 -0
- package/esm/_abstract/_CardList.js +37 -0
- package/esm/_abstract/_Image.d.ts +36 -0
- package/esm/_abstract/_Image.js +26 -0
- package/esm/_abstract/_Link.d.ts +60 -0
- package/esm/_abstract/_Link.js +64 -0
- package/esm/_abstract/_Quote.d.ts +11 -0
- package/esm/_abstract/_Quote.js +8 -0
- package/esm/_abstract/_TogglerGroup.d.ts +32 -0
- package/esm/_abstract/_TogglerGroup.js +28 -0
- package/esm/_abstract/_TogglerGroupField.d.ts +19 -0
- package/esm/_abstract/_TogglerGroupField.js +17 -0
- package/esm/_abstract/_TogglerInput.d.ts +23 -0
- package/esm/_abstract/_TogglerInput.js +23 -0
- package/esm/_abstract/breakOnNL.d.ts +1 -0
- package/esm/_abstract/breakOnNL.js +7 -0
- package/esm/assets.d.ts +42 -0
- package/esm/assets.js +58 -0
- package/esm/constants.d.ts +19 -0
- package/esm/constants.js +22 -0
- package/esm/focus-visible.d.ts +1 -0
- package/esm/focus-visible.js +3 -0
- package/esm/index.d.ts +97 -0
- package/esm/index.js +1 -0
- package/esm/package.json +1 -0
- package/esm/utils/HannaUIState.d.ts +8 -0
- package/esm/utils/HannaUIState.js +7 -0
- package/esm/utils/browserSide.d.ts +1 -0
- package/esm/utils/browserSide.js +1 -0
- package/esm/utils/config.d.ts +4 -0
- package/esm/utils/config.js +2 -0
- package/esm/utils/env.d.ts +1 -0
- package/esm/utils/env.js +8 -0
- package/esm/utils/seenEffect.d.ts +27 -0
- package/esm/utils/seenEffect.js +75 -0
- package/esm/utils/useDidChange.d.ts +37 -0
- package/esm/utils/useDidChange.js +43 -0
- package/esm/utils/useFormatMonitor.d.ts +38 -0
- package/esm/utils/useFormatMonitor.js +41 -0
- package/esm/utils/useGetSVGtext.d.ts +10 -0
- package/esm/utils/useGetSVGtext.js +23 -0
- package/esm/utils/useMenuToggling.d.ts +8 -0
- package/esm/utils/useMenuToggling.js +62 -0
- package/esm/utils/useMixedControlState.d.ts +137 -0
- package/esm/utils/useMixedControlState.js +101 -0
- package/esm/utils/useScrollbarWidthCSSVar.d.ts +17 -0
- package/esm/utils/useScrollbarWidthCSSVar.js +19 -0
- package/esm/utils.d.ts +8 -0
- package/esm/utils.js +8 -0
- package/package.json +389 -3
- package/utils/config.d.ts +2 -2
- package/utils/config.js +2 -2
- package/utils/useDidChange.d.ts +1 -1
- package/utils/useDidChange.js +1 -1
- package/utils/useMenuToggling.js +2 -2
- package/utils.d.ts +8 -8
- package/utils.js +8 -8
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { DefaultTexts } from '@reykjavik/hanna-utils/i18n';
|
|
2
|
+
import { SSRSupport } from './utils.js';
|
|
3
|
+
export type ContactBubbleI18n = {
|
|
4
|
+
lang?: string;
|
|
5
|
+
openBtn: string;
|
|
6
|
+
openBtnLong?: string;
|
|
7
|
+
closeBtn: string;
|
|
8
|
+
closeBtnLong?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare const defaultTexts: DefaultTexts<ContactBubbleI18n>;
|
|
11
|
+
declare const icons: {
|
|
12
|
+
readonly suggestions: 1;
|
|
13
|
+
readonly phone: 1;
|
|
14
|
+
readonly faq: 1;
|
|
15
|
+
readonly livechat: 1;
|
|
16
|
+
readonly other: 0;
|
|
17
|
+
};
|
|
18
|
+
export type ContactBubbleIcon = keyof typeof icons;
|
|
19
|
+
export declare const ensureIcon: (maybeIcon: string | undefined) => ContactBubbleIcon | undefined;
|
|
20
|
+
export type ContactBubbleItem = {
|
|
21
|
+
label: string;
|
|
22
|
+
extraLabel?: string;
|
|
23
|
+
icon?: ContactBubbleIcon;
|
|
24
|
+
} & ({
|
|
25
|
+
href: string;
|
|
26
|
+
/** Prevents default link behavior unless the handler function returns `true` */
|
|
27
|
+
onClick?: () => void | boolean;
|
|
28
|
+
target?: string;
|
|
29
|
+
} | {
|
|
30
|
+
onClick: () => void | boolean;
|
|
31
|
+
href?: undefined;
|
|
32
|
+
target?: undefined;
|
|
33
|
+
});
|
|
34
|
+
export type ContactBubbleProps = {
|
|
35
|
+
title?: string;
|
|
36
|
+
links: Array<ContactBubbleItem>;
|
|
37
|
+
/** By default the ContactBubble's toggler is hidden if the page
|
|
38
|
+
* is scrolled to near the top or the bottom.
|
|
39
|
+
*
|
|
40
|
+
* This means that on short pages (with hardly any scrolling)
|
|
41
|
+
* the ContactBubble **always** hidden.
|
|
42
|
+
*
|
|
43
|
+
* Set this prop to `true` if you want to disable this
|
|
44
|
+
* magic and always show the bubble toggler
|
|
45
|
+
*/
|
|
46
|
+
alwaysShow?: boolean;
|
|
47
|
+
texts?: ContactBubbleI18n;
|
|
48
|
+
lang?: string;
|
|
49
|
+
ssr?: SSRSupport;
|
|
50
|
+
} & ({
|
|
51
|
+
open?: boolean;
|
|
52
|
+
onToggle: (isOpen: boolean) => void;
|
|
53
|
+
} | {
|
|
54
|
+
open?: undefined;
|
|
55
|
+
onToggle?: (isOpen: boolean) => void;
|
|
56
|
+
});
|
|
57
|
+
export declare const ContactBubble: (props: ContactBubbleProps) => JSX.Element | null;
|
|
58
|
+
export default ContactBubble;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import focusElm from '@hugsmidjan/qj/focusElm';
|
|
3
|
+
import { useDomid } from '@hugsmidjan/react/hooks';
|
|
4
|
+
import getBemClass from '@hugsmidjan/react/utils/getBemClass';
|
|
5
|
+
import { getPageScrollElm } from '@reykjavik/hanna-utils';
|
|
6
|
+
import { getTexts } from '@reykjavik/hanna-utils/i18n';
|
|
7
|
+
import { Link } from './_abstract/_Link.js';
|
|
8
|
+
import { breakOnNL } from './_abstract/breakOnNL.js';
|
|
9
|
+
import { useIsBrowserSide } from './utils.js';
|
|
10
|
+
export const defaultTexts = {
|
|
11
|
+
is: {
|
|
12
|
+
lang: 'is',
|
|
13
|
+
openBtn: 'Hafa samband',
|
|
14
|
+
closeBtn: 'Loka',
|
|
15
|
+
closeBtnLong: 'Loka valmynd',
|
|
16
|
+
},
|
|
17
|
+
en: {
|
|
18
|
+
lang: 'en',
|
|
19
|
+
openBtn: 'Contact us',
|
|
20
|
+
closeBtn: 'Close',
|
|
21
|
+
closeBtnLong: 'Close bubble',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
const icons = {
|
|
26
|
+
suggestions: 1,
|
|
27
|
+
phone: 1,
|
|
28
|
+
faq: 1,
|
|
29
|
+
livechat: 1,
|
|
30
|
+
other: 0,
|
|
31
|
+
};
|
|
32
|
+
export const ensureIcon = (maybeIcon) => maybeIcon && icons[maybeIcon]
|
|
33
|
+
? maybeIcon
|
|
34
|
+
: undefined;
|
|
35
|
+
export const ContactBubble = (props) => {
|
|
36
|
+
const { title, links, onToggle, alwaysShow } = props;
|
|
37
|
+
const txt = getTexts(props, defaultTexts);
|
|
38
|
+
const useLocalState = props.open == null;
|
|
39
|
+
const [localOpen, setLocalOpen] = useState(false);
|
|
40
|
+
const open = useLocalState ? localOpen : props.open;
|
|
41
|
+
const isBrowser = useIsBrowserSide(props.ssr);
|
|
42
|
+
const domid = useDomid();
|
|
43
|
+
const wrapperRef = useRef(null);
|
|
44
|
+
const { openBubble, closeBubble } = useMemo(() => ({
|
|
45
|
+
openBubble: () => {
|
|
46
|
+
useLocalState && setLocalOpen(true);
|
|
47
|
+
onToggle && onToggle(true);
|
|
48
|
+
},
|
|
49
|
+
closeBubble: (setFocus) => {
|
|
50
|
+
useLocalState && setLocalOpen(false);
|
|
51
|
+
onToggle && onToggle(false);
|
|
52
|
+
setFocus !== false && focusElm(wrapperRef.current);
|
|
53
|
+
},
|
|
54
|
+
}), [useLocalState, onToggle]);
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
const wrapperElm = wrapperRef.current;
|
|
57
|
+
if (!wrapperElm) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (alwaysShow) {
|
|
61
|
+
wrapperElm.dataset.show = 'true';
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const scrollElm = getPageScrollElm();
|
|
65
|
+
let pending = 0;
|
|
66
|
+
const checkScroll = () => {
|
|
67
|
+
if (!pending) {
|
|
68
|
+
pending = requestAnimationFrame(() => {
|
|
69
|
+
const { scrollTop, scrollHeight, clientHeight } = scrollElm;
|
|
70
|
+
const scrollLength = scrollHeight - clientHeight;
|
|
71
|
+
// const f = scrollLength > 600 ? 1 : (scrollLength - 200) / 600;
|
|
72
|
+
const f = 1;
|
|
73
|
+
const show = scrollTop > f * 150 && scrollLength - scrollTop > f * 250;
|
|
74
|
+
wrapperElm.dataset.show = String(show);
|
|
75
|
+
!show && closeBubble(false);
|
|
76
|
+
pending = 0;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
checkScroll();
|
|
81
|
+
// Set scroll-listeners on both the ´document` and the `scrollElm`
|
|
82
|
+
// because mobile browsers seem to handle CSS height and overflow
|
|
83
|
+
// rules on <html> and <body> differently from desktop browsers.
|
|
84
|
+
// Only one of these two handlers seems to trigger though,
|
|
85
|
+
// (as Element scroll events don't bubble)
|
|
86
|
+
// and even if they did, the rAF throttling prevents that from
|
|
87
|
+
// becoming a problem.
|
|
88
|
+
document.addEventListener('scroll', checkScroll);
|
|
89
|
+
scrollElm.addEventListener('scroll', checkScroll);
|
|
90
|
+
return () => {
|
|
91
|
+
document.removeEventListener('scroll', checkScroll);
|
|
92
|
+
scrollElm.removeEventListener('scroll', checkScroll);
|
|
93
|
+
};
|
|
94
|
+
}, [isBrowser, alwaysShow, closeBubble]);
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
const escHandler = (e) => e.key === 'Escape' && closeBubble();
|
|
97
|
+
const outsideClickHandler = (e) => {
|
|
98
|
+
var _a;
|
|
99
|
+
if (open && !((_a = wrapperRef.current) === null || _a === void 0 ? void 0 : _a.contains(e.target))) {
|
|
100
|
+
closeBubble(false);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
document.addEventListener('keydown', escHandler);
|
|
104
|
+
document.addEventListener('click', outsideClickHandler, true);
|
|
105
|
+
const htmlDataset = document.documentElement.dataset;
|
|
106
|
+
if (open) {
|
|
107
|
+
htmlDataset.contactBubble = 'true';
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
delete htmlDataset.contactBubble;
|
|
111
|
+
}
|
|
112
|
+
return () => {
|
|
113
|
+
delete htmlDataset.contactBubble;
|
|
114
|
+
document.removeEventListener('keydown', escHandler);
|
|
115
|
+
document.removeEventListener('click', outsideClickHandler, true);
|
|
116
|
+
};
|
|
117
|
+
}, [open, closeBubble]);
|
|
118
|
+
if (links.length === 0) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
const menu = (React.createElement("div", { className: "ContactBubble", id: isBrowser && domid, hidden: isBrowser && !open, "data-always-show": alwaysShow || undefined, "data-sprinkled": isBrowser },
|
|
122
|
+
React.createElement("h2", { className: "ContactBubble__title" }, title || txt.openBtn),
|
|
123
|
+
React.createElement("ul", { className: "ContactBubble__list" }, links.map((linkInfo, i) => {
|
|
124
|
+
const { href, label, extraLabel, target, onClick } = linkInfo;
|
|
125
|
+
const icon = ensureIcon(linkInfo.icon);
|
|
126
|
+
const itemClass = getBemClass('ContactBubble__item', icon && 'type--' + icon);
|
|
127
|
+
const onClickHandler = (e) => {
|
|
128
|
+
if (onClick) {
|
|
129
|
+
const doPreventDefault = onClick() !== true;
|
|
130
|
+
if (doPreventDefault) {
|
|
131
|
+
e.preventDefault();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
closeBubble(false);
|
|
135
|
+
};
|
|
136
|
+
const content = [
|
|
137
|
+
' ',
|
|
138
|
+
label,
|
|
139
|
+
'\n',
|
|
140
|
+
extraLabel && React.createElement("small", { key: "\uD83E\uDD21" }, breakOnNL(extraLabel)),
|
|
141
|
+
'\n',
|
|
142
|
+
];
|
|
143
|
+
return (React.createElement("li", { key: i, className: itemClass }, href && href !== '#' ? (React.createElement(Link, { className: "ContactBubble__link", href: href, onClick: onClickHandler, target: target }, content)) : (React.createElement("button", { className: "ContactBubble__link", onClick: onClickHandler, type: "button" }, content))));
|
|
144
|
+
})),
|
|
145
|
+
'\n\n',
|
|
146
|
+
isBrowser && (React.createElement("button", { className: "ContactBubble__closebtn", "aria-controls": domid, "aria-label": txt.closeBtnLong, onClick: () => closeBubble(), type: "button" }, txt.closeBtn))));
|
|
147
|
+
return isBrowser ? (React.createElement("div", { className: "ContactBubble__wrapper", ref: wrapperRef },
|
|
148
|
+
React.createElement("button", { className: "ContactBubble__openbtn", "aria-controls": domid, "aria-expanded": open, "aria-label": txt.openBtnLong, onClick: open ? () => closeBubble() : openBubble, type: "button" }, txt.openBtn),
|
|
149
|
+
'\n\n',
|
|
150
|
+
menu)) : (menu);
|
|
151
|
+
};
|
|
152
|
+
export default ContactBubble;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { SeenProp } from './utils/seenEffect.js';
|
|
3
|
+
import { ArticleMetaProps } from './ArticleMeta.js';
|
|
4
|
+
import { ContentImageProps } from './ContentImage.js';
|
|
5
|
+
import { RelatedLinksProps } from './RelatedLinks.js';
|
|
6
|
+
export type ContentArticleProps = {
|
|
7
|
+
/** Date, author, etc. */
|
|
8
|
+
meta?: ArticleMetaProps['items'];
|
|
9
|
+
headline: string;
|
|
10
|
+
headlineTag?: 'h1' | 'h2';
|
|
11
|
+
topImage?: ContentImageProps;
|
|
12
|
+
body: ReactNode;
|
|
13
|
+
relatedLinks?: RelatedLinksProps;
|
|
14
|
+
} & SeenProp;
|
|
15
|
+
export declare const ContentArticle: (props: ContentArticleProps) => JSX.Element;
|
|
16
|
+
export default ContentArticle;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useSeenEffect } from './utils/seenEffect.js';
|
|
3
|
+
import ArticleMeta from './ArticleMeta.js';
|
|
4
|
+
import ContentImage from './ContentImage.js';
|
|
5
|
+
import Heading from './Heading.js';
|
|
6
|
+
import RelatedLinks from './RelatedLinks.js';
|
|
7
|
+
import TextBlock from './TextBlock.js';
|
|
8
|
+
import VSpacer from './VSpacer.js';
|
|
9
|
+
export const ContentArticle = (props) => {
|
|
10
|
+
const { relatedLinks } = props;
|
|
11
|
+
const [ref] = useSeenEffect(props.startSeen);
|
|
12
|
+
const headingElm = (React.createElement(Heading, { forceH1: props.headlineTag === 'h1' }, props.headline));
|
|
13
|
+
return (React.createElement("div", { className: "ContentArticle", ref: ref },
|
|
14
|
+
props.meta ? (React.createElement("div", { className: "ContentArticle__header" },
|
|
15
|
+
headingElm,
|
|
16
|
+
React.createElement(ArticleMeta, { items: props.meta }))) : (headingElm),
|
|
17
|
+
React.createElement(TextBlock, { startSeen: true },
|
|
18
|
+
props.topImage && React.createElement(ContentImage, Object.assign({}, props.topImage)),
|
|
19
|
+
props.body),
|
|
20
|
+
relatedLinks && relatedLinks.links.length > 0 && (React.createElement(VSpacer, { size: "small" },
|
|
21
|
+
React.createElement("hr", null))),
|
|
22
|
+
relatedLinks && React.createElement(RelatedLinks, Object.assign({}, relatedLinks))));
|
|
23
|
+
};
|
|
24
|
+
export default ContentArticle;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ImageProps } from './_abstract/_Image.js';
|
|
2
|
+
export type ContentImageProps = {
|
|
3
|
+
image?: ImageProps;
|
|
4
|
+
caption?: string | JSX.Element;
|
|
5
|
+
credit?: string | JSX.Element;
|
|
6
|
+
};
|
|
7
|
+
export declare const ContentImage: (props: ContentImageProps) => JSX.Element;
|
|
8
|
+
export default ContentImage;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Image } from './_abstract/_Image.js';
|
|
3
|
+
export const ContentImage = (props) => {
|
|
4
|
+
const { image, caption, credit } = props;
|
|
5
|
+
return (React.createElement("figure", { className: "ContentImage" },
|
|
6
|
+
(caption || credit) && (React.createElement("figcaption", { className: "ContentImage__caption" },
|
|
7
|
+
caption && React.createElement("span", { className: "ContentImage__text" },
|
|
8
|
+
" ",
|
|
9
|
+
caption,
|
|
10
|
+
" "),
|
|
11
|
+
' ',
|
|
12
|
+
credit && React.createElement("small", { className: "ContentImage__credit" },
|
|
13
|
+
" ",
|
|
14
|
+
credit,
|
|
15
|
+
" "))),
|
|
16
|
+
React.createElement(Image, Object.assign({ className: "ContentImage__image" }, image))));
|
|
17
|
+
};
|
|
18
|
+
export default ContentImage;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
import { FormFieldWrappingProps } from './FormField.js';
|
|
3
|
+
export type DatepickerProps = {
|
|
4
|
+
small?: boolean;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
value?: Date;
|
|
7
|
+
name?: string;
|
|
8
|
+
startDate?: Date;
|
|
9
|
+
endDate?: Date;
|
|
10
|
+
minDate?: Date;
|
|
11
|
+
maxDate?: Date;
|
|
12
|
+
localeCode?: 'is' | 'en' | 'pl';
|
|
13
|
+
dateFormat?: string | Array<string>;
|
|
14
|
+
isStartDate?: boolean;
|
|
15
|
+
isEndDate?: boolean;
|
|
16
|
+
inputRef?: RefObject<HTMLInputElement>;
|
|
17
|
+
onChange: (date?: Date) => void;
|
|
18
|
+
datepickerExtraProps?: Record<string, unknown>;
|
|
19
|
+
/** @deprecated use value instead. (Will be removed in v0.11) */
|
|
20
|
+
initialDate?: Date;
|
|
21
|
+
} & FormFieldWrappingProps;
|
|
22
|
+
export declare const getDateDiff: (date: Date, diff: number) => Date;
|
|
23
|
+
export type DatepickerLocaleProps = {
|
|
24
|
+
nextMonthAriaLabel: string;
|
|
25
|
+
nextMonthButtonLabel: string;
|
|
26
|
+
nextYearAriaLabel: string;
|
|
27
|
+
nextYearButtonLabel: string;
|
|
28
|
+
previousMonthAriaLabel: string;
|
|
29
|
+
previousMonthButtonLabel: string;
|
|
30
|
+
previousYearAriaLabel: string;
|
|
31
|
+
previousYearButtonLabel: string;
|
|
32
|
+
timeInputLabel: string;
|
|
33
|
+
weekAriaLabelPrefix: string;
|
|
34
|
+
weekLabel: string;
|
|
35
|
+
ariaLabelPrefix: string;
|
|
36
|
+
chooseDayAriaLabelPrefix: string;
|
|
37
|
+
disabledDayAriaLabelPrefix: string;
|
|
38
|
+
};
|
|
39
|
+
export declare const Datepicker: (props: DatepickerProps) => JSX.Element;
|
|
40
|
+
export default Datepicker;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
// Documentation: https://reactdatepicker.com/
|
|
3
|
+
import ReactDatePicker, { registerLocale,
|
|
4
|
+
// setDefaultLocale,
|
|
5
|
+
} from 'react-datepicker';
|
|
6
|
+
import { useDomid } from '@hugsmidjan/react/hooks';
|
|
7
|
+
import getBemClass from '@hugsmidjan/react/utils/getBemClass';
|
|
8
|
+
// For more info on localization see: https://stackoverflow.com/questions/54399084/change-locale-in-react-datepicker/58306958#58306958
|
|
9
|
+
import is from 'date-fns/locale/is';
|
|
10
|
+
import pl from 'date-fns/locale/pl';
|
|
11
|
+
import FormField from './FormField.js';
|
|
12
|
+
registerLocale('is', is);
|
|
13
|
+
registerLocale('pl', pl);
|
|
14
|
+
export const getDateDiff = (date, diff) => {
|
|
15
|
+
const newDate = new Date(date);
|
|
16
|
+
newDate.setDate(newDate.getDate() + diff);
|
|
17
|
+
return newDate;
|
|
18
|
+
};
|
|
19
|
+
const i18n = {
|
|
20
|
+
is: {
|
|
21
|
+
nextMonthAriaLabel: 'Næsti mánuður',
|
|
22
|
+
nextMonthButtonLabel: 'Næsti mánuður',
|
|
23
|
+
nextYearAriaLabel: 'Næsta ár',
|
|
24
|
+
nextYearButtonLabel: 'Næsta ár',
|
|
25
|
+
previousMonthAriaLabel: 'Fyrri mánuður',
|
|
26
|
+
previousMonthButtonLabel: 'Fyrri mánuður',
|
|
27
|
+
previousYearAriaLabel: 'Fyrra ár',
|
|
28
|
+
previousYearButtonLabel: 'Fyrra ár',
|
|
29
|
+
timeInputLabel: 'Tími: ',
|
|
30
|
+
weekAriaLabelPrefix: 'Vika: ',
|
|
31
|
+
weekLabel: 'Vika',
|
|
32
|
+
ariaLabelPrefix: 'Mánuður:',
|
|
33
|
+
chooseDayAriaLabelPrefix: 'Veldu:',
|
|
34
|
+
disabledDayAriaLabelPrefix: 'Dagsetning ekki í boði',
|
|
35
|
+
},
|
|
36
|
+
pl: {
|
|
37
|
+
nextMonthAriaLabel: 'Następny miesiącu',
|
|
38
|
+
nextMonthButtonLabel: 'Następny miesiącu',
|
|
39
|
+
nextYearAriaLabel: 'Następny rok',
|
|
40
|
+
nextYearButtonLabel: 'Następny rok',
|
|
41
|
+
previousMonthAriaLabel: 'Poprzedni miesiac',
|
|
42
|
+
previousMonthButtonLabel: 'Poprzedni miesiac',
|
|
43
|
+
previousYearAriaLabel: 'Poprzedni rok',
|
|
44
|
+
previousYearButtonLabel: 'Poprzedni rok',
|
|
45
|
+
timeInputLabel: 'Czas: ',
|
|
46
|
+
weekAriaLabelPrefix: 'Tydzień: ',
|
|
47
|
+
weekLabel: 'Tydzień',
|
|
48
|
+
ariaLabelPrefix: 'Miesiąc:',
|
|
49
|
+
chooseDayAriaLabelPrefix: 'Wybierać:',
|
|
50
|
+
disabledDayAriaLabelPrefix: 'Data niedostępna',
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
export const Datepicker = (props) => {
|
|
54
|
+
const { className, id, label, hideLabel, assistText, disabled, readOnly, invalid, errorMessage, required, reqText, placeholder, small, localeCode = 'is', dateFormat = 'd.M.yyyy', initialDate, value = initialDate, name, startDate, endDate, minDate, maxDate, isStartDate = false, isEndDate = false, onChange, datepickerExtraProps, ssr, inputRef, } = props;
|
|
55
|
+
const domid = useDomid(id);
|
|
56
|
+
const txts = i18n[localeCode] || {};
|
|
57
|
+
const filled = !!value;
|
|
58
|
+
const empty = !filled && !placeholder;
|
|
59
|
+
return (React.createElement(FormField, { className: getBemClass('Datepicker', [], className), ssr: ssr, label: label, small: small, assistText: assistText, hideLabel: hideLabel, invalid: invalid, required: required, reqText: reqText, disabled: disabled, readOnly: readOnly, filled: filled, empty: empty, errorMessage: errorMessage, renderInput: (className, inputProps, addFocusProps) => {
|
|
60
|
+
return (React.createElement("div", Object.assign({ className: className.input, onClick: ({ target, currentTarget }) => { var _a; return target === currentTarget && ((_a = currentTarget.querySelector('input')) === null || _a === void 0 ? void 0 : _a.focus()); }, ref: inputRef &&
|
|
61
|
+
((elm) => {
|
|
62
|
+
inputRef.current =
|
|
63
|
+
(elm === null || elm === void 0 ? void 0 : elm.querySelector('input')) || undefined;
|
|
64
|
+
return elm;
|
|
65
|
+
}) }, addFocusProps()),
|
|
66
|
+
React.createElement(ReactDatePicker, Object.assign({ id: domid, required: inputProps.required, disabled: inputProps.disabled, readOnly: inputProps.readOnly, selected: value, name: name, locale: localeCode, dateFormat: dateFormat, onChange: (date) => {
|
|
67
|
+
onChange(date || undefined);
|
|
68
|
+
const inputElm = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current;
|
|
69
|
+
if (inputElm) {
|
|
70
|
+
inputElm.dispatchEvent(new Event('change', { bubbles: true }));
|
|
71
|
+
}
|
|
72
|
+
}, placeholderText: placeholder,
|
|
73
|
+
// TODO: Implement this
|
|
74
|
+
// selectsRange
|
|
75
|
+
minDate: minDate, maxDate: maxDate, startDate: startDate, endDate: endDate, selectsStart: isStartDate, selectsEnd: isEndDate, formatWeekDay: (weekday) => weekday.charAt(0).toUpperCase(), showYearDropdown: true, scrollableYearDropdown: true, yearDropdownItemNumber: 15, showMonthDropdown: true }, inputProps, txts, datepickerExtraProps))));
|
|
76
|
+
} }));
|
|
77
|
+
};
|
|
78
|
+
export default Datepicker;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { TextCardListProps } from './_abstract/_CardList.js';
|
|
2
|
+
import { SeenProp } from './utils/seenEffect.js';
|
|
3
|
+
export type RelatedLink = {
|
|
4
|
+
href: string;
|
|
5
|
+
label: string;
|
|
6
|
+
blank?: boolean;
|
|
7
|
+
type?: 'link' | 'pdf' | 'text';
|
|
8
|
+
};
|
|
9
|
+
type RelatedProps = {
|
|
10
|
+
relatedTitle?: string;
|
|
11
|
+
relatedLinks?: Array<RelatedLink>;
|
|
12
|
+
};
|
|
13
|
+
export type ExtraLinksCardProps = TextCardListProps['cards'][number];
|
|
14
|
+
export type ExtraLinksProps = TextCardListProps & RelatedProps & {
|
|
15
|
+
className?: string;
|
|
16
|
+
} & SeenProp;
|
|
17
|
+
export declare const ExtraLinks: (props: ExtraLinksProps) => JSX.Element;
|
|
18
|
+
export default ExtraLinks;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { __rest } from "tslib";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import getBemClass from '@hugsmidjan/react/utils/getBemClass';
|
|
4
|
+
import { CardList } from './_abstract/_CardList.js';
|
|
5
|
+
import { Link } from './_abstract/_Link.js';
|
|
6
|
+
import { useSeenEffect } from './utils/seenEffect.js';
|
|
7
|
+
const ExtraLinks__related = (props) => {
|
|
8
|
+
const { relatedTitle, relatedLinks } = props;
|
|
9
|
+
return (React.createElement("div", { className: "ExtraLinks__related" },
|
|
10
|
+
relatedTitle && React.createElement("h3", { className: "ExtraLinks__related__title" }, relatedTitle),
|
|
11
|
+
React.createElement("ul", { className: "ExtraLinks__related__list" }, relatedLinks &&
|
|
12
|
+
relatedLinks.map(({ href, label, blank = false, type }, i) => (React.createElement("li", { className: "ExtraLinks__related__item", key: i },
|
|
13
|
+
React.createElement(Link, { className: getBemClass('ExtraLinks__related__link', type), href: href, target: blank ? '_blank' : '', rel: blank ? 'noreferrer noopener' : '' }, label)))))));
|
|
14
|
+
};
|
|
15
|
+
export const ExtraLinks = (props) => {
|
|
16
|
+
const { relatedTitle, relatedLinks, className, startSeen } = props, cardListProps = __rest(props, ["relatedTitle", "relatedLinks", "className", "startSeen"]);
|
|
17
|
+
const hasRelated = !!(relatedLinks && relatedLinks.length);
|
|
18
|
+
const [ref] = useSeenEffect(startSeen);
|
|
19
|
+
return (React.createElement("div", { className: getBemClass('ExtraLinks', hasRelated && 'related', className), ref: ref },
|
|
20
|
+
React.createElement("div", { className: "ExtraLinks__main" },
|
|
21
|
+
React.createElement(CardList, Object.assign({}, cardListProps, { bemPrefix: "ExtraLinks" }))),
|
|
22
|
+
hasRelated && (React.createElement(ExtraLinks__related, { relatedTitle: relatedTitle, relatedLinks: relatedLinks }))));
|
|
23
|
+
};
|
|
24
|
+
export default ExtraLinks;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Efnistakn } from '@reykjavik/hanna-utils/assets';
|
|
2
|
+
import { SeenProp } from './utils/seenEffect.js';
|
|
3
|
+
export type FeatureListProps = {
|
|
4
|
+
title: string;
|
|
5
|
+
features: Array<{
|
|
6
|
+
icon?: Efnistakn;
|
|
7
|
+
iconUrl?: string;
|
|
8
|
+
name: string;
|
|
9
|
+
}>;
|
|
10
|
+
} & SeenProp;
|
|
11
|
+
export declare const FeatureList: (props: FeatureListProps) => JSX.Element;
|
|
12
|
+
export default FeatureList;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useSeenEffect } from './utils/seenEffect.js';
|
|
3
|
+
import Bling from './Bling.js';
|
|
4
|
+
export const FeatureList = (props) => {
|
|
5
|
+
const { title, features, startSeen } = props;
|
|
6
|
+
const [ref] = useSeenEffect(startSeen);
|
|
7
|
+
const _features = features.length ? features : [{ name: '...' }];
|
|
8
|
+
return (React.createElement(React.Fragment, null,
|
|
9
|
+
React.createElement(Bling, { type: "snake-large", align: "left", vertical: "down-ish" }),
|
|
10
|
+
React.createElement("div", { className: "FeatureList", ref: ref },
|
|
11
|
+
React.createElement("h2", { className: "FeatureList__title" }, title),
|
|
12
|
+
React.createElement("ul", { className: "FeatureList__list" }, _features.map(({ name, icon, iconUrl }, i) => (React.createElement("li", { key: i, className: "FeatureList__feature", style: iconUrl
|
|
13
|
+
? { '--efnistakn': `url("${iconUrl}")` }
|
|
14
|
+
: undefined, "data-efnistakn": !iconUrl ? icon : undefined }, name)))))));
|
|
15
|
+
};
|
|
16
|
+
export default FeatureList;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export type FieldGroupProps = {
|
|
3
|
+
legend: string;
|
|
4
|
+
disabled?: boolean;
|
|
5
|
+
small?: boolean;
|
|
6
|
+
className?: string;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
};
|
|
9
|
+
export declare const FieldGroup: (props: FieldGroupProps) => JSX.Element;
|
|
10
|
+
export default FieldGroup;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import getBemClass from '@hugsmidjan/react/utils/getBemClass';
|
|
3
|
+
export const FieldGroup = (props) => {
|
|
4
|
+
const { legend, children, className, disabled, small } = props;
|
|
5
|
+
return (React.createElement("fieldset", { className: getBemClass('FieldGroup', small && 'small', className), disabled: disabled },
|
|
6
|
+
React.createElement("legend", { className: "FieldGroup__legend" }, legend),
|
|
7
|
+
children));
|
|
8
|
+
};
|
|
9
|
+
export default FieldGroup;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type CustomFile = {
|
|
2
|
+
preview?: string;
|
|
3
|
+
} & File;
|
|
4
|
+
/**
|
|
5
|
+
* Attaches a `preview` prop to file objects that don't already have a `preview` key defined
|
|
6
|
+
*
|
|
7
|
+
* The preview's value is either a data URI (for image-type files) or `undefined`
|
|
8
|
+
*/
|
|
9
|
+
export declare const addPreview: (file: CustomFile) => void;
|
|
10
|
+
/**
|
|
11
|
+
* Revokes `preview` data URIs to avoid memory leaks
|
|
12
|
+
*
|
|
13
|
+
* (See: https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL)
|
|
14
|
+
*/
|
|
15
|
+
export declare const releasePreview: (file: CustomFile) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Small+stupid file size pretty-printer.
|
|
18
|
+
*/
|
|
19
|
+
export declare const formatBytes: (bytes: number, lang?: string, decimals?: number) => string;
|
|
20
|
+
/**
|
|
21
|
+
* Figures out how to handle adding files to a FileInput
|
|
22
|
+
* Which files to retaine, which too delete, and
|
|
23
|
+
* what the updated fileList should look like.
|
|
24
|
+
*
|
|
25
|
+
*
|
|
26
|
+
*/
|
|
27
|
+
export declare const getFileListUpdate: (oldFileList: Array<File>, added: Array<File>, replaceMode: boolean) => {
|
|
28
|
+
fileList: File[];
|
|
29
|
+
diff: {
|
|
30
|
+
added: File[];
|
|
31
|
+
deleted: File[];
|
|
32
|
+
} | {
|
|
33
|
+
added: File[];
|
|
34
|
+
deleted?: undefined;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attaches a `preview` prop to file objects that don't already have a `preview` key defined
|
|
3
|
+
*
|
|
4
|
+
* The preview's value is either a data URI (for image-type files) or `undefined`
|
|
5
|
+
*/
|
|
6
|
+
export const addPreview = (file) => {
|
|
7
|
+
if (!('preview' in file)) {
|
|
8
|
+
file.preview = file.type.includes('image/') ? URL.createObjectURL(file) : undefined;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Revokes `preview` data URIs to avoid memory leaks
|
|
13
|
+
*
|
|
14
|
+
* (See: https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL)
|
|
15
|
+
*/
|
|
16
|
+
export const releasePreview = (file) => {
|
|
17
|
+
file.preview && URL.revokeObjectURL(file.preview);
|
|
18
|
+
delete file.preview;
|
|
19
|
+
};
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
const k = 1024;
|
|
22
|
+
const kThreshold = 970 / k; // Snap up a unit level at this point
|
|
23
|
+
const units = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB' /*, 'EB', 'ZB', 'YB' */];
|
|
24
|
+
const decimalSymbols = { is: ',', en: '.', pl: ',' };
|
|
25
|
+
/**
|
|
26
|
+
* Small+stupid file size pretty-printer.
|
|
27
|
+
*/
|
|
28
|
+
export const formatBytes = (bytes, lang = 'is', decimals = 2) => {
|
|
29
|
+
if (bytes === 0) {
|
|
30
|
+
return '0 Bytes';
|
|
31
|
+
}
|
|
32
|
+
const i = Math.min(Math.floor(Math.log(Math.abs(bytes) / kThreshold) / Math.log(k)), units.length - 1);
|
|
33
|
+
const scaled = bytes / Math.pow(k, i);
|
|
34
|
+
const formatted = (parseFloat(scaled.toFixed(decimals)) + '').replace('.',
|
|
35
|
+
// NOTE: As of 2022-11 Chrome still doesn't support Icelandic
|
|
36
|
+
decimalSymbols[lang] || (1.1).toLocaleString(lang)[1]);
|
|
37
|
+
return `${formatted} ${units[i]}`;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Figures out how to handle adding files to a FileInput
|
|
41
|
+
* Which files to retaine, which too delete, and
|
|
42
|
+
* what the updated fileList should look like.
|
|
43
|
+
*
|
|
44
|
+
*
|
|
45
|
+
*/
|
|
46
|
+
export const getFileListUpdate = (oldFileList, added,
|
|
47
|
+
/**
|
|
48
|
+
* `replaceMode: true` is the default "single-file" input behavior.
|
|
49
|
+
*
|
|
50
|
+
* Pass `false` to this argument when the "multiple" prop is true.
|
|
51
|
+
*/
|
|
52
|
+
replaceMode) => {
|
|
53
|
+
const deleted = replaceMode ? oldFileList : [];
|
|
54
|
+
const retained = [];
|
|
55
|
+
if (!replaceMode) {
|
|
56
|
+
oldFileList.forEach((oldFile) => {
|
|
57
|
+
if (added.find(({ name }) => name === oldFile.name)) {
|
|
58
|
+
deleted.push(oldFile);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
retained.push(oldFile);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
fileList: retained.concat(added),
|
|
67
|
+
diff: deleted.length ? { added, deleted } : { added },
|
|
68
|
+
};
|
|
69
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { formatBytes } from './_FileInput.utils';
|
|
2
|
+
import { CustomFile } from './_FileInput.utils';
|
|
3
|
+
export type FileListProps = {
|
|
4
|
+
files: Array<CustomFile>;
|
|
5
|
+
showFileSize?: boolean;
|
|
6
|
+
showImagePreviews?: boolean;
|
|
7
|
+
removeFileText: string;
|
|
8
|
+
removeFile: (file: File | string) => void;
|
|
9
|
+
formatBytes: typeof formatBytes;
|
|
10
|
+
};
|
|
11
|
+
export declare const DefaultFileList: (props: FileListProps) => JSX.Element | null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export const DefaultFileList = (props) => {
|
|
3
|
+
const { files, showFileSize, showImagePreviews, removeFileText, removeFile, formatBytes, } = props;
|
|
4
|
+
if (!files.length) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
return (React.createElement("ul", { className: "FileInput__filelist" }, files.map((file) => (React.createElement("li", { key: file.name, className: "FileInput__file" },
|
|
8
|
+
React.createElement("button", { className: "FileInput__file-remove", type: "button", onClick: () => removeFile(file), "aria-label": `${removeFileText} ${file.name}` }, removeFileText),
|
|
9
|
+
React.createElement("span", { className: "FileInput__fileinfo" },
|
|
10
|
+
showImagePreviews && file.preview && (React.createElement(React.Fragment, null,
|
|
11
|
+
React.createElement("span", { className: "FileInput__preview" },
|
|
12
|
+
React.createElement("img", { src: file.preview, alt: "" })),
|
|
13
|
+
' ')),
|
|
14
|
+
React.createElement("span", { className: "FileInput__filename" }, file.name),
|
|
15
|
+
showFileSize && (React.createElement("small", { className: "FileInput__filesize" },
|
|
16
|
+
" - (",
|
|
17
|
+
formatBytes(file.size),
|
|
18
|
+
")"))))))));
|
|
19
|
+
};
|