@intlayer/design-system 8.11.3 → 8.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/api/hooks/project.mjs +110 -1
- package/dist/esm/api/hooks/project.mjs.map +1 -1
- package/dist/esm/api/hooks/utils.mjs +1 -1
- package/dist/esm/api/index.mjs +2 -2
- package/dist/esm/api/useAuth/useOAuth2.mjs +2 -2
- package/dist/esm/api/useAuth/useSession.mjs +1 -1
- package/dist/esm/api/useIntlayerAPI.mjs +1 -1
- package/dist/esm/components/Accordion/Accordion.mjs.map +1 -1
- package/dist/esm/components/Badge/index.mjs +18 -55
- package/dist/esm/components/Badge/index.mjs.map +1 -1
- package/dist/esm/components/Breadcrumb/index.mjs +12 -12
- package/dist/esm/components/Breadcrumb/index.mjs.map +1 -1
- package/dist/esm/components/Browser/Browser.mjs +1 -1
- package/dist/esm/components/Browser/Browser.mjs.map +1 -1
- package/dist/esm/components/Button/Button.mjs +60 -117
- package/dist/esm/components/Button/Button.mjs.map +1 -1
- package/dist/esm/components/Button/index.mjs +2 -2
- package/dist/esm/components/Carousel/index.mjs +3 -3
- package/dist/esm/components/Carousel/index.mjs.map +1 -1
- package/dist/esm/components/Container/index.mjs +1 -71
- package/dist/esm/components/Container/index.mjs.map +1 -1
- package/dist/esm/components/ContentEditor/ContentEditor.mjs +0 -1
- package/dist/esm/components/ContentEditor/ContentEditor.mjs.map +1 -1
- package/dist/esm/components/ContentEditor/ContentEditorInput.mjs +2 -2
- package/dist/esm/components/ContentEditor/ContentEditorInput.mjs.map +1 -1
- package/dist/esm/components/ContentEditor/ContentEditorTextArea.mjs +2 -2
- package/dist/esm/components/ContentEditor/ContentEditorTextArea.mjs.map +1 -1
- package/dist/esm/components/ContentEditor/index.mjs +1 -1
- package/dist/esm/components/CopyButton/index.mjs +4 -4
- package/dist/esm/components/CopyButton/index.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/DictionaryEditor.mjs +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/BooleanWrapper.mjs +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/FileWrapper.mjs +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/NumberWrapper.mjs +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/StringWrapper.mjs +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/index.mjs +1 -1
- package/dist/esm/components/DictionaryFieldEditor/ContentEditor.mjs +1 -1
- package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/TextEditor.mjs +6 -7
- package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/TextEditor.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryCreationForm/DictionaryCreationForm.mjs +0 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryCreationForm/DictionaryCreationForm.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/DictionaryDetailsForm.mjs +3 -4
- package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/DictionaryDetailsForm.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryFieldEditor.mjs +3 -3
- package/dist/esm/components/DictionaryFieldEditor/DictionaryFieldEditor.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/JSONEditor.mjs +1 -1
- package/dist/esm/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs +3 -3
- package/dist/esm/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs +3 -4
- package/dist/esm/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/StructureEditor.mjs +1 -1
- package/dist/esm/components/DictionaryFieldEditor/StructureView/StructureView.mjs +2 -3
- package/dist/esm/components/DictionaryFieldEditor/StructureView/StructureView.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/VersionSwitcherDropDown/VersionSwitcher.mjs +1 -1
- package/dist/esm/components/DictionaryFieldEditor/VersionSwitcherDropDown/VersionSwitcher.mjs.map +1 -1
- package/dist/esm/components/DropDown/index.mjs +3 -23
- package/dist/esm/components/DropDown/index.mjs.map +1 -1
- package/dist/esm/components/EditableField/EditableFieldLayout.mjs +1 -1
- package/dist/esm/components/EditableField/EditableFieldLayout.mjs.map +1 -1
- package/dist/esm/components/EditableField/EditableFieldTextArea.mjs +1 -1
- package/dist/esm/components/Form/elements/OTPElement.mjs +1 -1
- package/dist/esm/components/IDE/CopyCode.mjs +0 -1
- package/dist/esm/components/IDE/CopyCode.mjs.map +1 -1
- package/dist/esm/components/Input/Checkbox.mjs +2 -22
- package/dist/esm/components/Input/Checkbox.mjs.map +1 -1
- package/dist/esm/components/Input/Input.mjs +1 -11
- package/dist/esm/components/Input/Input.mjs.map +1 -1
- package/dist/esm/components/Input/Radio.mjs +82 -0
- package/dist/esm/components/Input/Radio.mjs.map +1 -0
- package/dist/esm/components/Input/index.mjs +4 -3
- package/dist/esm/components/KeyboardScreenAdapter/index.mjs +1 -1
- package/dist/esm/components/KeyboardShortcut/KeyboardShortcut.mjs +2 -53
- package/dist/esm/components/KeyboardShortcut/KeyboardShortcut.mjs.map +1 -1
- package/dist/esm/components/KeyboardShortcut/index.mjs +2 -2
- package/dist/esm/components/Link/Link.mjs +33 -85
- package/dist/esm/components/Link/Link.mjs.map +1 -1
- package/dist/esm/components/Link/index.mjs +2 -2
- package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.mjs +3 -3
- package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.mjs.map +1 -1
- package/dist/esm/components/LocaleSwitcherDropDown/LocaleSwitcher.mjs +1 -1
- package/dist/esm/components/LocaleSwitcherDropDown/LocaleSwitcher.mjs.map +1 -1
- package/dist/esm/components/MarkDownRender/MarkDownIframe.mjs +3 -3
- package/dist/esm/components/MarkDownRender/MarkDownIframe.mjs.map +1 -1
- package/dist/esm/components/Modal/Modal.mjs +5 -16
- package/dist/esm/components/Modal/Modal.mjs.map +1 -1
- package/dist/esm/components/Modal/index.mjs +2 -2
- package/dist/esm/components/Navbar/DesktopNavbar.mjs +1 -1
- package/dist/esm/components/Navbar/DesktopNavbar.mjs.map +1 -1
- package/dist/esm/components/Navbar/MobileNavbar.mjs +2 -2
- package/dist/esm/components/Pagination/Pagination.mjs +3 -15
- package/dist/esm/components/Pagination/Pagination.mjs.map +1 -1
- package/dist/esm/components/Pagination/index.mjs +2 -2
- package/dist/esm/components/Pattern/DotPattern.mjs +1 -1
- package/dist/esm/components/Pattern/DotPattern.mjs.map +1 -1
- package/dist/esm/components/Popover/dynamic.mjs +4 -4
- package/dist/esm/components/Popover/dynamic.mjs.map +1 -1
- package/dist/esm/components/Popover/index.mjs +2 -2
- package/dist/esm/components/Popover/static.mjs +6 -28
- package/dist/esm/components/Popover/static.mjs.map +1 -1
- package/dist/esm/components/RightDrawer/RightDrawer.mjs +4 -4
- package/dist/esm/components/RightDrawer/RightDrawer.mjs.map +1 -1
- package/dist/esm/components/Select/Multiselect.mjs +4 -4
- package/dist/esm/components/Select/Multiselect.mjs.map +1 -1
- package/dist/esm/components/Select/Select.mjs +3 -15
- package/dist/esm/components/Select/Select.mjs.map +1 -1
- package/dist/esm/components/Select/index.mjs +2 -2
- package/dist/esm/components/Steps/index.mjs +37 -27
- package/dist/esm/components/Steps/index.mjs.map +1 -1
- package/dist/esm/components/Steps/steps.content.mjs +55 -0
- package/dist/esm/components/Steps/steps.content.mjs.map +1 -0
- package/dist/esm/components/SwitchSelector/SwitchSelector.mjs +19 -35
- package/dist/esm/components/SwitchSelector/SwitchSelector.mjs.map +1 -1
- package/dist/esm/components/SwitchSelector/VerticalSwitchSelector.mjs +20 -20
- package/dist/esm/components/SwitchSelector/VerticalSwitchSelector.mjs.map +1 -1
- package/dist/esm/components/SwitchSelector/index.mjs +2 -2
- package/dist/esm/components/Tab/Tab.mjs +3 -3
- package/dist/esm/components/Tab/Tab.mjs.map +1 -1
- package/dist/esm/components/TabSelector/TabSelector.mjs +2 -12
- package/dist/esm/components/TabSelector/TabSelector.mjs.map +1 -1
- package/dist/esm/components/TabSelector/index.mjs +2 -2
- package/dist/esm/components/Table/ExpandButton.mjs +0 -1
- package/dist/esm/components/Table/ExpandButton.mjs.map +1 -1
- package/dist/esm/components/Table/SmartTable.mjs +1 -1
- package/dist/esm/components/Table/SmartTable.mjs.map +1 -1
- package/dist/esm/components/Tag/index.mjs +51 -205
- package/dist/esm/components/Tag/index.mjs.map +1 -1
- package/dist/esm/components/TechLogo/TechLogo.mjs +36 -37
- package/dist/esm/components/TechLogo/TechLogo.mjs.map +1 -1
- package/dist/esm/components/TechLogo/index.mjs +1 -2
- package/dist/esm/components/TechLogo/types.mjs +0 -44
- package/dist/esm/components/TextArea/AutoSizeTextArea.mjs +1 -1
- package/dist/esm/components/TextArea/AutoSizeTextArea.mjs.map +1 -1
- package/dist/esm/components/TextArea/ContentEditableTextArea.mjs.map +1 -1
- package/dist/esm/components/TextArea/TextArea.mjs +2 -2
- package/dist/esm/components/TextArea/TextArea.mjs.map +1 -1
- package/dist/esm/components/TextArea/index.mjs +2 -2
- package/dist/esm/components/ThemeSwitcherDropDown/DesktopThemeSwitcher.mjs +1 -2
- package/dist/esm/components/ThemeSwitcherDropDown/DesktopThemeSwitcher.mjs.map +1 -1
- package/dist/esm/components/ThemeSwitcherDropDown/MobileThemeSwitcher.mjs +0 -1
- package/dist/esm/components/ThemeSwitcherDropDown/MobileThemeSwitcher.mjs.map +1 -1
- package/dist/esm/components/ThemeSwitcherDropDown/index.mjs +1 -2
- package/dist/esm/components/ThemeSwitcherDropDown/types.mjs +0 -11
- package/dist/esm/components/index.mjs +24 -23
- package/dist/esm/hooks/index.mjs +8 -8
- package/dist/esm/providers/ReactQueryProvider.mjs +2 -2
- package/dist/types/api/hooks/project.d.ts +8 -1
- package/dist/types/api/hooks/project.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +2 -2
- package/dist/types/api/useIntlayerAPI.d.ts +9 -2
- package/dist/types/api/useIntlayerAPI.d.ts.map +1 -1
- package/dist/types/components/Accordion/Accordion.d.ts.map +1 -1
- package/dist/types/components/Badge/index.d.ts +6 -25
- package/dist/types/components/Badge/index.d.ts.map +1 -1
- package/dist/types/components/Breadcrumb/index.d.ts +1 -1
- package/dist/types/components/Browser/Browser.d.ts +1 -1
- package/dist/types/components/Browser/Browser.d.ts.map +1 -1
- package/dist/types/components/Button/Button.d.ts +9 -45
- package/dist/types/components/Button/Button.d.ts.map +1 -1
- package/dist/types/components/Carousel/index.d.ts.map +1 -1
- package/dist/types/components/CollapsibleTable/CollapsibleTable.d.ts +2 -2
- package/dist/types/components/Command/index.d.ts +2 -2
- package/dist/types/components/Command/index.d.ts.map +1 -1
- package/dist/types/components/Container/index.d.ts +11 -60
- package/dist/types/components/Container/index.d.ts.map +1 -1
- package/dist/types/components/ContentEditor/ContentEditor.d.ts.map +1 -1
- package/dist/types/components/CopyButton/index.d.ts +3 -3
- package/dist/types/components/CopyButton/index.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/ContentEditorView/SafeHtmlRenderer.d.ts +1 -1
- package/dist/types/components/DictionaryFieldEditor/ContentEditorView/SafeHtmlRenderer.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/ContentEditorView/TextEditor.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/DictionaryCreationForm/DictionaryCreationForm.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/SaveForm/SaveForm.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/StructureView/StructureView.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/VersionSwitcherDropDown/VersionSwitcher.d.ts.map +1 -1
- package/dist/types/components/DropDown/index.d.ts +4 -14
- package/dist/types/components/DropDown/index.d.ts.map +1 -1
- package/dist/types/components/Form/FormBase.d.ts +1 -1
- package/dist/types/components/Form/FormBase.d.ts.map +1 -1
- package/dist/types/components/Form/FormField.d.ts +1 -1
- package/dist/types/components/Form/FormField.d.ts.map +1 -1
- package/dist/types/components/Form/elements/EditableFieldInputElement.d.ts +1 -1
- package/dist/types/components/Form/elements/EditableFieldInputElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/EditableFieldTextAreaElement.d.ts +1 -1
- package/dist/types/components/Form/elements/EditableFieldTextAreaElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/FormElement.d.ts +1 -1
- package/dist/types/components/Form/elements/FormElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/MultiselectElement.d.ts +1 -1
- package/dist/types/components/Form/elements/MultiselectElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/OTPElement.d.ts +1 -1
- package/dist/types/components/Form/elements/OTPElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/SelectElement.d.ts +1 -1
- package/dist/types/components/Form/elements/SelectElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/SwitchSelectorElement.d.ts +1 -1
- package/dist/types/components/Form/elements/SwitchSelectorElement.d.ts.map +1 -1
- package/dist/types/components/IDE/CodeBlockHighlight.d.ts +1 -1
- package/dist/types/components/IDE/CodeBlockHighlight.d.ts.map +1 -1
- package/dist/types/components/Input/Checkbox.d.ts +4 -20
- package/dist/types/components/Input/Checkbox.d.ts.map +1 -1
- package/dist/types/components/Input/Input.d.ts +3 -9
- package/dist/types/components/Input/Input.d.ts.map +1 -1
- package/dist/types/components/Input/OTPInput.d.ts +1 -1
- package/dist/types/components/Input/OTPInput.d.ts.map +1 -1
- package/dist/types/components/Input/Radio.d.ts +25 -0
- package/dist/types/components/Input/Radio.d.ts.map +1 -0
- package/dist/types/components/Input/SearchInput.d.ts +1 -1
- package/dist/types/components/Input/SearchInput.d.ts.map +1 -1
- package/dist/types/components/Input/index.d.ts +2 -1
- package/dist/types/components/KeyboardShortcut/KeyboardShortcut.d.ts +1 -47
- package/dist/types/components/KeyboardShortcut/KeyboardShortcut.d.ts.map +1 -1
- package/dist/types/components/Link/Link.d.ts +8 -47
- package/dist/types/components/Link/Link.d.ts.map +1 -1
- package/dist/types/components/Loader/spinner.d.ts +1 -1
- package/dist/types/components/Loader/spinner.d.ts.map +1 -1
- package/dist/types/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.d.ts.map +1 -1
- package/dist/types/components/MarkDownRender/MarkDownRender.d.ts +44 -44
- package/dist/types/components/MarkDownRender/MarkDownRender.d.ts.map +1 -1
- package/dist/types/components/MaxWidthSmoother/index.d.ts +1 -1
- package/dist/types/components/MaxWidthSmoother/index.d.ts.map +1 -1
- package/dist/types/components/Modal/Modal.d.ts +2 -8
- package/dist/types/components/Modal/Modal.d.ts.map +1 -1
- package/dist/types/components/Navbar/Burger.d.ts +1 -1
- package/dist/types/components/Navbar/Burger.d.ts.map +1 -1
- package/dist/types/components/Navbar/DesktopNavbar.d.ts +1 -1
- package/dist/types/components/Navbar/DesktopNavbar.d.ts.map +1 -1
- package/dist/types/components/Navbar/MobileNavbar.d.ts +1 -1
- package/dist/types/components/Navbar/MobileNavbar.d.ts.map +1 -1
- package/dist/types/components/Navbar/index.d.ts +1 -1
- package/dist/types/components/Navbar/index.d.ts.map +1 -1
- package/dist/types/components/Pagination/Pagination.d.ts +2 -10
- package/dist/types/components/Pagination/Pagination.d.ts.map +1 -1
- package/dist/types/components/Popover/dynamic.d.ts.map +1 -1
- package/dist/types/components/Popover/static.d.ts +5 -17
- package/dist/types/components/Popover/static.d.ts.map +1 -1
- package/dist/types/components/Select/Multiselect.d.ts +3 -3
- package/dist/types/components/Select/Select.d.ts +3 -8
- package/dist/types/components/Select/Select.d.ts.map +1 -1
- package/dist/types/components/SocialNetworks/index.d.ts +1 -1
- package/dist/types/components/Steps/index.d.ts +4 -4
- package/dist/types/components/Steps/index.d.ts.map +1 -1
- package/dist/types/components/Steps/steps.content.d.ts +52 -0
- package/dist/types/components/Steps/steps.content.d.ts.map +1 -0
- package/dist/types/components/SwitchSelector/SwitchSelector.d.ts +4 -16
- package/dist/types/components/SwitchSelector/SwitchSelector.d.ts.map +1 -1
- package/dist/types/components/SwitchSelector/VerticalSwitchSelector.d.ts +2 -2
- package/dist/types/components/SwitchSelector/VerticalSwitchSelector.d.ts.map +1 -1
- package/dist/types/components/Tab/Tab.d.ts +2 -2
- package/dist/types/components/Tab/Tab.d.ts.map +1 -1
- package/dist/types/components/TabSelector/TabSelector.d.ts +2 -10
- package/dist/types/components/TabSelector/TabSelector.d.ts.map +1 -1
- package/dist/types/components/Table/TableElements.d.ts +4 -4
- package/dist/types/components/Table/TableElements.d.ts.map +1 -1
- package/dist/types/components/Tag/index.d.ts +44 -83
- package/dist/types/components/Tag/index.d.ts.map +1 -1
- package/dist/types/components/TechLogo/TechLogo.d.ts.map +1 -1
- package/dist/types/components/TechLogo/index.d.ts +1 -1
- package/dist/types/components/TechLogo/logos/Lit.d.ts +1 -1
- package/dist/types/components/TechLogo/logos/Lit.d.ts.map +1 -1
- package/dist/types/components/TechLogo/logos/Vanilla.d.ts +1 -1
- package/dist/types/components/TechLogo/logos/Vanilla.d.ts.map +1 -1
- package/dist/types/components/TechLogo/types.d.ts +1 -38
- package/dist/types/components/TechLogo/types.d.ts.map +1 -1
- package/dist/types/components/TextArea/AutoSizeTextArea.d.ts +1 -1
- package/dist/types/components/TextArea/ContentEditableTextArea.d.ts +3 -3
- package/dist/types/components/TextArea/TextArea.d.ts +6 -6
- package/dist/types/components/TextArea/TextArea.d.ts.map +1 -1
- package/dist/types/components/ThemeSwitcherDropDown/types.d.ts +1 -5
- package/dist/types/components/ThemeSwitcherDropDown/types.d.ts.map +1 -1
- package/dist/types/components/Toaster/Toast.d.ts +1 -1
- package/dist/types/components/Toaster/Toaster.d.ts +1 -1
- package/dist/types/components/Toaster/Toaster.d.ts.map +1 -1
- package/dist/types/components/index.d.ts +5 -2
- package/package.json +23 -24
- package/dist/esm/components/TechLogo/types.mjs.map +0 -1
- package/dist/esm/components/ThemeSwitcherDropDown/types.mjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { cn } from "../../utils/cn.mjs";
|
|
4
3
|
import { useKeyboardDetector } from "../../hooks/useKeyboardDetector.mjs";
|
|
4
|
+
import { cn } from "../../utils/cn.mjs";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
6
|
|
|
7
7
|
//#region src/components/KeyboardScreenAdapter/index.tsx
|
|
@@ -1,63 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { cn } from "../../utils/cn.mjs";
|
|
4
3
|
import { useDevice } from "../../hooks/useDevice.mjs";
|
|
4
|
+
import { cn } from "../../utils/cn.mjs";
|
|
5
5
|
import { useEffect, useState } from "react";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
|
|
8
8
|
//#region src/components/KeyboardShortcut/KeyboardShortcut.tsx
|
|
9
9
|
/**
|
|
10
|
-
* Enum for available keyboard keys
|
|
11
|
-
*/
|
|
12
|
-
let KeyList = /* @__PURE__ */ function(KeyList) {
|
|
13
|
-
KeyList["⌘"] = "⌘";
|
|
14
|
-
KeyList["Ctrl"] = "Ctrl";
|
|
15
|
-
KeyList["Alt"] = "Alt";
|
|
16
|
-
KeyList["⌥"] = "⌥";
|
|
17
|
-
KeyList["Shift"] = "Shift";
|
|
18
|
-
KeyList["Meta"] = "Meta";
|
|
19
|
-
KeyList["F"] = "F";
|
|
20
|
-
KeyList["K"] = "K";
|
|
21
|
-
KeyList["L"] = "L";
|
|
22
|
-
KeyList["P"] = "P";
|
|
23
|
-
KeyList["S"] = "S";
|
|
24
|
-
KeyList["A"] = "A";
|
|
25
|
-
KeyList["B"] = "B";
|
|
26
|
-
KeyList["C"] = "C";
|
|
27
|
-
KeyList["D"] = "D";
|
|
28
|
-
KeyList["E"] = "E";
|
|
29
|
-
KeyList["G"] = "G";
|
|
30
|
-
KeyList["H"] = "H";
|
|
31
|
-
KeyList["I"] = "I";
|
|
32
|
-
KeyList["J"] = "J";
|
|
33
|
-
KeyList["M"] = "M";
|
|
34
|
-
KeyList["N"] = "N";
|
|
35
|
-
KeyList["O"] = "O";
|
|
36
|
-
KeyList["Q"] = "Q";
|
|
37
|
-
KeyList["R"] = "R";
|
|
38
|
-
KeyList["T"] = "T";
|
|
39
|
-
KeyList["U"] = "U";
|
|
40
|
-
KeyList["V"] = "V";
|
|
41
|
-
KeyList["W"] = "W";
|
|
42
|
-
KeyList["X"] = "X";
|
|
43
|
-
KeyList["Y"] = "Y";
|
|
44
|
-
KeyList["Z"] = "Z";
|
|
45
|
-
KeyList["Enter"] = "Enter";
|
|
46
|
-
KeyList["Escape"] = "Escape";
|
|
47
|
-
KeyList["Backspace"] = "Backspace";
|
|
48
|
-
KeyList["Tab"] = "Tab";
|
|
49
|
-
KeyList["Space"] = "Space";
|
|
50
|
-
KeyList["ArrowUp"] = "ArrowUp";
|
|
51
|
-
KeyList["ArrowDown"] = "ArrowDown";
|
|
52
|
-
KeyList["ArrowLeft"] = "ArrowLeft";
|
|
53
|
-
KeyList["ArrowRight"] = "ArrowRight";
|
|
54
|
-
KeyList["↑"] = "↑";
|
|
55
|
-
KeyList["↓"] = "↓";
|
|
56
|
-
KeyList["←"] = "←";
|
|
57
|
-
KeyList["→"] = "→";
|
|
58
|
-
return KeyList;
|
|
59
|
-
}({});
|
|
60
|
-
/**
|
|
61
10
|
* Parse keyboard shortcut string into individual keys
|
|
62
11
|
*/
|
|
63
12
|
const parseShortcut = (shortcut) => {
|
|
@@ -227,5 +176,5 @@ const KeyboardShortcut = ({ shortcut, onTriggered, display = true, disabled = fa
|
|
|
227
176
|
};
|
|
228
177
|
|
|
229
178
|
//#endregion
|
|
230
|
-
export {
|
|
179
|
+
export { KeyboardShortcut };
|
|
231
180
|
//# sourceMappingURL=KeyboardShortcut.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeyboardShortcut.mjs","names":[],"sources":["../../../../src/components/KeyboardShortcut/KeyboardShortcut.tsx"],"sourcesContent":["'use client';\n\nimport { useDevice } from '@hooks/useDevice';\nimport { cn } from '@utils/cn';\nimport { type FC, useEffect, useState } from 'react';\n\n/**\n * Enum for available keyboard keys\n */\nexport enum KeyList {\n '⌘' = '⌘',\n Ctrl = 'Ctrl',\n Alt = 'Alt',\n '⌥' = '⌥',\n Shift = 'Shift',\n Meta = 'Meta',\n F = 'F',\n K = 'K',\n L = 'L',\n P = 'P',\n S = 'S',\n A = 'A',\n B = 'B',\n C = 'C',\n D = 'D',\n E = 'E',\n G = 'G',\n H = 'H',\n I = 'I',\n J = 'J',\n M = 'M',\n N = 'N',\n O = 'O',\n Q = 'Q',\n R = 'R',\n T = 'T',\n U = 'U',\n V = 'V',\n W = 'W',\n X = 'X',\n Y = 'Y',\n Z = 'Z',\n Enter = 'Enter',\n Escape = 'Escape',\n Backspace = 'Backspace',\n Tab = 'Tab',\n Space = 'Space',\n ArrowUp = 'ArrowUp',\n ArrowDown = 'ArrowDown',\n ArrowLeft = 'ArrowLeft',\n ArrowRight = 'ArrowRight',\n '↑' = '↑',\n '↓' = '↓',\n '←' = '←',\n '→' = '→',\n}\n\n/**\n * Type-safe keyboard shortcut combinations\n * Note: Using string type to avoid union type complexity issues\n * Expected format: \"Key + Key\" (e.g., \"⌘ + F\", \"Ctrl + Shift + K\")\n */\nexport type KeyboardShortcutType = string;\n\nexport type KeyboardShortcutProps = {\n /** The keyboard shortcut combination (e.g., \"⌘ + F\" or \"Ctrl + K\") */\n shortcut: KeyboardShortcutType;\n /** Callback function triggered when the shortcut is pressed */\n onTriggered?: () => void;\n /** Whether to display the shortcut visually (default: true) */\n display?: boolean;\n /** Whether to disable the shortcut trigger (default: false) */\n disabled?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Size of the keyboard shortcut display */\n size?: 'sm' | 'md' | 'lg';\n};\n\n/**\n * Parse keyboard shortcut string into individual keys\n */\nconst parseShortcut = (shortcut: string): string[] => {\n return shortcut.split(' + ').map((key) => key.trim());\n};\n\n/**\n * Normalize key name for event comparison\n */\nconst normalizeKey = (key: string): string => {\n const keyMap: Record<string, string> = {\n '⌘': 'Meta',\n Ctrl: 'Control',\n Control: 'Control',\n Alt: 'Alt',\n '⌥': 'Alt',\n Shift: 'Shift',\n Meta: 'Meta',\n '↑': 'ArrowUp',\n '↓': 'ArrowDown',\n '←': 'ArrowLeft',\n '→': 'ArrowRight',\n ArrowUp: 'ArrowUp',\n ArrowDown: 'ArrowDown',\n ArrowLeft: 'ArrowLeft',\n ArrowRight: 'ArrowRight',\n };\n\n return keyMap[key] || key;\n};\n\n/**\n * Check if the keyboard event matches the shortcut\n */\nconst matchesShortcut = (event: KeyboardEvent, keys: string[]): boolean => {\n const normalizedKeys = keys.map(normalizeKey);\n const hasModifiers = {\n Meta: normalizedKeys.includes('Meta'),\n Control: normalizedKeys.includes('Control'),\n Alt: normalizedKeys.includes('Alt'),\n Shift: normalizedKeys.includes('Shift'),\n };\n\n // Check if all required modifiers are pressed\n if (\n hasModifiers.Meta !== event.metaKey ||\n hasModifiers.Control !== event.ctrlKey ||\n hasModifiers.Alt !== event.altKey ||\n hasModifiers.Shift !== event.shiftKey\n ) {\n return false;\n }\n\n // Find the non-modifier key\n const nonModifierKey = keys.find(\n (key) =>\n !['⌘', 'Ctrl', 'Control', 'Alt', '⌥', 'Shift', 'Meta'].includes(\n normalizeKey(key)\n )\n );\n\n if (!nonModifierKey) return false;\n\n // Normalize the key for comparison\n const normalizedNonModifierKey = normalizeKey(nonModifierKey);\n\n // Compare the main key\n // For arrow keys, compare directly with event.key\n if (normalizedNonModifierKey.startsWith('Arrow')) {\n return event.key === normalizedNonModifierKey;\n }\n\n // For other keys, compare case-insensitive\n return event.key.toLowerCase() === normalizedNonModifierKey.toLowerCase();\n};\n\n/**\n * Get display key symbol for better visual representation\n */\nconst getDisplayKey = (key: string): string => {\n const displayMap: Record<string, string> = {\n ArrowUp: '↑',\n ArrowDown: '↓',\n ArrowLeft: '←',\n ArrowRight: '→',\n };\n\n return displayMap[key] || key;\n};\n\n/**\n * Get display shortcut based on OS (Mac uses ⌘ and ⌥, others use Ctrl and Alt)\n */\nconst getDisplayShortcut = (shortcut: string, isMac: boolean): string => {\n let result = shortcut;\n\n if (isMac) {\n result = result.replace(/Ctrl/g, '⌘');\n result = result.replace(/Alt/g, '⌥');\n } else {\n result = result.replace(/⌘/g, 'Ctrl');\n result = result.replace(/⌥/g, 'Alt');\n }\n\n // Replace arrow key names with symbols\n result = result.replace(/ArrowUp/g, '↑');\n result = result.replace(/ArrowDown/g, '↓');\n result = result.replace(/ArrowLeft/g, '←');\n result = result.replace(/ArrowRight/g, '→');\n\n return result;\n};\n\n/**\n * KeyboardShortcut Component\n *\n * A reusable component that displays keyboard shortcuts and listens for key combinations.\n * Automatically adapts to Mac (⌘, ⌥) and Windows/Linux (Ctrl, Alt) conventions.\n *\n * @example\n * ```tsx\n * <KeyboardShortcut\n * shortcut=\"⌘ + F\"\n * onTriggered={() => setShowSearch(true)}\n * />\n * ```\n */\nexport const KeyboardShortcut: FC<KeyboardShortcutProps> = ({\n shortcut,\n onTriggered,\n display = true,\n disabled = false,\n className,\n size = 'md',\n}) => {\n const { isMac } = useDevice();\n const displayShortcut = getDisplayShortcut(shortcut, isMac ?? false);\n const keys = parseShortcut(displayShortcut);\n const [pressedKeys, setPressedKeys] = useState<Set<string>>(new Set());\n\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n // 1. Identify input fields\n const target = event.target as HTMLElement;\n const isInputField =\n target.tagName === 'INPUT' ||\n target.tagName === 'TEXTAREA' ||\n target.isContentEditable;\n\n // ... (Your existing key visualization logic here) ...\n // Note: Copied your key tracking logic for context\n const currentKey = event.key;\n const normalizedEventKeys = new Set<string>();\n if (event.metaKey) normalizedEventKeys.add('⌘');\n if (event.ctrlKey) normalizedEventKeys.add('Ctrl');\n if (event.altKey) normalizedEventKeys.add(isMac ? '⌥' : 'Alt');\n if (event.shiftKey) normalizedEventKeys.add('Shift');\n\n if (currentKey.startsWith('Arrow')) {\n normalizedEventKeys.add(currentKey);\n normalizedEventKeys.add(getDisplayKey(currentKey));\n } else {\n normalizedEventKeys.add(currentKey.toUpperCase());\n }\n setPressedKeys(normalizedEventKeys);\n\n // 2. Trigger callback if shortcut matches\n if (!disabled && onTriggered && matchesShortcut(event, keys)) {\n // FIX: Check if the required shortcut is \"Escape\"\n const isEscapeShortcut = keys.includes('Escape');\n\n // Only block if it is an input field AND the shortcut is NOT Escape\n if (isInputField && !isEscapeShortcut) {\n return;\n }\n\n event.preventDefault();\n onTriggered();\n }\n };\n\n const handleKeyUp = () => {\n setPressedKeys(new Set());\n };\n\n window.addEventListener('keydown', handleKeyDown);\n window.addEventListener('keyup', handleKeyUp);\n window.addEventListener('blur', handleKeyUp);\n\n return () => {\n window.removeEventListener('keydown', handleKeyDown);\n window.removeEventListener('keyup', handleKeyUp);\n window.removeEventListener('blur', handleKeyUp);\n };\n }, [keys, onTriggered, isMac, disabled]);\n if (!display) return null;\n\n /**\n * Check if a key is currently pressed\n */\n const isKeyPressed = (key: string): boolean => {\n const upperKey = key.toUpperCase();\n const normalizedKey = normalizeKey(key);\n\n return (\n pressedKeys.has(key) ||\n pressedKeys.has(upperKey) ||\n pressedKeys.has(normalizedKey) ||\n // Check for modifier key matches\n (key === '⌘' && pressedKeys.has('Meta')) ||\n (key === 'Ctrl' && pressedKeys.has('Control')) ||\n (key === '⌥' && pressedKeys.has('Alt')) ||\n (key === 'Alt' && pressedKeys.has('Alt')) ||\n // Check for arrow key symbols\n (key === '←' && pressedKeys.has('ArrowLeft')) ||\n (key === '→' && pressedKeys.has('ArrowRight')) ||\n (key === '↑' && pressedKeys.has('ArrowUp')) ||\n (key === '↓' && pressedKeys.has('ArrowDown'))\n );\n };\n\n return (\n <kbd\n className={cn(\n 'inline-flex items-center justify-center gap-0.5 p-0.5',\n 'rounded-lg [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-xl',\n 'font-medium font-sans',\n 'border-1 border-neutral/20 text-neutral',\n size === 'sm' && 'text-xs',\n size === 'md' && 'text-sm',\n size === 'lg' && 'text-base',\n className\n )}\n >\n {keys.map((key, index) => {\n const keyId = `${key}-${index}-${shortcut}`;\n const displayKey = getDisplayKey(key);\n return (\n <span key={keyId} className=\"inline-flex items-center\">\n {index > 0 && <span className=\"text-neutral/50\">+</span>}\n <span\n className={cn(\n 'min-w-4 px-0.5 text-center',\n isKeyPressed(key) && 'scale-120 font-bold text-text'\n )}\n suppressHydrationWarning\n >\n {displayKey}\n </span>\n </span>\n );\n })}\n </kbd>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"KeyboardShortcut.mjs","names":[],"sources":["../../../../src/components/KeyboardShortcut/KeyboardShortcut.tsx"],"sourcesContent":["'use client';\n\nimport { useDevice } from '@hooks/useDevice';\nimport { cn } from '@utils/cn';\nimport { type FC, useEffect, useState } from 'react';\n\n/**\n * Enum for available keyboard keys\n */\nexport type KeyList = \n | 'Ctrl' |\n 'Alt' |\n 'Shift' |\n 'Meta' |\n 'F' |\n 'K' |\n 'L' |\n 'P' |\n 'S' |\n 'A' |\n 'B' |\n 'C' |\n 'D' |\n 'E' |\n 'G' |\n 'H' |\n 'I' |\n 'J' |\n 'M' |\n 'N' |\n 'O' |\n 'Q' |\n 'R' |\n 'T' |\n 'U' |\n 'V' |\n 'W' |\n 'X' |\n 'Y' |\n 'Z' |\n 'Enter' |\n 'Escape' |\n 'Backspace' |\n 'Tab' |\n 'Space' |\n 'ArrowUp' |\n 'ArrowDown' |\n 'ArrowLeft' |\n 'ArrowRight';\n\n/**\n * Type-safe keyboard shortcut combinations\n * Note: Using string type to avoid union type complexity issues\n * Expected format: \"Key + Key\" (e.g., \"⌘ + F\", \"Ctrl + Shift + K\")\n */\nexport type KeyboardShortcutType = string;\n\nexport type KeyboardShortcutProps = {\n /** The keyboard shortcut combination (e.g., \"⌘ + F\" or \"Ctrl + K\") */\n shortcut: KeyboardShortcutType;\n /** Callback function triggered when the shortcut is pressed */\n onTriggered?: () => void;\n /** Whether to display the shortcut visually (default: true) */\n display?: boolean;\n /** Whether to disable the shortcut trigger (default: false) */\n disabled?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Size of the keyboard shortcut display */\n size?: 'sm' | 'md' | 'lg';\n};\n\n/**\n * Parse keyboard shortcut string into individual keys\n */\nconst parseShortcut = (shortcut: string): string[] => {\n return shortcut.split(' + ').map((key) => key.trim());\n};\n\n/**\n * Normalize key name for event comparison\n */\nconst normalizeKey = (key: string): string => {\n const keyMap: Record<string, string> = {\n '⌘': 'Meta',\n Ctrl: 'Control',\n Control: 'Control',\n Alt: 'Alt',\n '⌥': 'Alt',\n Shift: 'Shift',\n Meta: 'Meta',\n '↑': 'ArrowUp',\n '↓': 'ArrowDown',\n '←': 'ArrowLeft',\n '→': 'ArrowRight',\n ArrowUp: 'ArrowUp',\n ArrowDown: 'ArrowDown',\n ArrowLeft: 'ArrowLeft',\n ArrowRight: 'ArrowRight',\n };\n\n return keyMap[key] || key;\n};\n\n/**\n * Check if the keyboard event matches the shortcut\n */\nconst matchesShortcut = (event: KeyboardEvent, keys: string[]): boolean => {\n const normalizedKeys = keys.map(normalizeKey);\n const hasModifiers = {\n Meta: normalizedKeys.includes('Meta'),\n Control: normalizedKeys.includes('Control'),\n Alt: normalizedKeys.includes('Alt'),\n Shift: normalizedKeys.includes('Shift'),\n };\n\n // Check if all required modifiers are pressed\n if (\n hasModifiers.Meta !== event.metaKey ||\n hasModifiers.Control !== event.ctrlKey ||\n hasModifiers.Alt !== event.altKey ||\n hasModifiers.Shift !== event.shiftKey\n ) {\n return false;\n }\n\n // Find the non-modifier key\n const nonModifierKey = keys.find(\n (key) =>\n !['⌘', 'Ctrl', 'Control', 'Alt', '⌥', 'Shift', 'Meta'].includes(\n normalizeKey(key)\n )\n );\n\n if (!nonModifierKey) return false;\n\n // Normalize the key for comparison\n const normalizedNonModifierKey = normalizeKey(nonModifierKey);\n\n // Compare the main key\n // For arrow keys, compare directly with event.key\n if (normalizedNonModifierKey.startsWith('Arrow')) {\n return event.key === normalizedNonModifierKey;\n }\n\n // For other keys, compare case-insensitive\n return event.key.toLowerCase() === normalizedNonModifierKey.toLowerCase();\n};\n\n/**\n * Get display key symbol for better visual representation\n */\nconst getDisplayKey = (key: string): string => {\n const displayMap: Record<string, string> = {\n ArrowUp: '↑',\n ArrowDown: '↓',\n ArrowLeft: '←',\n ArrowRight: '→',\n };\n\n return displayMap[key] || key;\n};\n\n/**\n * Get display shortcut based on OS (Mac uses ⌘ and ⌥, others use Ctrl and Alt)\n */\nconst getDisplayShortcut = (shortcut: string, isMac: boolean): string => {\n let result = shortcut;\n\n if (isMac) {\n result = result.replace(/Ctrl/g, '⌘');\n result = result.replace(/Alt/g, '⌥');\n } else {\n result = result.replace(/⌘/g, 'Ctrl');\n result = result.replace(/⌥/g, 'Alt');\n }\n\n // Replace arrow key names with symbols\n result = result.replace(/ArrowUp/g, '↑');\n result = result.replace(/ArrowDown/g, '↓');\n result = result.replace(/ArrowLeft/g, '←');\n result = result.replace(/ArrowRight/g, '→');\n\n return result;\n};\n\n/**\n * KeyboardShortcut Component\n *\n * A reusable component that displays keyboard shortcuts and listens for key combinations.\n * Automatically adapts to Mac (⌘, ⌥) and Windows/Linux (Ctrl, Alt) conventions.\n *\n * @example\n * ```tsx\n * <KeyboardShortcut\n * shortcut=\"⌘ + F\"\n * onTriggered={() => setShowSearch(true)}\n * />\n * ```\n */\nexport const KeyboardShortcut: FC<KeyboardShortcutProps> = ({\n shortcut,\n onTriggered,\n display = true,\n disabled = false,\n className,\n size = 'md',\n}) => {\n const { isMac } = useDevice();\n const displayShortcut = getDisplayShortcut(shortcut, isMac ?? false);\n const keys = parseShortcut(displayShortcut);\n const [pressedKeys, setPressedKeys] = useState<Set<string>>(new Set());\n\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n // 1. Identify input fields\n const target = event.target as HTMLElement;\n const isInputField =\n target.tagName === 'INPUT' ||\n target.tagName === 'TEXTAREA' ||\n target.isContentEditable;\n\n // ... (Your existing key visualization logic here) ...\n // Note: Copied your key tracking logic for context\n const currentKey = event.key;\n const normalizedEventKeys = new Set<string>();\n if (event.metaKey) normalizedEventKeys.add('⌘');\n if (event.ctrlKey) normalizedEventKeys.add('Ctrl');\n if (event.altKey) normalizedEventKeys.add(isMac ? '⌥' : 'Alt');\n if (event.shiftKey) normalizedEventKeys.add('Shift');\n\n if (currentKey.startsWith('Arrow')) {\n normalizedEventKeys.add(currentKey);\n normalizedEventKeys.add(getDisplayKey(currentKey));\n } else {\n normalizedEventKeys.add(currentKey.toUpperCase());\n }\n setPressedKeys(normalizedEventKeys);\n\n // 2. Trigger callback if shortcut matches\n if (!disabled && onTriggered && matchesShortcut(event, keys)) {\n // FIX: Check if the required shortcut is \"Escape\"\n const isEscapeShortcut = keys.includes('Escape');\n\n // Only block if it is an input field AND the shortcut is NOT Escape\n if (isInputField && !isEscapeShortcut) {\n return;\n }\n\n event.preventDefault();\n onTriggered();\n }\n };\n\n const handleKeyUp = () => {\n setPressedKeys(new Set());\n };\n\n window.addEventListener('keydown', handleKeyDown);\n window.addEventListener('keyup', handleKeyUp);\n window.addEventListener('blur', handleKeyUp);\n\n return () => {\n window.removeEventListener('keydown', handleKeyDown);\n window.removeEventListener('keyup', handleKeyUp);\n window.removeEventListener('blur', handleKeyUp);\n };\n }, [keys, onTriggered, isMac, disabled]);\n if (!display) return null;\n\n /**\n * Check if a key is currently pressed\n */\n const isKeyPressed = (key: string): boolean => {\n const upperKey = key.toUpperCase();\n const normalizedKey = normalizeKey(key);\n\n return (\n pressedKeys.has(key) ||\n pressedKeys.has(upperKey) ||\n pressedKeys.has(normalizedKey) ||\n // Check for modifier key matches\n (key === '⌘' && pressedKeys.has('Meta')) ||\n (key === 'Ctrl' && pressedKeys.has('Control')) ||\n (key === '⌥' && pressedKeys.has('Alt')) ||\n (key === 'Alt' && pressedKeys.has('Alt')) ||\n // Check for arrow key symbols\n (key === '←' && pressedKeys.has('ArrowLeft')) ||\n (key === '→' && pressedKeys.has('ArrowRight')) ||\n (key === '↑' && pressedKeys.has('ArrowUp')) ||\n (key === '↓' && pressedKeys.has('ArrowDown'))\n );\n };\n\n return (\n <kbd\n className={cn(\n 'inline-flex items-center justify-center gap-0.5 p-0.5',\n 'rounded-lg [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-xl',\n 'font-medium font-sans',\n 'border-1 border-neutral/20 text-neutral',\n size === 'sm' && 'text-xs',\n size === 'md' && 'text-sm',\n size === 'lg' && 'text-base',\n className\n )}\n >\n {keys.map((key, index) => {\n const keyId = `${key}-${index}-${shortcut}`;\n const displayKey = getDisplayKey(key);\n return (\n <span key={keyId} className=\"inline-flex items-center\">\n {index > 0 && <span className=\"text-neutral/50\">+</span>}\n <span\n className={cn(\n 'min-w-4 px-0.5 text-center',\n isKeyPressed(key) && 'scale-120 font-bold text-text'\n )}\n suppressHydrationWarning\n >\n {displayKey}\n </span>\n </span>\n );\n })}\n </kbd>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { KeyboardShortcut } from "./KeyboardShortcut.mjs";
|
|
2
2
|
|
|
3
|
-
export {
|
|
3
|
+
export { KeyboardShortcut };
|
|
@@ -6,100 +6,48 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
import { getLocalizedUrl } from "@intlayer/core/localization";
|
|
7
7
|
|
|
8
8
|
//#region src/components/Link/Link.tsx
|
|
9
|
-
/**
|
|
10
|
-
* Visual style variants for Link component
|
|
11
|
-
*/
|
|
12
|
-
let LinkVariant = /* @__PURE__ */ function(LinkVariant) {
|
|
13
|
-
LinkVariant["DEFAULT"] = "default";
|
|
14
|
-
LinkVariant["INVISIBLE_LINK"] = "invisible-link";
|
|
15
|
-
LinkVariant["BUTTON"] = "button";
|
|
16
|
-
LinkVariant["BUTTON_OUTLINED"] = "button-outlined";
|
|
17
|
-
LinkVariant["HOVERABLE"] = "hoverable";
|
|
18
|
-
return LinkVariant;
|
|
19
|
-
}({});
|
|
20
|
-
/**
|
|
21
|
-
* Color theme variants for Link component
|
|
22
|
-
*/
|
|
23
|
-
let LinkColor = /* @__PURE__ */ function(LinkColor) {
|
|
24
|
-
LinkColor["PRIMARY"] = "primary";
|
|
25
|
-
LinkColor["SECONDARY"] = "secondary";
|
|
26
|
-
LinkColor["NEUTRAL"] = "neutral";
|
|
27
|
-
LinkColor["LIGHT"] = "light";
|
|
28
|
-
LinkColor["DARK"] = "dark";
|
|
29
|
-
LinkColor["TEXT"] = "text";
|
|
30
|
-
LinkColor["TEXT_INVERSE"] = "text-inverse";
|
|
31
|
-
LinkColor["ERROR"] = "error";
|
|
32
|
-
LinkColor["SUCCESS"] = "success";
|
|
33
|
-
LinkColor["CUSTOM"] = "custom";
|
|
34
|
-
return LinkColor;
|
|
35
|
-
}({});
|
|
36
|
-
let LinkRoundedSize = /* @__PURE__ */ function(LinkRoundedSize) {
|
|
37
|
-
LinkRoundedSize["NONE"] = "none";
|
|
38
|
-
LinkRoundedSize["SM"] = "sm";
|
|
39
|
-
LinkRoundedSize["MD"] = "md";
|
|
40
|
-
LinkRoundedSize["LG"] = "lg";
|
|
41
|
-
LinkRoundedSize["XL"] = "xl";
|
|
42
|
-
LinkRoundedSize["TWO_XL"] = "2xl";
|
|
43
|
-
LinkRoundedSize["THREE_XL"] = "3xl";
|
|
44
|
-
LinkRoundedSize["FULL"] = "full";
|
|
45
|
-
return LinkRoundedSize;
|
|
46
|
-
}({});
|
|
47
|
-
let LinkSize = /* @__PURE__ */ function(LinkSize) {
|
|
48
|
-
LinkSize["SM"] = "sm";
|
|
49
|
-
LinkSize["MD"] = "md";
|
|
50
|
-
LinkSize["LG"] = "lg";
|
|
51
|
-
LinkSize["XL"] = "xl";
|
|
52
|
-
LinkSize["CUSTOM"] = "custom";
|
|
53
|
-
return LinkSize;
|
|
54
|
-
}({});
|
|
55
|
-
let LinkUnderlined = /* @__PURE__ */ function(LinkUnderlined) {
|
|
56
|
-
LinkUnderlined["DEFAULT"] = "default";
|
|
57
|
-
LinkUnderlined["TRUE"] = "true";
|
|
58
|
-
LinkUnderlined["FALSE"] = "false";
|
|
59
|
-
return LinkUnderlined;
|
|
60
|
-
}({});
|
|
61
9
|
const linkVariants = cva("gap-3 transition-all duration-300 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50", {
|
|
62
10
|
variants: {
|
|
63
11
|
variant: {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
12
|
+
default: "h-auto justify-start border-inherit bg-current/0 px-1 font-medium decoration-[1.5] underline-offset-5 hover:bg-current/0 hover:text-current/80 hover:underline hover:underline-offset-6",
|
|
13
|
+
"invisible-link": "h-auto justify-start border-inherit bg-current/0 px-1 underline-offset-5 hover:bg-current/0 aria-[current]:bg-current/5",
|
|
14
|
+
button: "relative flex cursor-pointer flex-row items-center justify-center gap-2 rounded-full bg-current text-center font-medium text-text ring-0 *:text-text-opposite hover:bg-current/90 hover:ring-5 aria-selected:ring-5 aria-[current]:ring-5",
|
|
15
|
+
"button-outlined": "relative flex cursor-pointer flex-row items-center justify-center gap-2 rounded-full border-[1.3px] border-current text-center font-medium text-text ring-0 *:text-text hover:bg-current/20 hover:ring-5 aria-selected:ring-5 aria-[current]:ring-5",
|
|
16
|
+
hoverable: "rounded-lg border-none bg-current/0 transition *:text-current! hover:bg-current/20 aria-[current]:bg-current/5"
|
|
69
17
|
},
|
|
70
18
|
roundedSize: {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
19
|
+
none: "rounded-none",
|
|
20
|
+
sm: "rounded-lg [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-xl",
|
|
21
|
+
md: "rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl",
|
|
22
|
+
lg: "rounded-2xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-3xl",
|
|
23
|
+
xl: "rounded-3xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-4xl",
|
|
24
|
+
"2xl": "rounded-4xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[2.5rem]",
|
|
25
|
+
"3xl": "rounded-[2.5rem] [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[3rem]",
|
|
26
|
+
full: "rounded-full"
|
|
79
27
|
},
|
|
80
28
|
color: {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
29
|
+
primary: "text-primary",
|
|
30
|
+
secondary: "text-secondary",
|
|
31
|
+
neutral: "text-neutral",
|
|
32
|
+
light: "text-white",
|
|
33
|
+
dark: "text-neutral-800",
|
|
34
|
+
text: "text-text",
|
|
35
|
+
"text-inverse": "text-text-opposite",
|
|
36
|
+
error: "text-error",
|
|
37
|
+
success: "text-success",
|
|
38
|
+
custom: ""
|
|
91
39
|
},
|
|
92
40
|
size: {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
41
|
+
sm: "text-sm",
|
|
42
|
+
md: "text-base",
|
|
43
|
+
lg: "text-lg",
|
|
44
|
+
xl: "text-xl",
|
|
45
|
+
custom: ""
|
|
98
46
|
},
|
|
99
47
|
underlined: {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
48
|
+
default: "",
|
|
49
|
+
true: "underline",
|
|
50
|
+
false: "no-underline"
|
|
103
51
|
}
|
|
104
52
|
},
|
|
105
53
|
compoundVariants: [
|
|
@@ -183,7 +131,7 @@ const linkVariants = cva("gap-3 transition-all duration-300 focus-visible:outlin
|
|
|
183
131
|
variant: "default",
|
|
184
132
|
roundedSize: "md",
|
|
185
133
|
underlined: "default",
|
|
186
|
-
size: "
|
|
134
|
+
size: "custom"
|
|
187
135
|
}
|
|
188
136
|
});
|
|
189
137
|
const checkIsExternalLink = ({ href, isExternalLink: isExternalLinkProp }, url) => {
|
|
@@ -240,5 +188,5 @@ const Link = (props) => {
|
|
|
240
188
|
};
|
|
241
189
|
|
|
242
190
|
//#endregion
|
|
243
|
-
export { Link,
|
|
191
|
+
export { Link, checkIsExternalLink, isTextChildren, linkVariants };
|
|
244
192
|
//# sourceMappingURL=Link.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Link.mjs","names":[],"sources":["../../../../src/components/Link/Link.tsx"],"sourcesContent":["import { getLocalizedUrl } from '@intlayer/core/localization';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { ExternalLink, MoveRight } from 'lucide-react';\nimport {\n type AnchorHTMLAttributes,\n type DetailedHTMLProps,\n type FC,\n isValidElement,\n type ReactNode,\n} from 'react';\n\n/**\n * Visual style variants for Link component\n */\nexport enum LinkVariant {\n DEFAULT = 'default',\n INVISIBLE_LINK = 'invisible-link',\n BUTTON = 'button',\n BUTTON_OUTLINED = 'button-outlined',\n HOVERABLE = 'hoverable',\n}\n\n/**\n * Color theme variants for Link component\n */\nexport enum LinkColor {\n PRIMARY = 'primary',\n SECONDARY = 'secondary',\n NEUTRAL = 'neutral',\n LIGHT = 'light',\n DARK = 'dark',\n TEXT = 'text',\n TEXT_INVERSE = 'text-inverse',\n ERROR = 'error',\n SUCCESS = 'success',\n CUSTOM = 'custom',\n}\n\nexport enum LinkRoundedSize {\n NONE = 'none',\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n TWO_XL = '2xl',\n THREE_XL = '3xl',\n FULL = 'full',\n}\n\nexport enum LinkSize {\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n CUSTOM = 'custom',\n}\n\nexport enum LinkUnderlined {\n DEFAULT = 'default',\n TRUE = 'true',\n FALSE = 'false',\n}\n\nexport const linkVariants = cva(\n 'gap-3 transition-all duration-300 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n variant: {\n [`${LinkVariant.DEFAULT}`]:\n 'h-auto justify-start border-inherit bg-current/0 px-1 font-medium decoration-[1.5] underline-offset-5 hover:bg-current/0 hover:text-current/80 hover:underline hover:underline-offset-6',\n [`${LinkVariant.INVISIBLE_LINK}`]:\n 'h-auto justify-start border-inherit bg-current/0 px-1 underline-offset-5 hover:bg-current/0 aria-[current]:bg-current/5',\n\n [`${LinkVariant.BUTTON}`]:\n 'relative flex cursor-pointer flex-row items-center justify-center gap-2 rounded-full bg-current text-center font-medium text-text ring-0 *:text-text-opposite hover:bg-current/90 hover:ring-5 aria-selected:ring-5 aria-[current]:ring-5',\n\n [`${LinkVariant.BUTTON_OUTLINED}`]:\n 'relative flex cursor-pointer flex-row items-center justify-center gap-2 rounded-full border-[1.3px] border-current text-center font-medium text-text ring-0 *:text-text hover:bg-current/20 hover:ring-5 aria-selected:ring-5 aria-[current]:ring-5',\n\n [`${LinkVariant.HOVERABLE}`]:\n 'rounded-lg border-none bg-current/0 transition *:text-current! hover:bg-current/20 aria-[current]:bg-current/5',\n },\n roundedSize: {\n [`${LinkRoundedSize.NONE}`]: 'rounded-none',\n [`${LinkRoundedSize.SM}`]:\n 'rounded-lg [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-xl',\n [`${LinkRoundedSize.MD}`]:\n 'rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl',\n [`${LinkRoundedSize.LG}`]:\n 'rounded-2xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-3xl',\n [`${LinkRoundedSize.XL}`]:\n 'rounded-3xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-4xl',\n [`${LinkRoundedSize.TWO_XL}`]:\n 'rounded-4xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[2.5rem]',\n [`${LinkRoundedSize.THREE_XL}`]:\n 'rounded-[2.5rem] [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[3rem]',\n [`${LinkRoundedSize.FULL}`]: 'rounded-full',\n },\n color: {\n [`${LinkColor.PRIMARY}`]: 'text-primary',\n [`${LinkColor.SECONDARY}`]: 'text-secondary',\n [`${LinkColor.NEUTRAL}`]: 'text-neutral',\n [`${LinkColor.LIGHT}`]: 'text-white',\n [`${LinkColor.DARK}`]: 'text-neutral-800',\n [`${LinkColor.TEXT}`]: 'text-text',\n [`${LinkColor.TEXT_INVERSE}`]: 'text-text-opposite',\n [`${LinkColor.ERROR}`]: 'text-error',\n [`${LinkColor.SUCCESS}`]: 'text-success',\n [`${LinkColor.CUSTOM}`]: '',\n },\n size: {\n [`${LinkSize.SM}`]: 'text-sm',\n [`${LinkSize.MD}`]: 'text-base',\n [`${LinkSize.LG}`]: 'text-lg',\n [`${LinkSize.XL}`]: 'text-xl',\n [`${LinkSize.CUSTOM}`]: '',\n },\n underlined: {\n [LinkUnderlined.DEFAULT]: '',\n [LinkUnderlined.TRUE]: 'underline',\n [LinkUnderlined.FALSE]: 'no-underline',\n },\n },\n // Compound variants handle height and padding\n compoundVariants: [\n // ---------------------------------------------------------\n // FIX START: Correctly Handle Contrast for TEXT_INVERSE\n // ---------------------------------------------------------\n {\n // Filled Button + Inverse Color (e.g., White Button):\n // We DO NOT override parent text color (it must remain 'text-opposite' so bg-current is white).\n // We ONLY override children to be 'text-text' (Dark) so they show up on white.\n variant: LinkVariant.BUTTON,\n color: LinkColor.TEXT_INVERSE,\n class: '*:text-text',\n },\n {\n // Outlined Button + Inverse Color (e.g., White Border):\n // Parent is 'text-opposite' (Border is white).\n // Children must also be 'text-opposite' (White text) to show on dark background.\n variant: LinkVariant.BUTTON_OUTLINED,\n color: LinkColor.TEXT_INVERSE,\n class: 'text-text-opposite *:text-text-opposite',\n },\n\n // Min height and padding for button variants\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n size: LinkSize.SM,\n class: 'min-h-7 px-3 max-md:py-1',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n size: LinkSize.MD,\n class: 'min-h-8 px-6 max-md:py-2',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n size: LinkSize.LG,\n class: 'min-h-10 px-8 max-md:py-3',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n size: LinkSize.XL,\n class: 'min-h-11 px-10 max-md:py-4',\n },\n // Ring color variants\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.PRIMARY,\n class: 'ring-primary/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.SECONDARY,\n class: 'ring-secondary/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.NEUTRAL,\n class: 'ring-neutral/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.LIGHT,\n class: 'ring-white/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.DARK,\n class: 'ring-neutral-800/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.TEXT,\n class: 'ring-text/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.TEXT_INVERSE,\n class: 'ring-text-opposite/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.ERROR,\n class: 'ring-error/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.SUCCESS,\n class: 'ring-success/20',\n },\n ],\n\n defaultVariants: {\n variant: LinkVariant.DEFAULT,\n roundedSize: LinkRoundedSize.MD,\n underlined: LinkUnderlined.DEFAULT,\n size: LinkSize.MD,\n },\n }\n);\n\nexport type LinkProps = DetailedHTMLProps<\n AnchorHTMLAttributes<HTMLAnchorElement>,\n HTMLAnchorElement\n> &\n VariantProps<typeof linkVariants> & {\n label: string;\n isExternalLink?: boolean;\n isPageSection?: boolean;\n isActive?: boolean;\n locale?: LocalesValues;\n };\n\nexport const checkIsExternalLink = (\n {\n href,\n isExternalLink: isExternalLinkProp,\n }: Pick<LinkProps, 'href' | 'isExternalLink'>,\n url?: string\n): boolean => {\n // Explicit prop override takes precedence\n if (typeof isExternalLinkProp === 'boolean') {\n return isExternalLinkProp;\n }\n\n const isValidHref = typeof href === 'string' && href.trim() !== '';\n\n if (!isValidHref) return false;\n\n // Relative URLs (e.g., '/about') are always internal\n if (!/^https?:\\/\\//.test(href)) {\n return false;\n }\n\n // Compare base domains\n if (url) {\n try {\n const hrefHost = new URL(href).hostname;\n // Ensure the reference url has a protocol so URL() can parse it correctly\n const currentHost = new URL(\n url.startsWith('http') ? url : `https://${url}`\n ).hostname;\n\n // Extract the root domain (e.g., 'app.intlayer.org' -> 'intlayer.org')\n const getBaseDomain = (host: string) =>\n host.split('.').slice(-2).join('.');\n\n return getBaseDomain(hrefHost) !== getBaseDomain(currentHost);\n } catch {\n // If URL parsing fails for any reason, default to treating it as external\n return true;\n }\n }\n\n // Absolute URL with no comparison URL provided\n return true;\n};\n\nexport const isTextChildren = (children: ReactNode): boolean => {\n if (typeof children === 'string' || typeof children === 'number') {\n return true;\n }\n if (Array.isArray(children)) {\n return children.every(isTextChildren);\n }\n if (isValidElement(children)) {\n return isTextChildren(\n (children.props as { children?: ReactNode }).children\n );\n }\n return false;\n};\n\nexport const Link: FC<LinkProps> = (props) => {\n const {\n variant = LinkVariant.DEFAULT,\n color = LinkColor.CUSTOM,\n roundedSize,\n children,\n label,\n className,\n isActive,\n underlined,\n locale,\n size,\n isExternalLink: isExternalLinkProp,\n isPageSection: isPageSectionProp,\n href: hrefProp,\n ...otherProps\n } = props;\n\n const isExternalLink = isExternalLinkProp ?? checkIsExternalLink(props);\n const isPageSection = isPageSectionProp ?? hrefProp?.startsWith('#') ?? false;\n\n const isChildrenString = isTextChildren(children);\n const isButton =\n variant === LinkVariant.BUTTON || variant === LinkVariant.BUTTON_OUTLINED;\n\n const rel = isExternalLink ? 'noopener noreferrer nofollow' : undefined;\n\n const target = isExternalLink ? '_blank' : '_self';\n\n const resolvedHref =\n locale && hrefProp && !isExternalLink && !isPageSection\n ? getLocalizedUrl(hrefProp, locale)\n : hrefProp;\n\n const href = resolvedHref === '' ? undefined : resolvedHref;\n\n return (\n <a\n href={href}\n aria-label={label}\n rel={rel}\n target={target}\n aria-current={isActive ? 'page' : undefined}\n suppressHydrationWarning\n className={cn(\n linkVariants({\n variant,\n color,\n roundedSize,\n underlined,\n size,\n className,\n })\n )}\n {...otherProps}\n >\n {isButton && isChildrenString ? <span>{children}</span> : children}\n\n {isExternalLink && isChildrenString && (\n <ExternalLink className=\"ml-2 inline-block size-4\" />\n )}\n {isPageSection && <MoveRight className=\"ml-2 inline-block size-4\" />}\n </a>\n );\n};\n"],"mappings":";;;;;;;;;;;AAgBA,IAAY,cAAL;CACL;CACA;CACA;CACA;CACA;;AACF;;;;AAKA,IAAY,YAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;AACF;AAEA,IAAY,kBAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;AACF;AAEA,IAAY,WAAL;CACL;CACA;CACA;CACA;CACA;;AACF;AAEA,IAAY,iBAAL;CACL;CACA;CACA;;AACF;AAEA,MAAa,eAAe,IAC1B,iHACA;CACE,UAAU;EACR,SAAS;IACN,YACC;IACD,mBACC;IAED,WACC;IAED,oBACC;IAED,cACC;EACJ;EACA,aAAa;IACV,SAA4B;IAC5B,OACC;IACD,OACC;IACD,OACC;IACD,OACC;IACD,QACC;IACD,QACC;IACD,SAA4B;EAC/B;EACA,OAAO;IACJ,YAAyB;IACzB,cAA2B;IAC3B,YAAyB;IACzB,UAAuB;IACvB,SAAsB;IACtB,SAAsB;IACtB,iBAA8B;IAC9B,UAAuB;IACvB,YAAyB;IACzB,WAAwB;EAC3B;EACA,MAAM;IACH,OAAmB;IACnB,OAAmB;IACnB,OAAmB;IACnB,OAAmB;IACnB,WAAuB;EAC1B;EACA,YAAY;gBACgB;aACH;cACC;EAC1B;CACF;CAEA,kBAAkB;EAIhB;GAIE;GACA;GACA,OAAO;EACT;EACA;GAIE;GACA;GACA,OAAO;EACT;EAGA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EAEA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;CACF;CAEA,iBAAiB;EACf;EACA;EACA;EACA;CACF;AACF,CACF;AAcA,MAAa,uBACX,EACE,MACA,gBAAgB,sBAElB,QACY;CAEZ,IAAI,OAAO,uBAAuB,WAChC,OAAO;CAKT,IAAI,EAFgB,OAAO,SAAS,YAAY,KAAK,KAAK,MAAM,KAE9C,OAAO;CAGzB,IAAI,CAAC,eAAe,KAAK,IAAI,GAC3B,OAAO;CAIT,IAAI,KACF,IAAI;EACF,MAAM,WAAW,IAAI,IAAI,IAAI,EAAE;EAE/B,MAAM,cAAc,IAAI,IACtB,IAAI,WAAW,MAAM,IAAI,MAAM,WAAW,KAC5C,EAAE;EAGF,MAAM,iBAAiB,SACrB,KAAK,MAAM,GAAG,EAAE,MAAM,EAAE,EAAE,KAAK,GAAG;EAEpC,OAAO,cAAc,QAAQ,MAAM,cAAc,WAAW;CAC9D,QAAQ;EAEN,OAAO;CACT;CAIF,OAAO;AACT;AAEA,MAAa,kBAAkB,aAAiC;CAC9D,IAAI,OAAO,aAAa,YAAY,OAAO,aAAa,UACtD,OAAO;CAET,IAAI,MAAM,QAAQ,QAAQ,GACxB,OAAO,SAAS,MAAM,cAAc;CAEtC,IAAI,eAAe,QAAQ,GACzB,OAAO,eACJ,SAAS,MAAmC,QAC/C;CAEF,OAAO;AACT;AAEA,MAAa,QAAuB,UAAU;CAC5C,MAAM,EACJ,qBACA,kBACA,aACA,UACA,OACA,WACA,UACA,YACA,QACA,MACA,gBAAgB,oBAChB,eAAe,mBACf,MAAM,UACN,GAAG,eACD;CAEJ,MAAM,iBAAiB,sBAAsB,oBAAoB,KAAK;CACtE,MAAM,gBAAgB,qBAAqB,UAAU,WAAW,GAAG,KAAK;CAExE,MAAM,mBAAmB,eAAe,QAAQ;CAChD,MAAM,WACJ,wBAAkC;CAEpC,MAAM,MAAM,iBAAiB,iCAAiC;CAE9D,MAAM,SAAS,iBAAiB,WAAW;CAE3C,MAAM,eACJ,UAAU,YAAY,CAAC,kBAAkB,CAAC,gBACtC,gBAAgB,UAAU,MAAM,IAChC;CAIN,OACE,qBAAC,KAAD;EACE,MAJS,iBAAiB,KAAK,SAAY;EAK3C,cAAY;EACP;EACG;EACR,gBAAc,WAAW,SAAS;EAClC;EACA,WAAW,GACT,aAAa;GACX;GACA;GACA;GACA;GACA;GACA;EACF,CAAC,CACH;EACA,GAAI;YAjBN;GAmBG,YAAY,mBAAmB,oBAAC,QAAD,EAAO,SAAe,KAAI;GAEzD,kBAAkB,oBACjB,oBAAC,cAAD,EAAc,WAAU,2BAA4B;GAErD,iBAAiB,oBAAC,WAAD,EAAW,WAAU,2BAA4B;EAClE;;AAEP"}
|
|
1
|
+
{"version":3,"file":"Link.mjs","names":[],"sources":["../../../../src/components/Link/Link.tsx"],"sourcesContent":["import { getLocalizedUrl } from '@intlayer/core/localization';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { ExternalLink, MoveRight } from 'lucide-react';\nimport {\n type AnchorHTMLAttributes,\n type DetailedHTMLProps,\n type FC,\n isValidElement,\n type ReactNode,\n} from 'react';\n\nexport type LinkVariant =\n | 'default'\n | 'invisible-link'\n | 'button'\n | 'button-outlined'\n | 'hoverable';\n\n/**\n * Color theme variants for Link component\n */\nexport type LinkColor =\n | 'primary'\n | 'secondary'\n | 'neutral'\n | 'light'\n | 'dark'\n | 'text'\n | 'text-inverse'\n | 'error'\n | 'success'\n | 'custom';\n\nexport type LinkRoundedSize =\n | 'none'\n | 'sm'\n | 'md'\n | 'lg'\n | 'xl'\n | '2xl'\n | '3xl'\n | 'full';\n\nexport type LinkSize = 'sm' | 'md' | 'lg' | 'xl' | 'custom';\n\nexport type LinkUnderlined = 'default' | 'true' | 'false';\n\nexport const linkVariants = cva(\n 'gap-3 transition-all duration-300 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n variant: {\n default:\n 'h-auto justify-start border-inherit bg-current/0 px-1 font-medium decoration-[1.5] underline-offset-5 hover:bg-current/0 hover:text-current/80 hover:underline hover:underline-offset-6',\n 'invisible-link':\n 'h-auto justify-start border-inherit bg-current/0 px-1 underline-offset-5 hover:bg-current/0 aria-[current]:bg-current/5',\n\n button:\n 'relative flex cursor-pointer flex-row items-center justify-center gap-2 rounded-full bg-current text-center font-medium text-text ring-0 *:text-text-opposite hover:bg-current/90 hover:ring-5 aria-selected:ring-5 aria-[current]:ring-5',\n\n 'button-outlined':\n 'relative flex cursor-pointer flex-row items-center justify-center gap-2 rounded-full border-[1.3px] border-current text-center font-medium text-text ring-0 *:text-text hover:bg-current/20 hover:ring-5 aria-selected:ring-5 aria-[current]:ring-5',\n\n hoverable:\n 'rounded-lg border-none bg-current/0 transition *:text-current! hover:bg-current/20 aria-[current]:bg-current/5',\n },\n roundedSize: {\n none: 'rounded-none',\n sm:\n 'rounded-lg [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-xl',\n md:\n 'rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl',\n lg:\n 'rounded-2xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-3xl',\n xl:\n 'rounded-3xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-4xl',\n '2xl':\n 'rounded-4xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[2.5rem]',\n '3xl':\n 'rounded-[2.5rem] [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[3rem]',\n full: 'rounded-full',\n },\n color: {\n primary: 'text-primary',\n secondary: 'text-secondary',\n neutral: 'text-neutral',\n light: 'text-white',\n dark: 'text-neutral-800',\n text: 'text-text',\n 'text-inverse': 'text-text-opposite',\n error: 'text-error',\n success: 'text-success',\n custom: '',\n },\n size: {\n sm: 'text-sm',\n md: 'text-base',\n lg: 'text-lg',\n xl: 'text-xl',\n custom: '',\n },\n underlined: {\n default: '',\n true: 'underline',\n false: 'no-underline',\n },\n },\n // Compound variants handle height and padding\n compoundVariants: [\n // ---------------------------------------------------------\n // FIX START: Correctly Handle Contrast for TEXT_INVERSE\n // ---------------------------------------------------------\n {\n // Filled Button + Inverse Color (e.g., White Button):\n // We DO NOT override parent text color (it must remain 'text-opposite' so bg-current is white).\n // We ONLY override children to be 'text-text' (Dark) so they show up on white.\n variant: 'button',\n color: 'text-inverse',\n class: '*:text-text',\n },\n {\n // Outlined Button + Inverse Color (e.g., White Border):\n // Parent is 'text-opposite' (Border is white).\n // Children must also be 'text-opposite' (White text) to show on dark background.\n variant: 'button-outlined',\n color: 'text-inverse',\n class: 'text-text-opposite *:text-text-opposite',\n },\n\n // Min height and padding for button variants\n {\n variant: ['button', 'button-outlined'],\n size: 'sm',\n class: 'min-h-7 px-3 max-md:py-1',\n },\n {\n variant: ['button', 'button-outlined'],\n size: 'md',\n class: 'min-h-8 px-6 max-md:py-2',\n },\n {\n variant: ['button', 'button-outlined'],\n size: 'lg',\n class: 'min-h-10 px-8 max-md:py-3',\n },\n {\n variant: ['button', 'button-outlined'],\n size: 'xl',\n class: 'min-h-11 px-10 max-md:py-4',\n },\n // Ring color variants\n {\n variant: ['button', 'button-outlined'],\n color: 'primary',\n class: 'ring-primary/20',\n },\n {\n variant: ['button', 'button-outlined'],\n color: 'secondary',\n class: 'ring-secondary/20',\n },\n {\n variant: ['button', 'button-outlined'],\n color: 'neutral',\n class: 'ring-neutral/20',\n },\n {\n variant: ['button', 'button-outlined'],\n color: 'light',\n class: 'ring-white/20',\n },\n {\n variant: ['button', 'button-outlined'],\n color: 'dark',\n class: 'ring-neutral-800/20',\n },\n {\n variant: ['button', 'button-outlined'],\n color: 'text',\n class: 'ring-text/20',\n },\n {\n variant: ['button', 'button-outlined'],\n color: 'text-inverse',\n class: 'ring-text-opposite/20',\n },\n {\n variant: ['button', 'button-outlined'],\n color: 'error',\n class: 'ring-error/20',\n },\n {\n variant: ['button', 'button-outlined'],\n color: 'success',\n class: 'ring-success/20',\n },\n ],\n\n defaultVariants: {\n variant: 'default',\n roundedSize: 'md',\n underlined: 'default',\n size: 'custom',\n },\n }\n);\n\nexport type LinkProps = DetailedHTMLProps<\n AnchorHTMLAttributes<HTMLAnchorElement>,\n HTMLAnchorElement\n> &\n VariantProps<typeof linkVariants> & {\n label: string;\n isExternalLink?: boolean;\n isPageSection?: boolean;\n isActive?: boolean;\n locale?: LocalesValues;\n };\n\nexport const checkIsExternalLink = (\n {\n href,\n isExternalLink: isExternalLinkProp,\n }: Pick<LinkProps, 'href' | 'isExternalLink'>,\n url?: string\n): boolean => {\n // Explicit prop override takes precedence\n if (typeof isExternalLinkProp === 'boolean') {\n return isExternalLinkProp;\n }\n\n const isValidHref = typeof href === 'string' && href.trim() !== '';\n\n if (!isValidHref) return false;\n\n // Relative URLs (e.g., '/about') are always internal\n if (!/^https?:\\/\\//.test(href)) {\n return false;\n }\n\n // Compare base domains\n if (url) {\n try {\n const hrefHost = new URL(href).hostname;\n // Ensure the reference url has a protocol so URL() can parse it correctly\n const currentHost = new URL(\n url.startsWith('http') ? url : `https://${url}`\n ).hostname;\n\n // Extract the root domain (e.g., 'app.intlayer.org' -> 'intlayer.org')\n const getBaseDomain = (host: string) =>\n host.split('.').slice(-2).join('.');\n\n return getBaseDomain(hrefHost) !== getBaseDomain(currentHost);\n } catch {\n // If URL parsing fails for any reason, default to treating it as external\n return true;\n }\n }\n\n // Absolute URL with no comparison URL provided\n return true;\n};\n\nexport const isTextChildren = (children: ReactNode): boolean => {\n if (typeof children === 'string' || typeof children === 'number') {\n return true;\n }\n if (Array.isArray(children)) {\n return children.every(isTextChildren);\n }\n if (isValidElement(children)) {\n return isTextChildren(\n (children.props as { children?: ReactNode }).children\n );\n }\n return false;\n};\n\nexport const Link: FC<LinkProps> = (props) => {\n const {\n variant = 'default',\n color = 'custom',\n roundedSize,\n children,\n label,\n className,\n isActive,\n underlined,\n locale,\n size,\n isExternalLink: isExternalLinkProp,\n isPageSection: isPageSectionProp,\n href: hrefProp,\n ...otherProps\n } = props;\n\n const isExternalLink = isExternalLinkProp ?? checkIsExternalLink(props);\n const isPageSection = isPageSectionProp ?? hrefProp?.startsWith('#') ?? false;\n\n const isChildrenString = isTextChildren(children);\n const isButton =\n variant === 'button' || variant === 'button-outlined';\n\n const rel = isExternalLink ? 'noopener noreferrer nofollow' : undefined;\n\n const target = isExternalLink ? '_blank' : '_self';\n\n const resolvedHref =\n locale && hrefProp && !isExternalLink && !isPageSection\n ? getLocalizedUrl(hrefProp, locale)\n : hrefProp;\n\n const href = resolvedHref === '' ? undefined : resolvedHref;\n\n return (\n <a\n href={href}\n aria-label={label}\n rel={rel}\n target={target}\n aria-current={isActive ? 'page' : undefined}\n suppressHydrationWarning\n className={cn(\n linkVariants({\n variant,\n color,\n roundedSize,\n underlined,\n size,\n className,\n })\n )}\n {...otherProps}\n >\n {isButton && isChildrenString ? <span>{children}</span> : children}\n\n {isExternalLink && isChildrenString && (\n <ExternalLink className=\"ml-2 inline-block size-4\" />\n )}\n {isPageSection && <MoveRight className=\"ml-2 inline-block size-4\" />}\n </a>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { Link,
|
|
1
|
+
import { Link, checkIsExternalLink, isTextChildren, linkVariants } from "./Link.mjs";
|
|
2
2
|
|
|
3
|
-
export { Link,
|
|
3
|
+
export { Link, checkIsExternalLink, isTextChildren, linkVariants };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { usePersistedStore } from "../../hooks/usePersistedStore.mjs";
|
|
4
|
+
import { Button } from "../Button/Button.mjs";
|
|
3
5
|
import { Container } from "../Container/index.mjs";
|
|
4
|
-
import { Button, ButtonColor, ButtonSize, ButtonTextAlign, ButtonVariant } from "../Button/Button.mjs";
|
|
5
6
|
import { DropDown } from "../DropDown/index.mjs";
|
|
6
7
|
import { Input } from "../Input/Input.mjs";
|
|
7
|
-
import { SwitchSelector
|
|
8
|
-
import { usePersistedStore } from "../../hooks/usePersistedStore.mjs";
|
|
8
|
+
import { SwitchSelector } from "../SwitchSelector/SwitchSelector.mjs";
|
|
9
9
|
import { useLocaleSwitcherContent } from "./LocaleSwitcherContentContext.mjs";
|
|
10
10
|
import { useMemo, useRef, useState } from "react";
|
|
11
11
|
import { Check, Globe, MoveVertical } from "lucide-react";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocaleSwitcherContent.mjs","names":[],"sources":["../../../../src/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.tsx"],"sourcesContent":["'use client';\n\nimport { usePersistedStore } from '@hooks/usePersistedStore';\nimport { getHTMLTextDir, getLocaleName } from '@intlayer/core/localization';\nimport { ENGLISH } from '@intlayer/types/locales';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport Fuse, { type IFuseOptions } from 'fuse.js';\nimport { Check, Globe, MoveVertical } from 'lucide-react';\nimport { type FC, useMemo, useRef, useState } from 'react';\nimport { useIntlayer, useLocale } from 'react-intlayer';\nimport {\n Button,\n ButtonColor,\n ButtonSize,\n ButtonTextAlign,\n ButtonVariant,\n} from '../Button';\nimport { Container } from '../Container';\nimport { DropDown, type PanelProps } from '../DropDown';\nimport { Input } from '../Input';\nimport {\n SwitchSelector,\n SwitchSelectorColor,\n SwitchSelectorSize,\n} from '../SwitchSelector';\nimport { useLocaleSwitcherContent } from './LocaleSwitcherContentContext';\n\nexport type LocaleSwitcherContentProps = {\n panelProps?: Omit<PanelProps, 'identifier'>;\n isMultilingual?: boolean;\n};\n\nconst DROPDOWN_IDENTIFIER = 'locale-switcher-content';\n\ntype MultilingualAvailableLocales = {\n locale: LocalesValues;\n englishName: string;\n currentLocaleName: string;\n ownLocaleName: string;\n};\n\nexport const LocaleSwitcherContent: FC<LocaleSwitcherContentProps> = ({\n panelProps,\n isMultilingual = true,\n}) => {\n const {\n switchTo,\n searchInput,\n localeSwitcherLabel,\n languageListLabel,\n seeAllLocalesSwitch,\n } = useIntlayer('locale-switcher-content');\n const inputRef = useRef<HTMLInputElement>(null);\n const { locale } = useLocale();\n const { availableLocales, selectedLocales, setSelectedLocales } =\n useLocaleSwitcherContent();\n\n // 1. Memoize the list construction so it doesn't rebuild every render\n const multilingualAvailableLocales: MultilingualAvailableLocales[] = useMemo(\n () =>\n availableLocales.map((localeEl) => {\n const englishName = getLocaleName(localeEl, ENGLISH);\n const currentLocaleName = getLocaleName(localeEl, locale);\n const ownLocaleName = getLocaleName(localeEl);\n return {\n locale: localeEl,\n englishName,\n currentLocaleName,\n ownLocaleName,\n };\n }),\n [availableLocales, locale]\n );\n\n // 2. State for Search Query only (Source of Truth)\n const [searchQuery, setSearchQuery] = useState('');\n\n const [seeAllLocales, setSeeAllLocales] = usePersistedStore(\n 'locale-content-selector-see-all-locales',\n false\n );\n\n // 3. Memoize Fuse instance\n const fuse = useMemo(() => {\n const fuseOptions: IFuseOptions<MultilingualAvailableLocales> = {\n keys: [\n { name: 'ownLocaleName', weight: 0.4 },\n { name: 'englishName', weight: 0.2 },\n { name: 'currentLocaleName', weight: 0.2 },\n { name: 'locale', weight: 0.2 },\n ],\n threshold: 0.02,\n };\n return new Fuse(multilingualAvailableLocales, fuseOptions);\n }, [multilingualAvailableLocales]);\n\n // 4. Derive results from Search Query\n const results = useMemo(() => {\n if (!searchQuery) {\n return multilingualAvailableLocales;\n }\n return fuse.search(searchQuery).map((result) => result.item);\n }, [searchQuery, multilingualAvailableLocales, fuse]);\n\n const handleClickLocale = (localeItem: LocalesValues) => {\n if (isMultilingual) {\n if (selectedLocales.includes(localeItem)) {\n if (selectedLocales.length > 1) {\n setSelectedLocales((prev) => prev.filter((el) => el !== localeItem));\n }\n } else {\n setSelectedLocales((prev) => [...prev, localeItem]);\n }\n } else {\n setSelectedLocales([localeItem]);\n }\n };\n\n const handleSeeAllLocales = (value: boolean) => {\n setSeeAllLocales(value);\n\n if (value) {\n setSelectedLocales(availableLocales);\n } else {\n setSelectedLocales([locale]);\n }\n };\n\n return (\n <div className=\"rounded-xl border border-text text-text transition-colors\">\n <DropDown identifier={DROPDOWN_IDENTIFIER}>\n <DropDown.Trigger\n identifier={DROPDOWN_IDENTIFIER}\n label={localeSwitcherLabel.value}\n className=\"p-0!\"\n roundedSize=\"3xl\"\n color=\"text\"\n variant=\"hoverable\"\n >\n <div className=\"flex w-full items-center justify-between text-text\">\n <div className=\"px-2 py-1\">\n <Globe size={16} />\n </div>\n <MoveVertical className=\"self-center\" size={16} />\n </div>\n </DropDown.Trigger>\n\n <DropDown.Panel\n identifier={DROPDOWN_IDENTIFIER}\n isOverable\n isFocusable\n align=\"end\"\n {...panelProps}\n >\n <Container\n className=\"max-h-[60vh] min-w-28\"\n separator=\"y\"\n role=\"listbox\"\n transparency=\"xs\"\n border\n roundedSize=\"3xl\"\n borderColor=\"text\"\n aria-label={languageListLabel.value}\n >\n {isMultilingual && (\n <div className=\"m-auto p-2\">\n <SwitchSelector\n defaultValue={seeAllLocales} // Ensure this uses the persisted state\n onChange={handleSeeAllLocales}\n color={SwitchSelectorColor.TEXT}\n size={SwitchSelectorSize.SM}\n className=\"!w-60\"\n choices={[\n {\n content: seeAllLocalesSwitch.true.value,\n value: true,\n },\n {\n content: seeAllLocalesSwitch.false.value,\n value: false,\n },\n ]}\n />\n </div>\n )}\n\n {!(isMultilingual && seeAllLocales) && (\n <>\n <div className=\"p-3\">\n <Input\n type=\"search\"\n aria-label={searchInput.ariaLabel.value}\n placeholder={searchInput.placeholder.value}\n // Update search query state directly\n onChange={(e) => setSearchQuery(e.target.value)}\n ref={inputRef}\n />\n </div>\n <ol className=\"divide-y divide-dashed divide-text/20 overflow-y-auto p-1\">\n {results.map(\n ({\n locale: localeItem,\n currentLocaleName,\n ownLocaleName,\n }) => (\n <li className=\"px-1.5 py-1\" key={localeItem}>\n <Button\n onClick={() => handleClickLocale(localeItem)}\n label={`${switchTo} ${currentLocaleName}`}\n disabled={\n !(availableLocales ?? availableLocales).includes(\n localeItem\n )\n }\n isActive={selectedLocales.includes(localeItem)}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n isFullWidth\n textAlign={ButtonTextAlign.LEFT}\n size={ButtonSize.SM}\n >\n <div className=\"flex flex-row items-center justify-between gap-3 px-2 py-1\">\n {isMultilingual && (\n <div className=\"w-4\">\n {selectedLocales.includes(localeItem) && (\n <Check className=\"size-full\" />\n )}\n </div>\n )}\n <div className=\"flex flex-1 flex-row items-center justify-between gap-3 px-2 py-1\">\n <div className=\"flex flex-col text-nowrap\">\n <span\n dir={getHTMLTextDir(localeItem)}\n lang={localeItem}\n >\n {ownLocaleName}\n </span>\n <span className=\"text-neutral text-xs\">\n {currentLocaleName}\n </span>\n </div>\n <span className=\"text-neutral text-sm\">\n {localeItem.toUpperCase()}\n </span>\n </div>\n </div>\n </Button>\n </li>\n )\n )}\n </ol>\n </>\n )}\n </Container>\n </DropDown.Panel>\n </DropDown>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LocaleSwitcherContent.mjs","names":[],"sources":["../../../../src/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.tsx"],"sourcesContent":["'use client';\n\nimport { usePersistedStore } from '@hooks/usePersistedStore';\nimport { getHTMLTextDir, getLocaleName } from '@intlayer/core/localization';\nimport { ENGLISH } from '@intlayer/types/locales';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport Fuse, { type IFuseOptions } from 'fuse.js';\nimport { Check, Globe, MoveVertical } from 'lucide-react';\nimport { type FC, useMemo, useRef, useState } from 'react';\nimport { useIntlayer, useLocale } from 'react-intlayer';\nimport { Button } from '../Button';\nimport { Container } from '../Container';\nimport { DropDown, type PanelProps } from '../DropDown';\nimport { Input } from '../Input';\nimport { SwitchSelector } from '../SwitchSelector';\nimport { useLocaleSwitcherContent } from './LocaleSwitcherContentContext';\n\nexport type LocaleSwitcherContentProps = {\n panelProps?: Omit<PanelProps, 'identifier'>;\n isMultilingual?: boolean;\n};\n\nconst DROPDOWN_IDENTIFIER = 'locale-switcher-content';\n\ntype MultilingualAvailableLocales = {\n locale: LocalesValues;\n englishName: string;\n currentLocaleName: string;\n ownLocaleName: string;\n};\n\nexport const LocaleSwitcherContent: FC<LocaleSwitcherContentProps> = ({\n panelProps,\n isMultilingual = true,\n}) => {\n const {\n switchTo,\n searchInput,\n localeSwitcherLabel,\n languageListLabel,\n seeAllLocalesSwitch,\n } = useIntlayer('locale-switcher-content');\n const inputRef = useRef<HTMLInputElement>(null);\n const { locale } = useLocale();\n const { availableLocales, selectedLocales, setSelectedLocales } =\n useLocaleSwitcherContent();\n\n // 1. Memoize the list construction so it doesn't rebuild every render\n const multilingualAvailableLocales: MultilingualAvailableLocales[] = useMemo(\n () =>\n availableLocales.map((localeEl) => {\n const englishName = getLocaleName(localeEl, ENGLISH);\n const currentLocaleName = getLocaleName(localeEl, locale);\n const ownLocaleName = getLocaleName(localeEl);\n return {\n locale: localeEl,\n englishName,\n currentLocaleName,\n ownLocaleName,\n };\n }),\n [availableLocales, locale]\n );\n\n // 2. State for Search Query only (Source of Truth)\n const [searchQuery, setSearchQuery] = useState('');\n\n const [seeAllLocales, setSeeAllLocales] = usePersistedStore(\n 'locale-content-selector-see-all-locales',\n false\n );\n\n // 3. Memoize Fuse instance\n const fuse = useMemo(() => {\n const fuseOptions: IFuseOptions<MultilingualAvailableLocales> = {\n keys: [\n { name: 'ownLocaleName', weight: 0.4 },\n { name: 'englishName', weight: 0.2 },\n { name: 'currentLocaleName', weight: 0.2 },\n { name: 'locale', weight: 0.2 },\n ],\n threshold: 0.02,\n };\n return new Fuse(multilingualAvailableLocales, fuseOptions);\n }, [multilingualAvailableLocales]);\n\n // 4. Derive results from Search Query\n const results = useMemo(() => {\n if (!searchQuery) {\n return multilingualAvailableLocales;\n }\n return fuse.search(searchQuery).map((result) => result.item);\n }, [searchQuery, multilingualAvailableLocales, fuse]);\n\n const handleClickLocale = (localeItem: LocalesValues) => {\n if (isMultilingual) {\n if (selectedLocales.includes(localeItem)) {\n if (selectedLocales.length > 1) {\n setSelectedLocales((prev) => prev.filter((el) => el !== localeItem));\n }\n } else {\n setSelectedLocales((prev) => [...prev, localeItem]);\n }\n } else {\n setSelectedLocales([localeItem]);\n }\n };\n\n const handleSeeAllLocales = (value: boolean) => {\n setSeeAllLocales(value);\n\n if (value) {\n setSelectedLocales(availableLocales);\n } else {\n setSelectedLocales([locale]);\n }\n };\n\n return (\n <div className=\"rounded-xl border border-text text-text transition-colors\">\n <DropDown identifier={DROPDOWN_IDENTIFIER}>\n <DropDown.Trigger\n identifier={DROPDOWN_IDENTIFIER}\n label={localeSwitcherLabel.value}\n className=\"p-0!\"\n roundedSize=\"3xl\"\n color=\"text\"\n variant=\"hoverable\"\n >\n <div className=\"flex w-full items-center justify-between text-text\">\n <div className=\"px-2 py-1\">\n <Globe size={16} />\n </div>\n <MoveVertical className=\"self-center\" size={16} />\n </div>\n </DropDown.Trigger>\n\n <DropDown.Panel\n identifier={DROPDOWN_IDENTIFIER}\n isOverable\n isFocusable\n align=\"end\"\n {...panelProps}\n >\n <Container\n className=\"max-h-[60vh] min-w-28\"\n separator=\"y\"\n role=\"listbox\"\n transparency=\"xs\"\n border\n roundedSize=\"3xl\"\n borderColor=\"text\"\n aria-label={languageListLabel.value}\n >\n {isMultilingual && (\n <div className=\"m-auto p-2\">\n <SwitchSelector\n defaultValue={seeAllLocales} // Ensure this uses the persisted state\n onChange={handleSeeAllLocales}\n color=\"text\"\n size=\"sm\"\n className=\"!w-60\"\n choices={[\n {\n content: seeAllLocalesSwitch.true.value,\n value: true,\n },\n {\n content: seeAllLocalesSwitch.false.value,\n value: false,\n },\n ]}\n />\n </div>\n )}\n\n {!(isMultilingual && seeAllLocales) && (\n <>\n <div className=\"p-3\">\n <Input\n type=\"search\"\n aria-label={searchInput.ariaLabel.value}\n placeholder={searchInput.placeholder.value}\n // Update search query state directly\n onChange={(e) => setSearchQuery(e.target.value)}\n ref={inputRef}\n />\n </div>\n <ol className=\"divide-y divide-dashed divide-text/20 overflow-y-auto p-1\">\n {results.map(\n ({\n locale: localeItem,\n currentLocaleName,\n ownLocaleName,\n }) => (\n <li className=\"px-1.5 py-1\" key={localeItem}>\n <Button\n onClick={() => handleClickLocale(localeItem)}\n label={`${switchTo} ${currentLocaleName}`}\n disabled={\n !(availableLocales ?? availableLocales).includes(\n localeItem\n )\n }\n isActive={selectedLocales.includes(localeItem)}\n variant=\"hoverable\"\n color=\"text\"\n isFullWidth\n textAlign=\"left\"\n size=\"sm\"\n >\n <div className=\"flex flex-row items-center justify-between gap-3 px-2 py-1\">\n {isMultilingual && (\n <div className=\"w-4\">\n {selectedLocales.includes(localeItem) && (\n <Check className=\"size-full\" />\n )}\n </div>\n )}\n <div className=\"flex flex-1 flex-row items-center justify-between gap-3 px-2 py-1\">\n <div className=\"flex flex-col text-nowrap\">\n <span\n dir={getHTMLTextDir(localeItem)}\n lang={localeItem}\n >\n {ownLocaleName}\n </span>\n <span className=\"text-neutral text-xs\">\n {currentLocaleName}\n </span>\n </div>\n <span className=\"text-neutral text-sm\">\n {localeItem.toUpperCase()}\n </span>\n </div>\n </div>\n </Button>\n </li>\n )\n )}\n </ol>\n </>\n )}\n </Container>\n </DropDown.Panel>\n </DropDown>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAsBA,MAAM,sBAAsB;AAS5B,MAAa,yBAAyD,EACpE,YACA,iBAAiB,WACb;CACJ,MAAM,EACJ,UACA,aACA,qBACA,mBACA,wBACE,YAAY,yBAAyB;CACzC,MAAM,WAAW,OAAyB,IAAI;CAC9C,MAAM,EAAE,WAAW,UAAU;CAC7B,MAAM,EAAE,kBAAkB,iBAAiB,uBACzC,yBAAyB;CAG3B,MAAM,+BAA+D,cAEjE,iBAAiB,KAAK,aAAa;EAIjC,OAAO;GACL,QAAQ;GACR,aALkB,cAAc,UAAU,OAKhC;GACV,mBALwB,cAAc,UAAU,MAKhC;GAChB,eALoB,cAAc,QAKtB;EACd;CACF,CAAC,GACH,CAAC,kBAAkB,MAAM,CAC3B;CAGA,MAAM,CAAC,aAAa,kBAAkB,SAAS,EAAE;CAEjD,MAAM,CAAC,eAAe,oBAAoB,kBACxC,2CACA,KACF;CAGA,MAAM,OAAO,cAAc;EAUzB,OAAO,IAAI,KAAK,8BAA8B;GAR5C,MAAM;IACJ;KAAE,MAAM;KAAiB,QAAQ;IAAI;IACrC;KAAE,MAAM;KAAe,QAAQ;IAAI;IACnC;KAAE,MAAM;KAAqB,QAAQ;IAAI;IACzC;KAAE,MAAM;KAAU,QAAQ;IAAI;GAChC;GACA,WAAW;EAE2C,CAAC;CAC3D,GAAG,CAAC,4BAA4B,CAAC;CAGjC,MAAM,UAAU,cAAc;EAC5B,IAAI,CAAC,aACH,OAAO;EAET,OAAO,KAAK,OAAO,WAAW,EAAE,KAAK,WAAW,OAAO,IAAI;CAC7D,GAAG;EAAC;EAAa;EAA8B;CAAI,CAAC;CAEpD,MAAM,qBAAqB,eAA8B;EACvD,IAAI,gBACF,IAAI,gBAAgB,SAAS,UAAU,GACrC;OAAI,gBAAgB,SAAS,GAC3B,oBAAoB,SAAS,KAAK,QAAQ,OAAO,OAAO,UAAU,CAAC;EACrE,OAEA,oBAAoB,SAAS,CAAC,GAAG,MAAM,UAAU,CAAC;OAGpD,mBAAmB,CAAC,UAAU,CAAC;CAEnC;CAEA,MAAM,uBAAuB,UAAmB;EAC9C,iBAAiB,KAAK;EAEtB,IAAI,OACF,mBAAmB,gBAAgB;OAEnC,mBAAmB,CAAC,MAAM,CAAC;CAE/B;CAEA,OACE,oBAAC,OAAD;EAAK,WAAU;YACb,qBAAC,UAAD;GAAU,YAAY;aAAtB,CACE,oBAAC,SAAS,SAAV;IACE,YAAY;IACZ,OAAO,oBAAoB;IAC3B,WAAU;IACV,aAAY;IACZ,OAAM;IACN,SAAQ;cAER,qBAAC,OAAD;KAAK,WAAU;eAAf,CACE,oBAAC,OAAD;MAAK,WAAU;gBACb,oBAAC,OAAD,EAAO,MAAM,GAAK;KACf,IACL,oBAAC,cAAD;MAAc,WAAU;MAAc,MAAM;KAAK,EAC9C;;GACW,IAElB,oBAAC,SAAS,OAAV;IACE,YAAY;IACZ;IACA;IACA,OAAM;IACN,GAAI;cAEJ,qBAAC,WAAD;KACE,WAAU;KACV,WAAU;KACV,MAAK;KACL,cAAa;KACb;KACA,aAAY;KACZ,aAAY;KACZ,cAAY,kBAAkB;eARhC,CAUG,kBACC,oBAAC,OAAD;MAAK,WAAU;gBACb,oBAAC,gBAAD;OACE,cAAc;OACd,UAAU;OACV,OAAM;OACN,MAAK;OACL,WAAU;OACV,SAAS,CACP;QACE,SAAS,oBAAoB,KAAK;QAClC,OAAO;OACT,GACA;QACE,SAAS,oBAAoB,MAAM;QACnC,OAAO;OACT,CACF;MACD;KACE,IAGN,EAAE,kBAAkB,kBACnB,8CACE,oBAAC,OAAD;MAAK,WAAU;gBACb,oBAAC,OAAD;OACE,MAAK;OACL,cAAY,YAAY,UAAU;OAClC,aAAa,YAAY,YAAY;OAErC,WAAW,MAAM,eAAe,EAAE,OAAO,KAAK;OAC9C,KAAK;MACN;KACE,IACL,oBAAC,MAAD;MAAI,WAAU;gBACX,QAAQ,KACN,EACC,QAAQ,YACR,mBACA,oBAEA,oBAAC,MAAD;OAAI,WAAU;iBACZ,oBAAC,QAAD;QACE,eAAe,kBAAkB,UAAU;QAC3C,OAAO,GAAG,SAAS,GAAG;QACtB,UACE,EAAE,oBAAoB,kBAAkB,SACtC,UACF;QAEF,UAAU,gBAAgB,SAAS,UAAU;QAC7C,SAAQ;QACR,OAAM;QACN;QACA,WAAU;QACV,MAAK;kBAEL,qBAAC,OAAD;SAAK,WAAU;mBAAf,CACG,kBACC,oBAAC,OAAD;UAAK,WAAU;oBACZ,gBAAgB,SAAS,UAAU,KAClC,oBAAC,OAAD,EAAO,WAAU,YAAa;SAE7B,IAEP,qBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,qBAAC,OAAD;WAAK,WAAU;qBAAf,CACE,oBAAC,QAAD;YACE,KAAK,eAAe,UAAU;YAC9B,MAAM;sBAEL;WACG,IACN,oBAAC,QAAD;YAAM,WAAU;sBACb;WACG,EACH;cACL,oBAAC,QAAD;WAAM,WAAU;qBACb,WAAW,YAAY;UACpB,EACH;WACF;;OACC;MACN,GA1C6B,UA0C7B,CAER;KACE,EACJ,IAEK;;GACG,EACR;;CACP;AAET"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { Button } from "../Button/Button.mjs";
|
|
3
4
|
import { Container } from "../Container/index.mjs";
|
|
4
|
-
import { Button, ButtonColor, ButtonTextAlign, ButtonVariant } from "../Button/Button.mjs";
|
|
5
5
|
import { DropDown } from "../DropDown/index.mjs";
|
|
6
6
|
import { Input } from "../Input/Input.mjs";
|
|
7
7
|
import { useCallback, useMemo, useRef, useState } from "react";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocaleSwitcher.mjs","names":[],"sources":["../../../../src/components/LocaleSwitcherDropDown/LocaleSwitcher.tsx"],"sourcesContent":["'use client';\n\nimport { getHTMLTextDir, getLocaleName } from '@intlayer/core/localization';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport { ENGLISH } from '@intlayer/types/locales';\nimport Fuse, { type IFuseOptions } from 'fuse.js';\nimport { MoveVertical } from 'lucide-react';\nimport { type FC, useCallback, useMemo, useRef, useState } from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport { Button
|
|
1
|
+
{"version":3,"file":"LocaleSwitcher.mjs","names":[],"sources":["../../../../src/components/LocaleSwitcherDropDown/LocaleSwitcher.tsx"],"sourcesContent":["'use client';\n\nimport { getHTMLTextDir, getLocaleName } from '@intlayer/core/localization';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport { ENGLISH } from '@intlayer/types/locales';\nimport Fuse, { type IFuseOptions } from 'fuse.js';\nimport { MoveVertical } from 'lucide-react';\nimport { type FC, useCallback, useMemo, useRef, useState } from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport { Button } from '../Button';\nimport { Container } from '../Container';\nimport { DropDown, type PanelProps } from '../DropDown';\nimport { Input } from '../Input';\n\nexport type LocaleSwitcherProps = {\n locale?: Locale;\n localeList: Locale[];\n availableLocales?: Locale[];\n fullLocaleName?: boolean;\n setLocale: (locale: Locale) => void;\n panelProps?: Omit<PanelProps, 'identifier'>;\n};\n\nconst DROPDOWN_IDENTIFIER = 'locale-switcher';\n\ntype MultilingualAvailableLocales = {\n locale: Locale;\n englishName: string;\n currentLocaleName: string;\n ownLocaleName: string;\n};\n\nexport const LocaleSwitcher: FC<LocaleSwitcherProps> = ({\n locale,\n localeList,\n availableLocales,\n fullLocaleName = true,\n setLocale,\n panelProps,\n}) => {\n let localeName = 'Select a locale';\n const { switchTo, searchInput, languageListLabel, localeSwitcherLabel } =\n useIntlayer('locale-switcher');\n const inputRef = useRef<HTMLInputElement>(null);\n\n const multilingualAvailableLocales: MultilingualAvailableLocales[] = useMemo(\n () =>\n localeList.map((localeEl) => {\n const englishName = getLocaleName(localeEl, ENGLISH);\n const currentLocaleName = getLocaleName(localeEl, locale);\n const ownLocaleName = getLocaleName(localeEl);\n return {\n locale: localeEl,\n englishName,\n currentLocaleName,\n ownLocaleName,\n };\n }),\n [localeList, locale]\n );\n\n const [results, setResults] = useState<MultilingualAvailableLocales[]>(\n multilingualAvailableLocales\n );\n\n // Create a new Fuse instance with the options and documentation data\n const fuse = useMemo(() => {\n const fuseOptions: IFuseOptions<MultilingualAvailableLocales> = {\n keys: [\n { name: 'ownLocaleName', weight: 0.4 },\n { name: 'englishName', weight: 0.2 },\n { name: 'currentLocaleName', weight: 0.2 },\n { name: 'locale', weight: 0.2 },\n ],\n threshold: 0.02, // Defines how fuzzy the matching should be (lower is more strict)\n };\n\n return new Fuse(multilingualAvailableLocales, fuseOptions);\n }, [multilingualAvailableLocales]);\n\n const handleSearch = useCallback(\n (searchQuery: string) => {\n if (searchQuery) {\n // Perform search on every input change\n const searchResults = fuse\n .search(searchQuery)\n .map((result) => result.item);\n setResults(searchResults);\n } else {\n setResults(multilingualAvailableLocales);\n }\n },\n [fuse, multilingualAvailableLocales]\n );\n\n if (locale) {\n localeName = fullLocaleName ? getLocaleName(locale) : locale.toUpperCase();\n }\n\n return (\n <nav\n className=\"rounded-xl border border-text\"\n aria-label={localeSwitcherLabel.value}\n >\n <DropDown identifier={DROPDOWN_IDENTIFIER}>\n <DropDown.Trigger identifier={DROPDOWN_IDENTIFIER} color=\"text\">\n <div className=\"flex w-full items-center justify-between\">\n <div className=\"text-nowrap px-2\">{localeName}</div>\n <MoveVertical className=\"w-5 self-center\" />\n </div>\n </DropDown.Trigger>\n\n <DropDown.Panel\n identifier={DROPDOWN_IDENTIFIER}\n isOverable\n isFocusable\n align=\"end\"\n {...panelProps}\n >\n <Container\n className=\"max-h-[80vh] min-w-28\"\n separator=\"y\"\n role=\"listbox\"\n transparency=\"xs\"\n aria-label={languageListLabel.value}\n >\n <div className=\"p-3\">\n <Input\n type=\"search\"\n aria-label={searchInput.ariaLabel.value}\n placeholder={searchInput.placeholder.value}\n onChange={(e) => handleSearch(e.target.value)}\n ref={inputRef}\n />\n </div>\n <ol className=\"divide-y divide-dashed divide-text/20 overflow-y-auto p-1\">\n {results.map(\n ({ locale: localeItem, currentLocaleName, ownLocaleName }) => (\n <li className=\"px-1.5 py-1\" key={localeItem}>\n <Button\n onClick={() => setLocale(localeItem)}\n label={`${switchTo} ${currentLocaleName}`}\n disabled={\n !(availableLocales ?? localeList).includes(localeItem)\n }\n isActive={locale === localeItem}\n variant=\"hoverable\"\n color=\"text\"\n isFullWidth\n textAlign=\"left\"\n >\n <div className=\"flex flex-row items-center justify-between gap-3 px-2 py-1\">\n <div className=\"flex flex-col text-nowrap\">\n <span\n dir={getHTMLTextDir(localeItem)}\n lang={localeItem}\n suppressHydrationWarning\n >\n {ownLocaleName}\n </span>\n <span\n className=\"text-neutral text-xs\"\n suppressHydrationWarning\n >\n {currentLocaleName}\n </span>\n </div>\n <span className=\"text-neutral text-sm\">\n {localeItem.toUpperCase()}\n </span>\n </div>\n </Button>\n </li>\n )\n )}\n </ol>\n </Container>\n </DropDown.Panel>\n </DropDown>\n </nav>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;AAuBA,MAAM,sBAAsB;AAS5B,MAAa,kBAA2C,EACtD,QACA,YACA,kBACA,iBAAiB,MACjB,WACA,iBACI;CACJ,IAAI,aAAa;CACjB,MAAM,EAAE,UAAU,aAAa,mBAAmB,wBAChD,YAAY,iBAAiB;CAC/B,MAAM,WAAW,OAAyB,IAAI;CAE9C,MAAM,+BAA+D,cAEjE,WAAW,KAAK,aAAa;EAI3B,OAAO;GACL,QAAQ;GACR,aALkB,cAAc,UAAU,OAKhC;GACV,mBALwB,cAAc,UAAU,MAKhC;GAChB,eALoB,cAAc,QAKtB;EACd;CACF,CAAC,GACH,CAAC,YAAY,MAAM,CACrB;CAEA,MAAM,CAAC,SAAS,cAAc,SAC5B,4BACF;CAGA,MAAM,OAAO,cAAc;EAWzB,OAAO,IAAI,KAAK,8BAA8B;GAT5C,MAAM;IACJ;KAAE,MAAM;KAAiB,QAAQ;IAAI;IACrC;KAAE,MAAM;KAAe,QAAQ;IAAI;IACnC;KAAE,MAAM;KAAqB,QAAQ;IAAI;IACzC;KAAE,MAAM;KAAU,QAAQ;IAAI;GAChC;GACA,WAAW;EAG2C,CAAC;CAC3D,GAAG,CAAC,4BAA4B,CAAC;CAEjC,MAAM,eAAe,aAClB,gBAAwB;EACvB,IAAI,aAKF,WAHsB,KACnB,OAAO,WAAW,EAClB,KAAK,WAAW,OAAO,IACH,CAAC;OAExB,WAAW,4BAA4B;CAE3C,GACA,CAAC,MAAM,4BAA4B,CACrC;CAEA,IAAI,QACF,aAAa,iBAAiB,cAAc,MAAM,IAAI,OAAO,YAAY;CAG3E,OACE,oBAAC,OAAD;EACE,WAAU;EACV,cAAY,oBAAoB;YAEhC,qBAAC,UAAD;GAAU,YAAY;aAAtB,CACE,oBAAC,SAAS,SAAV;IAAkB,YAAY;IAAqB,OAAM;cACvD,qBAAC,OAAD;KAAK,WAAU;eAAf,CACE,oBAAC,OAAD;MAAK,WAAU;gBAAoB;KAAgB,IACnD,oBAAC,cAAD,EAAc,WAAU,kBAAmB,EACxC;;GACW,IAElB,oBAAC,SAAS,OAAV;IACE,YAAY;IACZ;IACA;IACA,OAAM;IACN,GAAI;cAEJ,qBAAC,WAAD;KACE,WAAU;KACV,WAAU;KACV,MAAK;KACL,cAAa;KACb,cAAY,kBAAkB;eALhC,CAOE,oBAAC,OAAD;MAAK,WAAU;gBACb,oBAAC,OAAD;OACE,MAAK;OACL,cAAY,YAAY,UAAU;OAClC,aAAa,YAAY,YAAY;OACrC,WAAW,MAAM,aAAa,EAAE,OAAO,KAAK;OAC5C,KAAK;MACN;KACE,IACL,oBAAC,MAAD;MAAI,WAAU;gBACX,QAAQ,KACN,EAAE,QAAQ,YAAY,mBAAmB,oBACxC,oBAAC,MAAD;OAAI,WAAU;iBACZ,oBAAC,QAAD;QACE,eAAe,UAAU,UAAU;QACnC,OAAO,GAAG,SAAS,GAAG;QACtB,UACE,EAAE,oBAAoB,YAAY,SAAS,UAAU;QAEvD,UAAU,WAAW;QACrB,SAAQ;QACR,OAAM;QACN;QACA,WAAU;kBAEV,qBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,qBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,oBAAC,QAAD;WACE,KAAK,eAAe,UAAU;WAC9B,MAAM;WACN;qBAEC;UACG,IACN,oBAAC,QAAD;WACE,WAAU;WACV;qBAEC;UACG,EACH;aACL,oBAAC,QAAD;UAAM,WAAU;oBACb,WAAW,YAAY;SACpB,EACH;;OACC;MACN,GAlC6B,UAkC7B,CAER;KACE,EACK;;GACG,EACR;;CACP;AAET"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { cn } from "../../utils/cn.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { Button, ButtonSize, ButtonVariant } from "../Button/Button.mjs";
|
|
4
|
+
import { Button } from "../Button/Button.mjs";
|
|
6
5
|
import { Link } from "../Link/Link.mjs";
|
|
7
|
-
import {
|
|
6
|
+
import { Container } from "../Container/index.mjs";
|
|
7
|
+
import { Modal } from "../Modal/Modal.mjs";
|
|
8
8
|
import { useState } from "react";
|
|
9
9
|
import { MoveDiagonal } from "lucide-react";
|
|
10
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkDownIframe.mjs","names":[],"sources":["../../../../src/components/MarkDownRender/MarkDownIframe.tsx"],"sourcesContent":["'use client';\n\nimport { Button
|
|
1
|
+
{"version":3,"file":"MarkDownIframe.mjs","names":[],"sources":["../../../../src/components/MarkDownRender/MarkDownIframe.tsx"],"sourcesContent":["'use client';\n\nimport { Button } from '@components/Button';\nimport { Container } from '@components/Container';\nimport { Link } from '@components/Link';\nimport { Modal } from '@components/Modal';\nimport { cn } from '@utils/cn';\nimport { MoveDiagonal } from 'lucide-react';\nimport { type ComponentProps, type FC, useState } from 'react';\n\nfunction embedLinkMeta(src: string | undefined): {\n href: string;\n label: string;\n} {\n if (!src) return { href: '', label: '' };\n if (/^https?:\\/\\//i.test(src)) {\n try {\n const url = new URL(src);\n return { href: url.href, label: url.host };\n } catch {\n return { href: src, label: src };\n }\n }\n return { href: src, label: src };\n}\n\nexport const MarkDownIframe: FC<ComponentProps<'iframe'>> = (props) => {\n const { src, className, title, ...rest } = props;\n const [isModalOpen, setIsModalOpen] = useState(false);\n const { href, label } = embedLinkMeta(src);\n\n return (\n <Container\n roundedSize=\"2xl\"\n border\n borderColor=\"neutral\"\n className=\"overflow-hidden p-0\"\n gap=\"none\"\n >\n <iframe\n {...rest}\n src={src}\n title={title}\n className={cn(\n 'block max-h-[80vh] min-h-[12rem] w-full border-0',\n className\n )}\n />\n <div className=\"flex items-center justify-between gap-3 px-3 py-1\">\n {href ? (\n <Link\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n label=\"\"\n color=\"neutral\"\n className=\"inline-flex min-w-0 max-w-[calc(100%-3rem)] items-center gap-2 text-neutral text-xs underline-offset-2 hover:text-text hover:underline\"\n >\n {label}\n </Link>\n ) : (\n <span className=\"text-neutral text-sm\">Embedded frame</span>\n )}\n <Button\n variant=\"hoverable\"\n size=\"icon-md\"\n onClick={() => setIsModalOpen(true)}\n label=\"Open embedded page in fullscreen\"\n Icon={MoveDiagonal}\n />\n </div>\n\n <Modal\n isOpen={isModalOpen}\n onClose={() => setIsModalOpen(false)}\n size=\"unset\"\n hasCloseButton\n isScrollable\n padding=\"sm\"\n >\n {isModalOpen && src ? (\n <Container\n roundedSize=\"2xl\"\n border\n borderColor=\"neutral\"\n className=\"overflow-hidden p-0\"\n gap=\"none\"\n >\n <iframe\n {...rest}\n src={src}\n title={title ?? 'Embedded content'}\n allowFullScreen\n className=\"block min-h-[82vh] w-full border-0\"\n />\n </Container>\n ) : null}\n </Modal>\n </Container>\n );\n};\n"],"mappings":";;;;;;;;;;;;AAUA,SAAS,cAAc,KAGrB;CACA,IAAI,CAAC,KAAK,OAAO;EAAE,MAAM;EAAI,OAAO;CAAG;CACvC,IAAI,gBAAgB,KAAK,GAAG,GAC1B,IAAI;EACF,MAAM,MAAM,IAAI,IAAI,GAAG;EACvB,OAAO;GAAE,MAAM,IAAI;GAAM,OAAO,IAAI;EAAK;CAC3C,QAAQ;EACN,OAAO;GAAE,MAAM;GAAK,OAAO;EAAI;CACjC;CAEF,OAAO;EAAE,MAAM;EAAK,OAAO;CAAI;AACjC;AAEA,MAAa,kBAAgD,UAAU;CACrE,MAAM,EAAE,KAAK,WAAW,OAAO,GAAG,SAAS;CAC3C,MAAM,CAAC,aAAa,kBAAkB,SAAS,KAAK;CACpD,MAAM,EAAE,MAAM,UAAU,cAAc,GAAG;CAEzC,OACE,qBAAC,WAAD;EACE,aAAY;EACZ;EACA,aAAY;EACZ,WAAU;EACV,KAAI;YALN;GAOE,oBAAC,UAAD;IACE,GAAI;IACC;IACE;IACP,WAAW,GACT,oDACA,SACF;GACD;GACD,qBAAC,OAAD;IAAK,WAAU;cAAf,CACG,OACC,oBAAC,MAAD;KACQ;KACN,QAAO;KACP,KAAI;KACJ,OAAM;KACN,OAAM;KACN,WAAU;eAET;IACG,KAEN,oBAAC,QAAD;KAAM,WAAU;eAAuB;IAAoB,IAE7D,oBAAC,QAAD;KACE,SAAQ;KACR,MAAK;KACL,eAAe,eAAe,IAAI;KAClC,OAAM;KACN,MAAM;IACP,EACE;;GAEL,oBAAC,OAAD;IACE,QAAQ;IACR,eAAe,eAAe,KAAK;IACnC,MAAK;IACL;IACA;IACA,SAAQ;cAEP,eAAe,MACd,oBAAC,WAAD;KACE,aAAY;KACZ;KACA,aAAY;KACZ,WAAU;KACV,KAAI;eAEJ,oBAAC,UAAD;MACE,GAAI;MACC;MACL,OAAO,SAAS;MAChB;MACA,WAAU;KACX;IACQ,KACT;GACC;EACE;;AAEf"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { cn } from "../../utils/cn.mjs";
|
|
4
|
-
import { Container } from "../Container/index.mjs";
|
|
5
|
-
import { Button, ButtonColor, ButtonSize, ButtonVariant } from "../Button/Button.mjs";
|
|
6
3
|
import { useGetElementOrWindow } from "../../hooks/useGetElementOrWindow.mjs";
|
|
7
4
|
import { useScrollBlockage } from "../../hooks/useScrollBlockage/index.mjs";
|
|
5
|
+
import { cn } from "../../utils/cn.mjs";
|
|
6
|
+
import { Button } from "../Button/Button.mjs";
|
|
7
|
+
import { Container } from "../Container/index.mjs";
|
|
8
8
|
import { H3 } from "../Headers/index.mjs";
|
|
9
9
|
import { useEffect } from "react";
|
|
10
10
|
import { cva } from "class-variance-authority";
|
|
@@ -14,17 +14,6 @@ import { motion } from "framer-motion";
|
|
|
14
14
|
import { createPortal } from "react-dom";
|
|
15
15
|
|
|
16
16
|
//#region src/components/Modal/Modal.tsx
|
|
17
|
-
/**
|
|
18
|
-
* Enumeration of available modal sizes
|
|
19
|
-
*/
|
|
20
|
-
let ModalSize = /* @__PURE__ */ function(ModalSize) {
|
|
21
|
-
ModalSize["SM"] = "sm";
|
|
22
|
-
ModalSize["MD"] = "md";
|
|
23
|
-
ModalSize["LG"] = "lg";
|
|
24
|
-
ModalSize["XL"] = "xl";
|
|
25
|
-
ModalSize["UNSET"] = "unset";
|
|
26
|
-
return ModalSize;
|
|
27
|
-
}({});
|
|
28
17
|
const modalVariants = cva("flex cursor-default flex-col overflow-hidden shadow-sm", {
|
|
29
18
|
variants: { size: {
|
|
30
19
|
sm: "h-auto max-h-[30vh] w-[95vw] max-w-xl",
|
|
@@ -77,7 +66,7 @@ const MotionModal = motion.create(Container);
|
|
|
77
66
|
* onClose={onClose}
|
|
78
67
|
* title="Confirm Action"
|
|
79
68
|
* hasCloseButton
|
|
80
|
-
* size=
|
|
69
|
+
* size="lg"
|
|
81
70
|
* >
|
|
82
71
|
* <div>
|
|
83
72
|
* <p>Are you sure you want to continue?</p>
|
|
@@ -198,5 +187,5 @@ const Modal = ({ children, isOpen, container, onClose, hasCloseButton = false, t
|
|
|
198
187
|
};
|
|
199
188
|
|
|
200
189
|
//#endregion
|
|
201
|
-
export { Modal
|
|
190
|
+
export { Modal };
|
|
202
191
|
//# sourceMappingURL=Modal.mjs.map
|