@intlayer/design-system 8.9.7 → 8.10.0-canary.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/components/Accordion/Accordion.mjs.map +1 -1
- package/dist/esm/components/Avatar/image.mjs.map +1 -1
- package/dist/esm/components/Avatar/index.mjs +5 -5
- package/dist/esm/components/Avatar/index.mjs.map +1 -1
- package/dist/esm/components/Badge/index.mjs.map +1 -1
- package/dist/esm/components/Breadcrumb/breadcrumb.content.mjs.map +1 -1
- package/dist/esm/components/Breadcrumb/index.mjs.map +1 -1
- package/dist/esm/components/Browser/Browser.content.mjs +120 -0
- package/dist/esm/components/Browser/Browser.content.mjs.map +1 -1
- package/dist/esm/components/Browser/Browser.mjs +131 -9
- package/dist/esm/components/Browser/Browser.mjs.map +1 -1
- package/dist/esm/components/Browser/extractUrlFromSitemap.mjs +44 -0
- package/dist/esm/components/Browser/extractUrlFromSitemap.mjs.map +1 -0
- package/dist/esm/components/Button/Button.mjs +7 -4
- package/dist/esm/components/Button/Button.mjs.map +1 -1
- package/dist/esm/components/Carousel/index.content.mjs.map +1 -1
- package/dist/esm/components/Carousel/index.mjs.map +1 -1
- package/dist/esm/components/ClickOutsideDiv/index.mjs.map +1 -1
- package/dist/esm/components/CollapsibleTable/CollapsibleTable.mjs +1 -1
- package/dist/esm/components/CollapsibleTable/CollapsibleTable.mjs.map +1 -1
- package/dist/esm/components/Command/index.mjs.map +1 -1
- package/dist/esm/components/Container/index.mjs +1 -1
- package/dist/esm/components/Container/index.mjs.map +1 -1
- package/dist/esm/components/ContentEditor/ContentEditor.mjs.map +1 -1
- package/dist/esm/components/ContentEditor/ContentEditorInput.mjs.map +1 -1
- package/dist/esm/components/ContentEditor/ContentEditorTextArea.mjs +1 -1
- package/dist/esm/components/ContentEditor/ContentEditorTextArea.mjs.map +1 -1
- package/dist/esm/components/ContentSelector/ContentSelector.mjs.map +1 -1
- package/dist/esm/components/CopyButton/CopyButton.content.mjs.map +1 -1
- package/dist/esm/components/CopyButton/index.mjs.map +1 -1
- package/dist/esm/components/CopyToClipboard/index.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/DictionaryEditor.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/ItemLayout.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/ArrayWrapper.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/BooleanWrapper.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/ConditionWrapper.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/EnumerationWrapper.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/FileWrapper.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/HtmlWrapper.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/InsertionWrapper.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/MarkdownWrapper.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/NestedObjectWrapper.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/NumberWrapper.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/PluralWrapper.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/StringWrapper.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/TranslationWrapper.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/index.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/ContentEditor.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/SafeHtmlRenderer.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/TextEditor.mjs +51 -3
- package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/TextEditor.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/object.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryCreationForm/DictionaryCreationForm.mjs +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryCreationForm/DictionaryCreationForm.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryCreationForm/dictionaryCreationForm.content.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryCreationForm/useDictionaryFormSchema.content.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryCreationForm/useDictionaryFormSchema.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/DictionaryDetailsForm.mjs +3 -3
- package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/DictionaryDetailsForm.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/dictionaryDetails.content.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/useDictionaryDetailsSchema.content.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/useDictionaryDetailsSchema.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryFieldEditor.mjs +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryFieldEditor.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/EnumKeyInput.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/JSONEditor.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/KeyPathBreadcrumb.mjs +1 -1
- package/dist/esm/components/DictionaryFieldEditor/KeyPathBreadcrumb.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs +4 -4
- package/dist/esm/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/NavigationView/navigationViewNode.content.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/NodeTypeSelector.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs +2 -2
- package/dist/esm/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/SaveForm/saveForm.content.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/StructureEditor.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/StructureView/StructureView.mjs +1 -1
- package/dist/esm/components/DictionaryFieldEditor/StructureView/StructureView.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/StructureView/structureView.content.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/VersionSwitcherDropDown/VersionSwitcher.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/VersionSwitcherDropDown/VersionSwitcherContext.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/VersionSwitcherDropDown/versionSwitcherDropDown.content.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/dictionaryFieldEditor.content.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/getIsEditableSection.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/nodeTypeSelector.content.mjs.map +1 -1
- package/dist/esm/components/DropDown/index.mjs.map +1 -1
- package/dist/esm/components/EditableField/EditableFieldInput.mjs.map +1 -1
- package/dist/esm/components/EditableField/EditableFieldLayout.mjs.map +1 -1
- package/dist/esm/components/EditableField/EditableFieldTextArea.mjs.map +1 -1
- package/dist/esm/components/ExpandCollapse/ExpandCollapse.mjs.map +1 -1
- package/dist/esm/components/ExpandCollapse/expandCollapse.content.mjs.map +1 -1
- package/dist/esm/components/Flags/Flag.mjs.map +1 -1
- package/dist/esm/components/Flags/ae.mjs.map +1 -1
- package/dist/esm/components/Flags/af.mjs.map +1 -1
- package/dist/esm/components/Flags/al.mjs.map +1 -1
- package/dist/esm/components/Flags/am.mjs.map +1 -1
- package/dist/esm/components/Flags/ar.mjs.map +1 -1
- package/dist/esm/components/Flags/at.mjs.map +1 -1
- package/dist/esm/components/Flags/au.mjs.map +1 -1
- package/dist/esm/components/Flags/az.mjs.map +1 -1
- package/dist/esm/components/Flags/ba.mjs.map +1 -1
- package/dist/esm/components/Flags/bd.mjs.map +1 -1
- package/dist/esm/components/Flags/be.mjs.map +1 -1
- package/dist/esm/components/Flags/bg.mjs.map +1 -1
- package/dist/esm/components/Flags/bh.mjs.map +1 -1
- package/dist/esm/components/Flags/bn.mjs.map +1 -1
- package/dist/esm/components/Flags/bo.mjs.map +1 -1
- package/dist/esm/components/Flags/br.mjs.map +1 -1
- package/dist/esm/components/Flags/bw.mjs.map +1 -1
- package/dist/esm/components/Flags/by.mjs.map +1 -1
- package/dist/esm/components/Flags/bz.mjs.map +1 -1
- package/dist/esm/components/Flags/ca.mjs.map +1 -1
- package/dist/esm/components/Flags/ch.mjs.map +1 -1
- package/dist/esm/components/Flags/cl.mjs.map +1 -1
- package/dist/esm/components/Flags/cn.mjs.map +1 -1
- package/dist/esm/components/Flags/co.mjs.map +1 -1
- package/dist/esm/components/Flags/cr.mjs.map +1 -1
- package/dist/esm/components/Flags/cu.mjs.map +1 -1
- package/dist/esm/components/Flags/cv.mjs.map +1 -1
- package/dist/esm/components/Flags/cz.mjs.map +1 -1
- package/dist/esm/components/Flags/de.mjs.map +1 -1
- package/dist/esm/components/Flags/dj.mjs.map +1 -1
- package/dist/esm/components/Flags/dk.mjs.map +1 -1
- package/dist/esm/components/Flags/do.mjs.map +1 -1
- package/dist/esm/components/Flags/dz.mjs.map +1 -1
- package/dist/esm/components/Flags/ec.mjs.map +1 -1
- package/dist/esm/components/Flags/ee.mjs.map +1 -1
- package/dist/esm/components/Flags/eg.mjs.map +1 -1
- package/dist/esm/components/Flags/es-ct.mjs.map +1 -1
- package/dist/esm/components/Flags/es-ga.mjs.map +1 -1
- package/dist/esm/components/Flags/es-pv.mjs.map +1 -1
- package/dist/esm/components/Flags/es.mjs.map +1 -1
- package/dist/esm/components/Flags/et.mjs.map +1 -1
- package/dist/esm/components/Flags/fi.mjs.map +1 -1
- package/dist/esm/components/Flags/flags.mjs.map +1 -1
- package/dist/esm/components/Flags/fo.mjs.map +1 -1
- package/dist/esm/components/Flags/fr.mjs.map +1 -1
- package/dist/esm/components/Flags/gb-wls.mjs.map +1 -1
- package/dist/esm/components/Flags/gb.mjs.map +1 -1
- package/dist/esm/components/Flags/ge.mjs.map +1 -1
- package/dist/esm/components/Flags/gh.mjs.map +1 -1
- package/dist/esm/components/Flags/gr.mjs.map +1 -1
- package/dist/esm/components/Flags/gt.mjs.map +1 -1
- package/dist/esm/components/Flags/gw.mjs.map +1 -1
- package/dist/esm/components/Flags/hk.mjs.map +1 -1
- package/dist/esm/components/Flags/hn.mjs.map +1 -1
- package/dist/esm/components/Flags/hr.mjs.map +1 -1
- package/dist/esm/components/Flags/hu.mjs.map +1 -1
- package/dist/esm/components/Flags/id.mjs.map +1 -1
- package/dist/esm/components/Flags/ie.mjs.map +1 -1
- package/dist/esm/components/Flags/il.mjs.map +1 -1
- package/dist/esm/components/Flags/in.mjs.map +1 -1
- package/dist/esm/components/Flags/iq.mjs.map +1 -1
- package/dist/esm/components/Flags/ir.mjs.map +1 -1
- package/dist/esm/components/Flags/is.mjs.map +1 -1
- package/dist/esm/components/Flags/it.mjs.map +1 -1
- package/dist/esm/components/Flags/jm.mjs.map +1 -1
- package/dist/esm/components/Flags/jo.mjs.map +1 -1
- package/dist/esm/components/Flags/jp.mjs.map +1 -1
- package/dist/esm/components/Flags/ke.mjs.map +1 -1
- package/dist/esm/components/Flags/kg.mjs.map +1 -1
- package/dist/esm/components/Flags/kh.mjs.map +1 -1
- package/dist/esm/components/Flags/km.mjs.map +1 -1
- package/dist/esm/components/Flags/kr.mjs.map +1 -1
- package/dist/esm/components/Flags/kw.mjs.map +1 -1
- package/dist/esm/components/Flags/kz.mjs.map +1 -1
- package/dist/esm/components/Flags/la.mjs.map +1 -1
- package/dist/esm/components/Flags/lb.mjs.map +1 -1
- package/dist/esm/components/Flags/li.mjs.map +1 -1
- package/dist/esm/components/Flags/lk.mjs.map +1 -1
- package/dist/esm/components/Flags/lt.mjs.map +1 -1
- package/dist/esm/components/Flags/lu.mjs.map +1 -1
- package/dist/esm/components/Flags/lv.mjs.map +1 -1
- package/dist/esm/components/Flags/ly.mjs.map +1 -1
- package/dist/esm/components/Flags/ma.mjs.map +1 -1
- package/dist/esm/components/Flags/mc.mjs.map +1 -1
- package/dist/esm/components/Flags/md.mjs.map +1 -1
- package/dist/esm/components/Flags/mk.mjs.map +1 -1
- package/dist/esm/components/Flags/mm.mjs.map +1 -1
- package/dist/esm/components/Flags/mn.mjs.map +1 -1
- package/dist/esm/components/Flags/mo.mjs.map +1 -1
- package/dist/esm/components/Flags/mr.mjs.map +1 -1
- package/dist/esm/components/Flags/mt.mjs.map +1 -1
- package/dist/esm/components/Flags/mv.mjs.map +1 -1
- package/dist/esm/components/Flags/mx.mjs.map +1 -1
- package/dist/esm/components/Flags/my.mjs.map +1 -1
- package/dist/esm/components/Flags/mz.mjs.map +1 -1
- package/dist/esm/components/Flags/ng.mjs.map +1 -1
- package/dist/esm/components/Flags/ni.mjs.map +1 -1
- package/dist/esm/components/Flags/nl.mjs.map +1 -1
- package/dist/esm/components/Flags/no.mjs.map +1 -1
- package/dist/esm/components/Flags/np.mjs.map +1 -1
- package/dist/esm/components/Flags/nz.mjs.map +1 -1
- package/dist/esm/components/Flags/om.mjs.map +1 -1
- package/dist/esm/components/Flags/pa.mjs.map +1 -1
- package/dist/esm/components/Flags/pe.mjs.map +1 -1
- package/dist/esm/components/Flags/ph.mjs.map +1 -1
- package/dist/esm/components/Flags/pk.mjs.map +1 -1
- package/dist/esm/components/Flags/pl.mjs.map +1 -1
- package/dist/esm/components/Flags/pr.mjs.map +1 -1
- package/dist/esm/components/Flags/ps.mjs.map +1 -1
- package/dist/esm/components/Flags/pt.mjs.map +1 -1
- package/dist/esm/components/Flags/py.mjs.map +1 -1
- package/dist/esm/components/Flags/qa.mjs.map +1 -1
- package/dist/esm/components/Flags/ro.mjs.map +1 -1
- package/dist/esm/components/Flags/rs.mjs.map +1 -1
- package/dist/esm/components/Flags/ru.mjs.map +1 -1
- package/dist/esm/components/Flags/sa.mjs.map +1 -1
- package/dist/esm/components/Flags/sd.mjs.map +1 -1
- package/dist/esm/components/Flags/se.mjs.map +1 -1
- package/dist/esm/components/Flags/sg.mjs.map +1 -1
- package/dist/esm/components/Flags/si.mjs.map +1 -1
- package/dist/esm/components/Flags/sk.mjs.map +1 -1
- package/dist/esm/components/Flags/so.mjs.map +1 -1
- package/dist/esm/components/Flags/st.mjs.map +1 -1
- package/dist/esm/components/Flags/sv.mjs.map +1 -1
- package/dist/esm/components/Flags/sy.mjs.map +1 -1
- package/dist/esm/components/Flags/td.mjs.map +1 -1
- package/dist/esm/components/Flags/th.mjs.map +1 -1
- package/dist/esm/components/Flags/tl.mjs.map +1 -1
- package/dist/esm/components/Flags/tn.mjs.map +1 -1
- package/dist/esm/components/Flags/tr.mjs.map +1 -1
- package/dist/esm/components/Flags/tt.mjs.map +1 -1
- package/dist/esm/components/Flags/tw.mjs.map +1 -1
- package/dist/esm/components/Flags/tz.mjs.map +1 -1
- package/dist/esm/components/Flags/ua.mjs.map +1 -1
- package/dist/esm/components/Flags/ug.mjs.map +1 -1
- package/dist/esm/components/Flags/us.mjs.map +1 -1
- package/dist/esm/components/Flags/uy.mjs.map +1 -1
- package/dist/esm/components/Flags/uz.mjs.map +1 -1
- package/dist/esm/components/Flags/ve.mjs.map +1 -1
- package/dist/esm/components/Flags/vn.mjs.map +1 -1
- package/dist/esm/components/Flags/xx.mjs.map +1 -1
- package/dist/esm/components/Flags/ye.mjs.map +1 -1
- package/dist/esm/components/Flags/za.mjs.map +1 -1
- package/dist/esm/components/Flags/zw.mjs.map +1 -1
- package/dist/esm/components/Footer/index.mjs.map +1 -1
- package/dist/esm/components/Form/FormBase.mjs.map +1 -1
- package/dist/esm/components/Form/FormControl.mjs.map +1 -1
- package/dist/esm/components/Form/FormDescription.mjs.map +1 -1
- package/dist/esm/components/Form/FormField.mjs.map +1 -1
- package/dist/esm/components/Form/FormItem.mjs.map +1 -1
- package/dist/esm/components/Form/FormLabel.mjs.map +1 -1
- package/dist/esm/components/Form/FormMessage.mjs.map +1 -1
- package/dist/esm/components/Form/elements/AutoSizeTextAreaElement.mjs.map +1 -1
- package/dist/esm/components/Form/elements/CheckboxElement.mjs.map +1 -1
- package/dist/esm/components/Form/elements/EditableFieldInputElement.mjs.map +1 -1
- package/dist/esm/components/Form/elements/EditableFieldTextAreaElement.mjs.map +1 -1
- package/dist/esm/components/Form/elements/FormElement.mjs.map +1 -1
- package/dist/esm/components/Form/elements/FormElementWrapper.mjs.map +1 -1
- package/dist/esm/components/Form/elements/InputElement.mjs.map +1 -1
- package/dist/esm/components/Form/elements/InputPasswordElement.mjs.map +1 -1
- package/dist/esm/components/Form/elements/MultiselectElement.mjs.map +1 -1
- package/dist/esm/components/Form/elements/OTPElement.mjs +1 -1
- package/dist/esm/components/Form/elements/OTPElement.mjs.map +1 -1
- package/dist/esm/components/Form/elements/SearchInputElement.mjs.map +1 -1
- package/dist/esm/components/Form/elements/SelectElement.mjs.map +1 -1
- package/dist/esm/components/Form/elements/SwitchSelectorElement.mjs.map +1 -1
- package/dist/esm/components/Form/elements/TextAreaElement.mjs.map +1 -1
- package/dist/esm/components/Form/layout/FormItemLayout.mjs.map +1 -1
- package/dist/esm/components/Form/layout/FormLabelLayout.mjs.map +1 -1
- package/dist/esm/components/Form/layout/RequiredStar.mjs.map +1 -1
- package/dist/esm/components/HTMLRender/HTMLRender.mjs.map +1 -1
- package/dist/esm/components/Headers/index.mjs.map +1 -1
- package/dist/esm/components/HeightResizer/index.mjs.map +1 -1
- package/dist/esm/components/HideShow/index.mjs.map +1 -1
- package/dist/esm/components/IDE/Code.mjs.map +1 -1
- package/dist/esm/components/IDE/CodeBlockClient.mjs.map +1 -1
- package/dist/esm/components/IDE/CodeBlockHighlight.mjs.map +1 -1
- package/dist/esm/components/IDE/CodeBlockServer.mjs.map +1 -1
- package/dist/esm/components/IDE/CodeBlockShiki.mjs.map +1 -1
- package/dist/esm/components/IDE/CodeConditionalRenderer.mjs.map +1 -1
- package/dist/esm/components/IDE/CodeContext.mjs.map +1 -1
- package/dist/esm/components/IDE/CodeFormatSelector.mjs.map +1 -1
- package/dist/esm/components/IDE/ContentDeclarationFormatSelector.mjs.map +1 -1
- package/dist/esm/components/IDE/CopyCode.mjs.map +1 -1
- package/dist/esm/components/IDE/FileList.mjs.map +1 -1
- package/dist/esm/components/IDE/FileTree.mjs.map +1 -1
- package/dist/esm/components/IDE/IDE.mjs.map +1 -1
- package/dist/esm/components/IDE/MarkDownRender.mjs.map +1 -1
- package/dist/esm/components/IDE/MonacoCode.mjs.map +1 -1
- package/dist/esm/components/IDE/PackageManagerSelector.mjs.map +1 -1
- package/dist/esm/components/IDE/code.content.mjs.map +1 -1
- package/dist/esm/components/IDE/codeTransformer.mjs.map +1 -1
- package/dist/esm/components/IDE/copyCode.content.mjs.map +1 -1
- package/dist/esm/components/IDE/createFileTree.mjs.map +1 -1
- package/dist/esm/components/IDE/selectors.content.mjs.map +1 -1
- package/dist/esm/components/InformationTag/index.mjs.map +1 -1
- package/dist/esm/components/Input/Checkbox.mjs.map +1 -1
- package/dist/esm/components/Input/Input.mjs.map +1 -1
- package/dist/esm/components/Input/InputPassword.mjs.map +1 -1
- package/dist/esm/components/Input/OTPInput.mjs.map +1 -1
- package/dist/esm/components/Input/SearchInput.mjs.map +1 -1
- package/dist/esm/components/KeyboardScreenAdapter/index.mjs.map +1 -1
- package/dist/esm/components/KeyboardShortcut/KeyboardShortcut.mjs.map +1 -1
- package/dist/esm/components/Label/index.mjs.map +1 -1
- package/dist/esm/components/LanguageBackground/index.mjs.map +1 -1
- package/dist/esm/components/Link/Link.mjs +3 -2
- package/dist/esm/components/Link/Link.mjs.map +1 -1
- package/dist/esm/components/Loader/index.content.mjs.map +1 -1
- package/dist/esm/components/Loader/index.mjs.map +1 -1
- package/dist/esm/components/Loader/spinner.mjs.map +1 -1
- package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.mjs +2 -2
- package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.mjs.map +1 -1
- package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContentContext.mjs +8 -1
- package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContentContext.mjs.map +1 -1
- package/dist/esm/components/LocaleSwitcherContentDropDown/localeSwitcher.content.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/LocaleSwitcherDropDown/localeSwitcher.content.mjs.map +1 -1
- package/dist/esm/components/Logo/Logo.mjs.map +1 -1
- package/dist/esm/components/Logo/LogoTextOnly.mjs.map +1 -1
- package/dist/esm/components/Logo/LogoWithText.mjs.map +1 -1
- package/dist/esm/components/Logo/LogoWithTextBelow.mjs.map +1 -1
- package/dist/esm/components/MarkDownRender/MarkDownIframe.mjs.map +1 -1
- package/dist/esm/components/MarkDownRender/MarkDownRender.mjs.map +1 -1
- package/dist/esm/components/MaxHeightSmoother/index.mjs.map +1 -1
- package/dist/esm/components/MaxWidthSmoother/index.mjs.map +1 -1
- package/dist/esm/components/Modal/Modal.mjs +2 -2
- package/dist/esm/components/Modal/Modal.mjs.map +1 -1
- package/dist/esm/components/Navbar/Burger.mjs.map +1 -1
- package/dist/esm/components/Navbar/DesktopNavbar.mjs.map +1 -1
- package/dist/esm/components/Navbar/MobileNavbar.mjs +1 -1
- package/dist/esm/components/Navbar/MobileNavbar.mjs.map +1 -1
- package/dist/esm/components/Navbar/index.mjs.map +1 -1
- package/dist/esm/components/Navbar/useNavigation.mjs.map +1 -1
- package/dist/esm/components/Pagination/NumberItemsSelector.mjs.map +1 -1
- package/dist/esm/components/Pagination/Pagination.mjs +1 -1
- package/dist/esm/components/Pagination/Pagination.mjs.map +1 -1
- package/dist/esm/components/Pagination/ShowingResultsNumberItems.mjs.map +1 -1
- package/dist/esm/components/Pagination/pagination.content.mjs.map +1 -1
- package/dist/esm/components/Pattern/DotPattern.mjs.map +1 -1
- package/dist/esm/components/Pattern/GridPattern.mjs.map +1 -1
- package/dist/esm/components/Pattern/SpotLight.mjs.map +1 -1
- package/dist/esm/components/Popover/dynamic.mjs.map +1 -1
- package/dist/esm/components/Popover/static.mjs.map +1 -1
- package/dist/esm/components/PressableSpan/PressableSpan.mjs.map +1 -1
- package/dist/esm/components/RightDrawer/RightDrawer.mjs +3 -3
- package/dist/esm/components/RightDrawer/RightDrawer.mjs.map +1 -1
- package/dist/esm/components/RightDrawer/isElementAtTopAndNotCovered.mjs.map +1 -1
- package/dist/esm/components/RightDrawer/rightDrawer.content.mjs.map +1 -1
- package/dist/esm/components/RightDrawer/useRightDrawer.mjs.map +1 -1
- package/dist/esm/components/Select/Multiselect.mjs.map +1 -1
- package/dist/esm/components/Select/Select.mjs.map +1 -1
- package/dist/esm/components/SocialNetworks/DiscordLogo.mjs.map +1 -1
- package/dist/esm/components/SocialNetworks/FacebookLogo.mjs.map +1 -1
- package/dist/esm/components/SocialNetworks/InstagramLogo.mjs.map +1 -1
- package/dist/esm/components/SocialNetworks/ProductHuntLogo.mjs.map +1 -1
- package/dist/esm/components/SocialNetworks/TiktokLogo.mjs.map +1 -1
- package/dist/esm/components/SocialNetworks/XLogo.mjs.map +1 -1
- package/dist/esm/components/SocialNetworks/YoutubeLogo.mjs.map +1 -1
- package/dist/esm/components/SocialNetworks/index.mjs.map +1 -1
- package/dist/esm/components/SwitchSelector/SwitchSelector.mjs +2 -0
- package/dist/esm/components/SwitchSelector/SwitchSelector.mjs.map +1 -1
- package/dist/esm/components/SwitchSelector/VerticalSwitchSelector.mjs.map +1 -1
- package/dist/esm/components/SwitchSelector/useSwitchSelector.mjs.map +1 -1
- package/dist/esm/components/Tab/Tab.mjs +1 -1
- package/dist/esm/components/Tab/Tab.mjs.map +1 -1
- package/dist/esm/components/Tab/TabContext.mjs.map +1 -1
- package/dist/esm/components/TabSelector/TabSelector.mjs.map +1 -1
- package/dist/esm/components/Table/ExpandButton.mjs.map +1 -1
- package/dist/esm/components/Table/SmartTable.mjs.map +1 -1
- package/dist/esm/components/Table/Table.mjs.map +1 -1
- package/dist/esm/components/Table/TableElements.mjs.map +1 -1
- package/dist/esm/components/Table/table.content.mjs.map +1 -1
- package/dist/esm/components/Table/useTableWidths.mjs.map +1 -1
- package/dist/esm/components/Tag/index.mjs.map +1 -1
- package/dist/esm/components/TechLogo/TechLogo.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Adonis.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Angular.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Anthropic.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Astro.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Atlassian.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Bitbucket.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/ChatGPT.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Claude.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/DeepSeek.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Express.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Fastify.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Gemini.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/GitHub.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/GitLab.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Google.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/GoogleAI.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Grok.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Hono.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/LinkedIn.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Lit.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Lynx.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Microsoft.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Mistral.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/NestJS.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Nextjs.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Node.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Nuxt.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Ollama.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/OpenAI.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Perplexity.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Preact.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Reactjs.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Solid.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Svelte.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Tanstack.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Vanilla.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Vitejs.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/Vuejs.mjs.map +1 -1
- package/dist/esm/components/TechLogo/types.mjs.map +1 -1
- package/dist/esm/components/Terminal/Terminal.mjs.map +1 -1
- package/dist/esm/components/Terminal/terminal.content.mjs.map +1 -1
- package/dist/esm/components/TextArea/AutoSizeTextArea.mjs.map +1 -1
- package/dist/esm/components/TextArea/AutocompleteTextArea.mjs.map +1 -1
- package/dist/esm/components/TextArea/ContentEditableTextArea.mjs.map +1 -1
- package/dist/esm/components/TextArea/TextArea.mjs.map +1 -1
- package/dist/esm/components/ThemeSwitcherDropDown/DesktopThemeSwitcher.mjs.map +1 -1
- package/dist/esm/components/ThemeSwitcherDropDown/MobileThemeSwitcher.mjs.map +1 -1
- package/dist/esm/components/ThemeSwitcherDropDown/types.mjs.map +1 -1
- package/dist/esm/components/Toaster/Toast.mjs.map +1 -1
- package/dist/esm/components/Toaster/Toaster.mjs.map +1 -1
- package/dist/esm/components/Toaster/useToast.mjs.map +1 -1
- package/dist/esm/components/WithResizer/index.mjs +27 -10
- package/dist/esm/components/WithResizer/index.mjs.map +1 -1
- package/dist/esm/components/index.mjs +2 -2
- package/dist/esm/hooks/index.mjs +11 -11
- package/dist/esm/hooks/reactQuery.mjs +9 -1
- package/dist/esm/hooks/reactQuery.mjs.map +1 -1
- package/dist/esm/hooks/useAuth/useAuth.mjs.map +1 -1
- package/dist/esm/hooks/useAuth/useOAuth2.mjs.map +1 -1
- package/dist/esm/hooks/useAuth/useSession.mjs.map +1 -1
- package/dist/esm/hooks/useDevice.mjs.map +1 -1
- package/dist/esm/hooks/useGetElementById.mjs.map +1 -1
- package/dist/esm/hooks/useGetElementOrWindow.mjs.map +1 -1
- package/dist/esm/hooks/useHorizontalSwipe.mjs.map +1 -1
- package/dist/esm/hooks/useIntlayerAPI.mjs.map +1 -1
- package/dist/esm/hooks/useIsDarkMode.mjs.map +1 -1
- package/dist/esm/hooks/useIsMounted.mjs.map +1 -1
- package/dist/esm/hooks/useItemSelector.mjs.map +1 -1
- package/dist/esm/hooks/useKeyboardDetector.mjs.map +1 -1
- package/dist/esm/hooks/usePersistedStore.mjs.map +1 -1
- package/dist/esm/hooks/useScreenWidth.mjs.map +1 -1
- package/dist/esm/hooks/useScrollBlockage/index.mjs.map +1 -1
- package/dist/esm/hooks/useScrollBlockage/useScrollBlockageStore.mjs.map +1 -1
- package/dist/esm/hooks/useScrollDetection.mjs.map +1 -1
- package/dist/esm/hooks/useScrollY.mjs.map +1 -1
- package/dist/esm/hooks/useSearch.mjs.map +1 -1
- package/dist/esm/hooks/useUser/index.mjs.map +1 -1
- package/dist/esm/libs/auth.mjs.map +1 -1
- package/dist/esm/providers/ReactQueryProvider.mjs.map +1 -1
- package/dist/esm/tailwind.config.mjs.map +1 -1
- package/dist/esm/utils/cn.mjs.map +1 -1
- package/dist/types/components/Accordion/Accordion.d.ts.map +1 -1
- package/dist/types/components/Avatar/image.d.ts.map +1 -1
- package/dist/types/components/Avatar/index.d.ts +2 -0
- package/dist/types/components/Avatar/index.d.ts.map +1 -1
- package/dist/types/components/Badge/index.d.ts +2 -3
- package/dist/types/components/Badge/index.d.ts.map +1 -1
- package/dist/types/components/Breadcrumb/breadcrumb.content.d.ts +1 -3
- package/dist/types/components/Breadcrumb/breadcrumb.content.d.ts.map +1 -1
- package/dist/types/components/Breadcrumb/index.d.ts +1 -2
- package/dist/types/components/Breadcrumb/index.d.ts.map +1 -1
- package/dist/types/components/Browser/Browser.content.d.ts +127 -9
- package/dist/types/components/Browser/Browser.content.d.ts.map +1 -1
- package/dist/types/components/Browser/Browser.d.ts +1 -2
- package/dist/types/components/Browser/Browser.d.ts.map +1 -1
- package/dist/types/components/Browser/extractUrlFromSitemap.d.ts +5 -0
- package/dist/types/components/Browser/extractUrlFromSitemap.d.ts.map +1 -0
- package/dist/types/components/Button/Button.d.ts +7 -7
- package/dist/types/components/Button/Button.d.ts.map +1 -1
- package/dist/types/components/Carousel/index.content.d.ts +3 -5
- package/dist/types/components/Carousel/index.content.d.ts.map +1 -1
- package/dist/types/components/Carousel/index.d.ts.map +1 -1
- package/dist/types/components/ClickOutsideDiv/index.d.ts.map +1 -1
- package/dist/types/components/CollapsibleTable/CollapsibleTable.d.ts +3 -4
- package/dist/types/components/CollapsibleTable/CollapsibleTable.d.ts.map +1 -1
- package/dist/types/components/Command/index.d.ts +15 -17
- package/dist/types/components/Command/index.d.ts.map +1 -1
- package/dist/types/components/Container/index.d.ts +8 -9
- 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/ContentEditor/ContentEditorInput.d.ts.map +1 -1
- package/dist/types/components/ContentEditor/ContentEditorTextArea.d.ts.map +1 -1
- package/dist/types/components/ContentSelector/ContentSelector.d.ts +1 -1
- package/dist/types/components/ContentSelector/ContentSelector.d.ts.map +1 -1
- package/dist/types/components/CopyButton/CopyButton.content.d.ts +1 -3
- package/dist/types/components/CopyButton/CopyButton.content.d.ts.map +1 -1
- package/dist/types/components/CopyButton/index.d.ts.map +1 -1
- package/dist/types/components/CopyToClipboard/index.d.ts.map +1 -1
- package/dist/types/components/DictionaryEditor/DictionaryEditor.d.ts.map +1 -1
- package/dist/types/components/DictionaryEditor/ItemLayout.d.ts.map +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/ArrayWrapper.d.ts.map +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/BooleanWrapper.d.ts.map +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/ConditionWrapper.d.ts +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/ConditionWrapper.d.ts.map +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/EnumerationWrapper.d.ts +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/EnumerationWrapper.d.ts.map +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/FileWrapper.d.ts.map +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/HtmlWrapper.d.ts +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/HtmlWrapper.d.ts.map +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/InsertionWrapper.d.ts +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/InsertionWrapper.d.ts.map +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/MarkdownWrapper.d.ts +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/MarkdownWrapper.d.ts.map +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/NestedObjectWrapper.d.ts.map +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/NumberWrapper.d.ts.map +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/PluralWrapper.d.ts +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/PluralWrapper.d.ts.map +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/StringWrapper.d.ts.map +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/TranslationWrapper.d.ts +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/TranslationWrapper.d.ts.map +1 -1
- package/dist/types/components/DictionaryEditor/NodeWrapper/index.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/ContentEditor.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/ContentEditorView/SafeHtmlRenderer.d.ts +1 -3
- package/dist/types/components/DictionaryFieldEditor/ContentEditorView/SafeHtmlRenderer.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/ContentEditorView/TextEditor.d.ts +2 -3
- 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/DictionaryCreationForm/dictionaryCreationForm.content.d.ts +6 -8
- package/dist/types/components/DictionaryFieldEditor/DictionaryCreationForm/dictionaryCreationForm.content.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/DictionaryCreationForm/useDictionaryFormSchema.content.d.ts +4 -6
- package/dist/types/components/DictionaryFieldEditor/DictionaryCreationForm/useDictionaryFormSchema.content.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/DictionaryDetails/DictionaryDetailsForm.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/DictionaryDetails/dictionaryDetails.content.d.ts +27 -29
- package/dist/types/components/DictionaryFieldEditor/DictionaryDetails/dictionaryDetails.content.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/DictionaryDetails/useDictionaryDetailsSchema.content.d.ts +16 -18
- package/dist/types/components/DictionaryFieldEditor/DictionaryDetails/useDictionaryDetailsSchema.content.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/DictionaryFieldEditor.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/EnumKeyInput.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/JSONEditor.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/KeyPathBreadcrumb.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/NavigationView/navigationViewNode.content.d.ts +10 -12
- package/dist/types/components/DictionaryFieldEditor/NavigationView/navigationViewNode.content.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/NodeTypeSelector.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/SaveForm/SaveForm.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/SaveForm/saveForm.content.d.ts +16 -18
- package/dist/types/components/DictionaryFieldEditor/SaveForm/saveForm.content.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/StructureEditor.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/StructureView/StructureView.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/StructureView/structureView.content.d.ts +4 -6
- package/dist/types/components/DictionaryFieldEditor/StructureView/structureView.content.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/VersionSwitcherDropDown/VersionSwitcher.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/VersionSwitcherDropDown/VersionSwitcherContext.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/VersionSwitcherDropDown/versionSwitcherDropDown.content.d.ts +3 -5
- package/dist/types/components/DictionaryFieldEditor/VersionSwitcherDropDown/versionSwitcherDropDown.content.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/dictionaryFieldEditor.content.d.ts +2 -4
- package/dist/types/components/DictionaryFieldEditor/dictionaryFieldEditor.content.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/getIsEditableSection.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/nodeTypeSelector.content.d.ts +16 -18
- package/dist/types/components/DictionaryFieldEditor/nodeTypeSelector.content.d.ts.map +1 -1
- package/dist/types/components/DropDown/index.d.ts.map +1 -1
- package/dist/types/components/EditableField/EditableFieldInput.d.ts.map +1 -1
- package/dist/types/components/EditableField/EditableFieldLayout.d.ts.map +1 -1
- package/dist/types/components/EditableField/EditableFieldTextArea.d.ts.map +1 -1
- package/dist/types/components/ExpandCollapse/ExpandCollapse.d.ts.map +1 -1
- package/dist/types/components/ExpandCollapse/expandCollapse.content.d.ts +1 -3
- package/dist/types/components/ExpandCollapse/expandCollapse.content.d.ts.map +1 -1
- package/dist/types/components/Flags/Flag.d.ts.map +1 -1
- package/dist/types/components/Flags/flags.d.ts.map +1 -1
- package/dist/types/components/Footer/index.d.ts.map +1 -1
- package/dist/types/components/Form/Form.d.ts.map +1 -1
- package/dist/types/components/Form/FormBase.d.ts +2 -4
- package/dist/types/components/Form/FormBase.d.ts.map +1 -1
- package/dist/types/components/Form/FormField.d.ts +2 -4
- package/dist/types/components/Form/FormField.d.ts.map +1 -1
- package/dist/types/components/Form/FormItem.d.ts +1 -2
- package/dist/types/components/Form/FormItem.d.ts.map +1 -1
- package/dist/types/components/Form/elements/AutoSizeTextAreaElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/CheckboxElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/EditableFieldInputElement.d.ts +1 -2
- package/dist/types/components/Form/elements/EditableFieldInputElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/EditableFieldTextAreaElement.d.ts +1 -2
- package/dist/types/components/Form/elements/EditableFieldTextAreaElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/FormElement.d.ts +1 -2
- package/dist/types/components/Form/elements/FormElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/FormElementWrapper.d.ts.map +1 -1
- package/dist/types/components/Form/elements/InputElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/InputPasswordElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/MultiselectElement.d.ts +1 -2
- package/dist/types/components/Form/elements/MultiselectElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/OTPElement.d.ts +1 -2
- package/dist/types/components/Form/elements/OTPElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/SearchInputElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/SelectElement.d.ts +1 -2
- package/dist/types/components/Form/elements/SelectElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/SwitchSelectorElement.d.ts +1 -2
- package/dist/types/components/Form/elements/SwitchSelectorElement.d.ts.map +1 -1
- package/dist/types/components/Form/elements/TextAreaElement.d.ts.map +1 -1
- package/dist/types/components/Form/layout/FormItemLayout.d.ts.map +1 -1
- package/dist/types/components/Form/layout/FormLabelLayout.d.ts.map +1 -1
- package/dist/types/components/Form/layout/RequiredStar.d.ts.map +1 -1
- package/dist/types/components/HTMLRender/HTMLRender.d.ts.map +1 -1
- package/dist/types/components/Headers/index.d.ts.map +1 -1
- package/dist/types/components/HeightResizer/index.d.ts.map +1 -1
- package/dist/types/components/HideShow/index.d.ts.map +1 -1
- package/dist/types/components/IDE/Code.d.ts.map +1 -1
- package/dist/types/components/IDE/CodeBlockClient.d.ts.map +1 -1
- package/dist/types/components/IDE/CodeBlockHighlight.d.ts +1 -2
- package/dist/types/components/IDE/CodeBlockHighlight.d.ts.map +1 -1
- package/dist/types/components/IDE/CodeBlockServer.d.ts.map +1 -1
- package/dist/types/components/IDE/CodeBlockShiki.d.ts.map +1 -1
- package/dist/types/components/IDE/CodeContext.d.ts +1 -2
- package/dist/types/components/IDE/CodeContext.d.ts.map +1 -1
- package/dist/types/components/IDE/CodeFormatSelector.d.ts.map +1 -1
- package/dist/types/components/IDE/ContentDeclarationFormatSelector.d.ts.map +1 -1
- package/dist/types/components/IDE/CopyCode.d.ts.map +1 -1
- package/dist/types/components/IDE/FileList.d.ts.map +1 -1
- package/dist/types/components/IDE/FileTree.d.ts.map +1 -1
- package/dist/types/components/IDE/IDE.d.ts.map +1 -1
- package/dist/types/components/IDE/MarkDownRender.d.ts.map +1 -1
- package/dist/types/components/IDE/MonacoCode.d.ts.map +1 -1
- package/dist/types/components/IDE/PackageManagerSelector.d.ts.map +1 -1
- package/dist/types/components/IDE/code.content.d.ts +2 -4
- package/dist/types/components/IDE/code.content.d.ts.map +1 -1
- package/dist/types/components/IDE/codeTransformer.d.ts.map +1 -1
- package/dist/types/components/IDE/copyCode.content.d.ts +2 -4
- package/dist/types/components/IDE/copyCode.content.d.ts.map +1 -1
- package/dist/types/components/IDE/createFileTree.d.ts.map +1 -1
- package/dist/types/components/IDE/index.d.ts +1 -1
- package/dist/types/components/IDE/selectors.content.d.ts +6 -8
- package/dist/types/components/IDE/selectors.content.d.ts.map +1 -1
- package/dist/types/components/InformationTag/index.d.ts.map +1 -1
- package/dist/types/components/Input/Checkbox.d.ts +2 -3
- package/dist/types/components/Input/Checkbox.d.ts.map +1 -1
- package/dist/types/components/Input/Input.d.ts +1 -2
- package/dist/types/components/Input/Input.d.ts.map +1 -1
- package/dist/types/components/Input/InputPassword.d.ts.map +1 -1
- package/dist/types/components/Input/OTPInput.d.ts +3 -6
- package/dist/types/components/Input/OTPInput.d.ts.map +1 -1
- package/dist/types/components/Input/SearchInput.d.ts +1 -2
- package/dist/types/components/Input/SearchInput.d.ts.map +1 -1
- package/dist/types/components/KeyboardScreenAdapter/index.d.ts.map +1 -1
- package/dist/types/components/KeyboardShortcut/KeyboardShortcut.d.ts.map +1 -1
- package/dist/types/components/Label/index.d.ts.map +1 -1
- package/dist/types/components/LanguageBackground/index.d.ts.map +1 -1
- package/dist/types/components/Link/Link.d.ts +4 -5
- package/dist/types/components/Link/Link.d.ts.map +1 -1
- package/dist/types/components/Loader/index.content.d.ts +1 -3
- package/dist/types/components/Loader/index.content.d.ts.map +1 -1
- package/dist/types/components/Loader/index.d.ts.map +1 -1
- package/dist/types/components/Loader/spinner.d.ts +1 -2
- 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/LocaleSwitcherContentDropDown/LocaleSwitcherContentContext.d.ts.map +1 -1
- package/dist/types/components/LocaleSwitcherContentDropDown/localeSwitcher.content.d.ts +8 -10
- package/dist/types/components/LocaleSwitcherContentDropDown/localeSwitcher.content.d.ts.map +1 -1
- package/dist/types/components/LocaleSwitcherDropDown/LocaleSwitcher.d.ts.map +1 -1
- package/dist/types/components/LocaleSwitcherDropDown/localeSwitcher.content.d.ts +6 -8
- package/dist/types/components/LocaleSwitcherDropDown/localeSwitcher.content.d.ts.map +1 -1
- package/dist/types/components/Logo/Logo.d.ts.map +1 -1
- package/dist/types/components/Logo/LogoWithTextBelow.d.ts.map +1 -1
- package/dist/types/components/MarkDownRender/MarkDownIframe.d.ts.map +1 -1
- package/dist/types/components/MarkDownRender/MarkDownRender.d.ts +44 -45
- package/dist/types/components/MarkDownRender/MarkDownRender.d.ts.map +1 -1
- package/dist/types/components/MaxHeightSmoother/index.d.ts.map +1 -1
- package/dist/types/components/MaxWidthSmoother/index.d.ts +1 -2
- package/dist/types/components/MaxWidthSmoother/index.d.ts.map +1 -1
- package/dist/types/components/Modal/Modal.d.ts.map +1 -1
- package/dist/types/components/Navbar/Burger.d.ts +1 -2
- package/dist/types/components/Navbar/Burger.d.ts.map +1 -1
- package/dist/types/components/Navbar/DesktopNavbar.d.ts +1 -2
- package/dist/types/components/Navbar/DesktopNavbar.d.ts.map +1 -1
- package/dist/types/components/Navbar/MobileNavbar.d.ts +1 -2
- package/dist/types/components/Navbar/MobileNavbar.d.ts.map +1 -1
- package/dist/types/components/Navbar/index.d.ts +1 -2
- package/dist/types/components/Navbar/index.d.ts.map +1 -1
- package/dist/types/components/Navbar/useNavigation.d.ts.map +1 -1
- package/dist/types/components/Pagination/NumberItemsSelector.d.ts.map +1 -1
- package/dist/types/components/Pagination/Pagination.d.ts +2 -3
- package/dist/types/components/Pagination/Pagination.d.ts.map +1 -1
- package/dist/types/components/Pagination/ShowingResultsNumberItems.d.ts.map +1 -1
- package/dist/types/components/Pagination/pagination.content.d.ts +5 -7
- package/dist/types/components/Pagination/pagination.content.d.ts.map +1 -1
- package/dist/types/components/Pattern/DotPattern.d.ts.map +1 -1
- package/dist/types/components/Pattern/GridPattern.d.ts.map +1 -1
- package/dist/types/components/Pattern/SpotLight.d.ts.map +1 -1
- package/dist/types/components/Popover/dynamic.d.ts.map +1 -1
- package/dist/types/components/Popover/static.d.ts +3 -2
- package/dist/types/components/Popover/static.d.ts.map +1 -1
- package/dist/types/components/PressableSpan/PressableSpan.d.ts.map +1 -1
- package/dist/types/components/RightDrawer/RightDrawer.d.ts.map +1 -1
- package/dist/types/components/RightDrawer/isElementAtTopAndNotCovered.d.ts.map +1 -1
- package/dist/types/components/RightDrawer/rightDrawer.content.d.ts +2 -4
- package/dist/types/components/RightDrawer/rightDrawer.content.d.ts.map +1 -1
- package/dist/types/components/RightDrawer/useRightDrawer.d.ts.map +1 -1
- package/dist/types/components/Select/Multiselect.d.ts.map +1 -1
- package/dist/types/components/Select/Select.d.ts +2 -3
- package/dist/types/components/Select/Select.d.ts.map +1 -1
- package/dist/types/components/SocialNetworks/index.d.ts +1 -2
- package/dist/types/components/SocialNetworks/index.d.ts.map +1 -1
- package/dist/types/components/SwitchSelector/SwitchSelector.d.ts +8 -9
- package/dist/types/components/SwitchSelector/SwitchSelector.d.ts.map +1 -1
- package/dist/types/components/SwitchSelector/VerticalSwitchSelector.d.ts +4 -6
- package/dist/types/components/SwitchSelector/VerticalSwitchSelector.d.ts.map +1 -1
- package/dist/types/components/SwitchSelector/useSwitchSelector.d.ts +3 -4
- package/dist/types/components/SwitchSelector/useSwitchSelector.d.ts.map +1 -1
- package/dist/types/components/Tab/Tab.d.ts +3 -5
- package/dist/types/components/Tab/Tab.d.ts.map +1 -1
- package/dist/types/components/Tab/TabContext.d.ts +1 -2
- package/dist/types/components/Tab/TabContext.d.ts.map +1 -1
- package/dist/types/components/TabSelector/TabSelector.d.ts +3 -5
- package/dist/types/components/TabSelector/TabSelector.d.ts.map +1 -1
- package/dist/types/components/Table/ExpandButton.d.ts.map +1 -1
- package/dist/types/components/Table/SmartTable.d.ts.map +1 -1
- package/dist/types/components/Table/Table.d.ts +1 -2
- package/dist/types/components/Table/Table.d.ts.map +1 -1
- package/dist/types/components/Table/TableElements.d.ts +4 -5
- package/dist/types/components/Table/TableElements.d.ts.map +1 -1
- package/dist/types/components/Table/table.content.d.ts +2 -4
- package/dist/types/components/Table/table.content.d.ts.map +1 -1
- package/dist/types/components/Tag/index.d.ts +3 -4
- 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/logos/Lit.d.ts +1 -2
- package/dist/types/components/TechLogo/logos/Lit.d.ts.map +1 -1
- package/dist/types/components/TechLogo/logos/Vanilla.d.ts +1 -2
- package/dist/types/components/TechLogo/logos/Vanilla.d.ts.map +1 -1
- package/dist/types/components/Terminal/Terminal.d.ts.map +1 -1
- package/dist/types/components/Terminal/terminal.content.d.ts +2 -4
- package/dist/types/components/Terminal/terminal.content.d.ts.map +1 -1
- package/dist/types/components/TextArea/AutoSizeTextArea.d.ts.map +1 -1
- package/dist/types/components/TextArea/AutocompleteTextArea.d.ts.map +1 -1
- package/dist/types/components/TextArea/ContentEditableTextArea.d.ts +1 -2
- package/dist/types/components/TextArea/ContentEditableTextArea.d.ts.map +1 -1
- package/dist/types/components/TextArea/TextArea.d.ts.map +1 -1
- package/dist/types/components/ThemeSwitcherDropDown/DesktopThemeSwitcher.d.ts.map +1 -1
- package/dist/types/components/ThemeSwitcherDropDown/MobileThemeSwitcher.d.ts.map +1 -1
- package/dist/types/components/Toaster/Toast.d.ts +1 -2
- package/dist/types/components/Toaster/Toast.d.ts.map +1 -1
- package/dist/types/components/Toaster/Toaster.d.ts +1 -3
- package/dist/types/components/Toaster/Toaster.d.ts.map +1 -1
- package/dist/types/components/Toaster/useToast.d.ts.map +1 -1
- package/dist/types/components/WithResizer/index.d.ts +5 -1
- package/dist/types/components/WithResizer/index.d.ts.map +1 -1
- package/dist/types/components/index.d.ts +1 -1
- package/dist/types/hooks/index.d.ts +2 -2
- package/dist/types/hooks/reactQuery.d.ts +2 -1
- package/dist/types/hooks/reactQuery.d.ts.map +1 -1
- package/dist/types/hooks/useAuth/useOAuth2.d.ts.map +1 -1
- package/dist/types/hooks/useDevice.d.ts.map +1 -1
- package/dist/types/hooks/useGetElementById.d.ts.map +1 -1
- package/dist/types/hooks/useGetElementOrWindow.d.ts.map +1 -1
- package/dist/types/hooks/useHorizontalSwipe.d.ts.map +1 -1
- package/dist/types/hooks/useIntlayerAPI.d.ts.map +1 -1
- package/dist/types/hooks/useItemSelector.d.ts.map +1 -1
- package/dist/types/hooks/useScrollBlockage/index.d.ts.map +1 -1
- package/dist/types/hooks/useScrollBlockage/useScrollBlockageStore.d.ts.map +1 -1
- package/dist/types/hooks/useScrollDetection.d.ts.map +1 -1
- package/dist/types/hooks/useScrollY.d.ts.map +1 -1
- package/dist/types/hooks/useSearch.d.ts.map +1 -1
- package/dist/types/hooks/useUser/index.d.ts +1 -3
- package/dist/types/hooks/useUser/index.d.ts.map +1 -1
- package/dist/types/libs/auth.d.ts.map +1 -1
- package/dist/types/providers/ReactQueryProvider.d.ts.map +1 -1
- package/dist/types/routes.d.ts.map +1 -1
- package/dist/types/utils/cn.d.ts.map +1 -1
- package/package.json +17 -17
- package/tailwind.css +0 -1
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { cn } from "../../utils/cn.mjs";
|
|
4
|
+
import { Container } from "../Container/index.mjs";
|
|
4
5
|
import { Button } from "../Button/Button.mjs";
|
|
6
|
+
import { ClickOutsideDiv } from "../ClickOutsideDiv/index.mjs";
|
|
7
|
+
import { DropDown } from "../DropDown/index.mjs";
|
|
5
8
|
import { Input, inputVariants } from "../Input/Input.mjs";
|
|
6
|
-
import { useEffect, useImperativeHandle, useRef, useState } from "react";
|
|
7
|
-
import { ArrowLeft, ArrowRight, RotateCw } from "lucide-react";
|
|
9
|
+
import { useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
|
|
10
|
+
import { ArrowLeft, ArrowRight, RotateCw, ScanSearch } from "lucide-react";
|
|
8
11
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
12
|
import { useIntlayer } from "react-intlayer";
|
|
10
13
|
|
|
11
14
|
//#region src/components/Browser/Browser.tsx
|
|
15
|
+
const getUrlPath = (url) => {
|
|
16
|
+
try {
|
|
17
|
+
const { pathname, search, hash } = new URL(url);
|
|
18
|
+
return `${pathname}${search}${hash}` || "/";
|
|
19
|
+
} catch {
|
|
20
|
+
return url;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
12
23
|
const Browser = ({ initialUrl = "https://example.com", path, className, style, size = "md", "aria-label": ariaLabel, sandbox = "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads", ref, domainRestriction, ...props }) => {
|
|
13
24
|
const [inputUrl, setInputUrl] = useState(initialUrl);
|
|
14
25
|
const [currentUrl, setCurrentUrl] = useState(initialUrl);
|
|
@@ -17,6 +28,13 @@ const Browser = ({ initialUrl = "https://example.com", path, className, style, s
|
|
|
17
28
|
const [error, setError] = useState(null);
|
|
18
29
|
const [submitted, setSubmitted] = useState(false);
|
|
19
30
|
const internalIframeRef = useRef(null);
|
|
31
|
+
const [sitemapOpen, setSitemapOpen] = useState(false);
|
|
32
|
+
const [sitemapUrls, setSitemapUrls] = useState([]);
|
|
33
|
+
const [sitemapSearch, setSitemapSearch] = useState("");
|
|
34
|
+
const [sitemapLoading, setSitemapLoading] = useState(false);
|
|
35
|
+
const [sitemapFetched, setSitemapFetched] = useState(false);
|
|
36
|
+
const [sitemapError, setSitemapError] = useState(false);
|
|
37
|
+
const sitemapInputRef = useRef(null);
|
|
20
38
|
useImperativeHandle(ref, () => internalIframeRef.current, []);
|
|
21
39
|
const content = useIntlayer("browser");
|
|
22
40
|
useEffect(() => {
|
|
@@ -26,6 +44,11 @@ const Browser = ({ initialUrl = "https://example.com", path, className, style, s
|
|
|
26
44
|
setCurrentIndex(0);
|
|
27
45
|
setError(null);
|
|
28
46
|
setSubmitted(false);
|
|
47
|
+
setSitemapOpen(false);
|
|
48
|
+
setSitemapUrls([]);
|
|
49
|
+
setSitemapSearch("");
|
|
50
|
+
setSitemapFetched(false);
|
|
51
|
+
setSitemapError(false);
|
|
29
52
|
}, [initialUrl]);
|
|
30
53
|
useEffect(() => {
|
|
31
54
|
if (!path) return;
|
|
@@ -53,6 +76,11 @@ const Browser = ({ initialUrl = "https://example.com", path, className, style, s
|
|
|
53
76
|
domainRestriction,
|
|
54
77
|
initialUrl
|
|
55
78
|
]);
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
const iframe = internalIframeRef.current;
|
|
81
|
+
if (!iframe) return;
|
|
82
|
+
if (iframe.src !== currentUrl) iframe.src = currentUrl;
|
|
83
|
+
}, [currentUrl]);
|
|
56
84
|
const handleNavigateTo = (url) => {
|
|
57
85
|
try {
|
|
58
86
|
const validated = normalizeUrl(url);
|
|
@@ -98,13 +126,13 @@ const Browser = ({ initialUrl = "https://example.com", path, className, style, s
|
|
|
98
126
|
handleNavigateTo(inputUrl);
|
|
99
127
|
};
|
|
100
128
|
const handleReload = () => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
129
|
+
const iframe = internalIframeRef.current;
|
|
130
|
+
if (!iframe) return;
|
|
131
|
+
const src = iframe.src;
|
|
132
|
+
iframe.src = "";
|
|
133
|
+
setTimeout(() => {
|
|
134
|
+
if (internalIframeRef.current) internalIframeRef.current.src = src;
|
|
135
|
+
}, 50);
|
|
108
136
|
};
|
|
109
137
|
const isValidHostname = (host) => {
|
|
110
138
|
if (host === "localhost") return true;
|
|
@@ -141,6 +169,31 @@ const Browser = ({ initialUrl = "https://example.com", path, className, style, s
|
|
|
141
169
|
}
|
|
142
170
|
return url.toString();
|
|
143
171
|
};
|
|
172
|
+
const handleSitemapToggle = async () => {
|
|
173
|
+
const nextOpen = !sitemapOpen;
|
|
174
|
+
setSitemapOpen(nextOpen);
|
|
175
|
+
if (nextOpen && !sitemapFetched) {
|
|
176
|
+
setSitemapLoading(true);
|
|
177
|
+
setSitemapError(false);
|
|
178
|
+
setSitemapFetched(true);
|
|
179
|
+
try {
|
|
180
|
+
const { extractUrlFromSitemap } = await import("./extractUrlFromSitemap.mjs");
|
|
181
|
+
const urls = await extractUrlFromSitemap(currentUrl);
|
|
182
|
+
setSitemapUrls(urls);
|
|
183
|
+
if (urls.length === 0) setSitemapError(false);
|
|
184
|
+
} catch {
|
|
185
|
+
setSitemapError(true);
|
|
186
|
+
} finally {
|
|
187
|
+
setSitemapLoading(false);
|
|
188
|
+
}
|
|
189
|
+
setTimeout(() => sitemapInputRef.current?.focus(), 50);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
const filteredSitemapUrls = useMemo(() => {
|
|
193
|
+
const query = sitemapSearch.trim().toLowerCase();
|
|
194
|
+
if (!query) return sitemapUrls;
|
|
195
|
+
return sitemapUrls.filter((url) => url.toLowerCase().includes(query));
|
|
196
|
+
}, [sitemapUrls, sitemapSearch]);
|
|
144
197
|
const showError = submitted && !!error;
|
|
145
198
|
const canGoBack = currentIndex > 0;
|
|
146
199
|
const canGoForward = currentIndex < history.length - 1;
|
|
@@ -217,6 +270,75 @@ const Browser = ({ initialUrl = "https://example.com", path, className, style, s
|
|
|
217
270
|
})
|
|
218
271
|
]
|
|
219
272
|
}),
|
|
273
|
+
/* @__PURE__ */ jsx(ClickOutsideDiv, {
|
|
274
|
+
onClickOutSide: () => setSitemapOpen(false),
|
|
275
|
+
disabled: !sitemapOpen,
|
|
276
|
+
role: "none",
|
|
277
|
+
children: /* @__PURE__ */ jsxs(DropDown, {
|
|
278
|
+
identifier: "sitemap-explorer",
|
|
279
|
+
children: [/* @__PURE__ */ jsx(DropDown.Trigger, {
|
|
280
|
+
identifier: "sitemap-explorer-trigger",
|
|
281
|
+
type: "button",
|
|
282
|
+
color: "text",
|
|
283
|
+
onClick: handleSitemapToggle,
|
|
284
|
+
variant: "hoverable",
|
|
285
|
+
size: "icon-md",
|
|
286
|
+
label: content.sitemapButtonLabel.value,
|
|
287
|
+
Icon: ScanSearch
|
|
288
|
+
}), /* @__PURE__ */ jsx(DropDown.Panel, {
|
|
289
|
+
identifier: "sitemap-explorer",
|
|
290
|
+
isHidden: !sitemapOpen,
|
|
291
|
+
align: "end",
|
|
292
|
+
isFocusable: true,
|
|
293
|
+
isOverable: true,
|
|
294
|
+
children: /* @__PURE__ */ jsxs(Container, {
|
|
295
|
+
className: "min-w-48 rounded-md!",
|
|
296
|
+
roundedSize: "sm",
|
|
297
|
+
border: true,
|
|
298
|
+
borderColor: "neutral",
|
|
299
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
300
|
+
className: "p-2",
|
|
301
|
+
children: /* @__PURE__ */ jsx(Input, {
|
|
302
|
+
type: "search",
|
|
303
|
+
ref: sitemapInputRef,
|
|
304
|
+
"aria-label": content.sitemapSearchAriaLabel.value,
|
|
305
|
+
placeholder: content.sitemapSearchPlaceholder.value,
|
|
306
|
+
onChange: (e) => setSitemapSearch(e.target.value),
|
|
307
|
+
value: sitemapSearch,
|
|
308
|
+
size: "sm"
|
|
309
|
+
})
|
|
310
|
+
}), /* @__PURE__ */ jsx("ul", {
|
|
311
|
+
className: "max-h-64 divide-y divide-dotted divide-neutral/30 overflow-y-auto p-1",
|
|
312
|
+
"aria-label": content.sitemapButtonLabel.value,
|
|
313
|
+
children: sitemapLoading ? /* @__PURE__ */ jsx("li", {
|
|
314
|
+
className: "px-3 py-4 text-center text-neutral text-xs",
|
|
315
|
+
children: content.sitemapLoading.value
|
|
316
|
+
}) : sitemapError || !sitemapLoading && filteredSitemapUrls.length === 0 ? /* @__PURE__ */ jsx("li", {
|
|
317
|
+
className: "px-3 py-4 text-center text-neutral text-xs",
|
|
318
|
+
children: sitemapError ? content.sitemapError.value : content.sitemapEmpty.value
|
|
319
|
+
}) : filteredSitemapUrls.map((url) => /* @__PURE__ */ jsx("li", {
|
|
320
|
+
className: "py-0.5",
|
|
321
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
322
|
+
variant: "hoverable",
|
|
323
|
+
color: "text",
|
|
324
|
+
size: "sm",
|
|
325
|
+
className: "w-full justify-start",
|
|
326
|
+
label: url,
|
|
327
|
+
onClick: () => {
|
|
328
|
+
handleNavigateTo(url);
|
|
329
|
+
setSitemapOpen(false);
|
|
330
|
+
},
|
|
331
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
332
|
+
className: "max-w-64 truncate text-left text-base",
|
|
333
|
+
children: getUrlPath(url)
|
|
334
|
+
})
|
|
335
|
+
})
|
|
336
|
+
}, url))
|
|
337
|
+
})]
|
|
338
|
+
})
|
|
339
|
+
})]
|
|
340
|
+
})
|
|
341
|
+
}),
|
|
220
342
|
showError && /* @__PURE__ */ jsx("div", {
|
|
221
343
|
className: "absolute top-full left-4 z-20 mt-1",
|
|
222
344
|
children: /* @__PURE__ */ jsx("p", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Browser.mjs","names":[],"sources":["../../../../src/components/Browser/Browser.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport { ArrowLeft, ArrowRight, RotateCw } from 'lucide-react';\nimport {\n type CSSProperties,\n type SubmitEvent,\n type HTMLAttributes,\n type RefObject,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport { Button } from '../Button';\nimport { Input, inputVariants } from '../Input';\n\nexport type BrowserProps = {\n initialUrl?: string;\n path?: string;\n className?: string;\n style?: CSSProperties;\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n 'aria-label'?: string;\n sandbox?: string;\n ref?: RefObject<HTMLIFrameElement | null>;\n domainRestriction?: string;\n} & HTMLAttributes<HTMLIFrameElement>;\n\nexport const Browser = ({\n initialUrl = 'https://example.com',\n path,\n className,\n style,\n size = 'md',\n 'aria-label': ariaLabel,\n sandbox = 'allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads',\n ref,\n domainRestriction,\n ...props\n}: BrowserProps) => {\n // --- State -----------------------------------------------------------------\n const [inputUrl, setInputUrl] = useState(initialUrl);\n const [currentUrl, setCurrentUrl] = useState(initialUrl);\n\n // History Management\n const [history, setHistory] = useState<string[]>([initialUrl]);\n const [currentIndex, setCurrentIndex] = useState(0);\n\n const [error, setError] = useState<string | null>(null);\n const [submitted, setSubmitted] = useState(false);\n const internalIframeRef = useRef<HTMLIFrameElement>(null);\n\n useImperativeHandle(ref, () => internalIframeRef.current!, []);\n const content = useIntlayer('browser');\n\n // --- Effects ---------------------------------------------------------------\n\n // Reset everything if initialUrl changes completely\n useEffect(() => {\n setInputUrl(initialUrl);\n setCurrentUrl(initialUrl);\n setHistory([initialUrl]);\n setCurrentIndex(0);\n setError(null);\n setSubmitted(false);\n }, [initialUrl]);\n\n // Sync external path changes with the URL bar and History\n useEffect(() => {\n if (!path) return;\n\n try {\n const baseOrigin = domainRestriction ?? initialUrl;\n const origin = new URL(baseOrigin).origin;\n const fullUrl = `${origin}${path}`;\n\n // Update Input (Always update the visual bar)\n setInputUrl(fullUrl);\n\n // Check internal iframe state to avoid reload if already there\n let isAlreadyAtUrl = false;\n if (internalIframeRef.current?.contentWindow) {\n try {\n const currentIframeHref =\n internalIframeRef.current.contentWindow.location.href;\n if (new URL(currentIframeHref).href === new URL(fullUrl).href) {\n isAlreadyAtUrl = true;\n }\n } catch {\n // Cross-origin access ignored\n }\n }\n\n // Update History Stack\n // We perform this check regardless of `isAlreadyAtUrl`.\n // If the path changed (even internally), we want to record it in the arrow stack.\n if (history[currentIndex] !== fullUrl) {\n setHistory((prev) => {\n const newHistory = prev.slice(0, currentIndex + 1);\n newHistory.push(fullUrl);\n return newHistory;\n });\n setCurrentIndex((prev) => prev + 1);\n }\n\n // Navigate (Update src) only if NOT already there\n // This prevents the iframe from refreshing when the user navigated inside it.\n if (!isAlreadyAtUrl) {\n setCurrentUrl(fullUrl);\n }\n\n setError(null);\n } catch {\n // Ignore invalid paths\n }\n }, [path, domainRestriction, initialUrl]); // Removed currentIndex dependency to prevent loops\n\n // --- Navigation Logic ------------------------------------------------------\n\n const handleNavigateTo = (url: string) => {\n try {\n const validated = normalizeUrl(url);\n\n // If we are navigating to the exact same URL, just reload\n if (validated === currentUrl) {\n handleReload();\n return;\n }\n\n setCurrentUrl(validated);\n setInputUrl(validated);\n setError(null);\n\n // Update History: Slice future if we went back, then push new\n const newHistory = history.slice(0, currentIndex + 1);\n newHistory.push(validated);\n setHistory(newHistory);\n setCurrentIndex(newHistory.length - 1);\n } catch (e) {\n if (\n e instanceof Error &&\n e.message === 'URL does not match allowed domain' &&\n domainRestriction\n ) {\n setError(\n content.domainRestrictionError?.value ??\n `Only URLs from ${domainRestriction} are allowed.`\n );\n } else {\n setError(content.errorMessage.value);\n }\n }\n };\n\n const handleBack = () => {\n if (currentIndex > 0) {\n const newIndex = currentIndex - 1;\n const prevUrl = history[newIndex];\n setCurrentIndex(newIndex);\n setCurrentUrl(prevUrl);\n setInputUrl(prevUrl);\n setError(null);\n }\n };\n\n const handleForward = () => {\n if (currentIndex < history.length - 1) {\n const newIndex = currentIndex + 1;\n const nextUrl = history[newIndex];\n setCurrentIndex(newIndex);\n setCurrentUrl(nextUrl);\n setInputUrl(nextUrl);\n setError(null);\n }\n };\n\n const handleSubmit = (e: SubmitEvent<HTMLFormElement>) => {\n e.preventDefault();\n setSubmitted(true);\n handleNavigateTo(inputUrl);\n };\n\n const handleReload = () => {\n if (internalIframeRef.current) {\n // Create a clean reload effect\n const src = internalIframeRef.current.src;\n internalIframeRef.current.src = '';\n setTimeout(() => {\n if (internalIframeRef.current) internalIframeRef.current.src = src;\n }, 50);\n }\n };\n\n // --- Validation Helpers ----------------------------------------------------\n const isValidHostname = (host: string) => {\n if (host === 'localhost') return true;\n if (/^(\\d{1,3}\\.){3}\\d{1,3}$/.test(host)) return true;\n if (/^[a-f0-9:]+$/i.test(host)) return true;\n if (!/^[a-z0-9.-]+$/i.test(host)) return false;\n if (/^[-.]/.test(host) || /[-.]$/.test(host)) return false;\n if (host.includes('..')) return false;\n if (!host.includes('.')) return false;\n return true;\n };\n\n const getRestrictionOrigin = (): URL | null => {\n if (!domainRestriction) return null;\n try {\n return new URL(domainRestriction);\n } catch {\n return null;\n }\n };\n\n const normalizeUrl = (raw: string) => {\n const trimmed = raw.trim();\n if (!trimmed || /\\s/.test(trimmed)) throw new Error('Invalid');\n\n const restrictionOrigin = getRestrictionOrigin();\n const isRelativePath = trimmed.startsWith('/') && !trimmed.startsWith('//');\n\n if (isRelativePath) {\n if (restrictionOrigin) {\n return new URL(`${restrictionOrigin.origin}${trimmed}`).toString();\n }\n return new URL(`${new URL(currentUrl).origin}${trimmed}`).toString();\n }\n\n const hasProtocol = /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(trimmed);\n const candidate = hasProtocol ? trimmed : `https://${trimmed}`;\n const url = new URL(candidate);\n\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n throw new Error('Only http(s) is allowed');\n }\n\n if (!isValidHostname(url.hostname)) throw new Error('Invalid host');\n\n if (restrictionOrigin) {\n const urlMatches =\n url.hostname === restrictionOrigin.hostname &&\n url.protocol === restrictionOrigin.protocol &&\n (restrictionOrigin.port === '' ||\n url.port === restrictionOrigin.port ||\n url.host === restrictionOrigin.host);\n\n if (!urlMatches) throw new Error('URL does not match allowed domain');\n }\n\n return url.toString();\n };\n\n const showError = submitted && !!error;\n const canGoBack = currentIndex > 0;\n const canGoForward = currentIndex < history.length - 1;\n\n return (\n <section\n className={cn(\n 'flex w-full flex-col overflow-hidden rounded-xl bg-background shadow-[0_4px_12px_rgba(0,0,0,0.4),0_0_1px_rgba(0,0,0,0.2)]',\n className\n )}\n style={style}\n aria-label={ariaLabel ?? content.ariaLabel.value}\n >\n {/* Top bar */}\n <div className=\"relative z-10 flex shrink-0 items-center gap-3 rounded-t-xl bg-text/15 px-4 py-2\">\n {/* Navigation Controls */}\n <div className=\"flex items-center gap-1\">\n <Button\n type=\"button\"\n onClick={handleBack}\n disabled={!canGoBack}\n variant=\"hoverable\"\n size=\"icon-md\"\n label={content.backButtonLabel.value}\n Icon={ArrowLeft}\n />\n <Button\n type=\"button\"\n onClick={handleForward}\n disabled={!canGoForward}\n variant=\"hoverable\"\n size=\"icon-md\"\n label={content.forwardButtonLabel.value}\n Icon={ArrowRight}\n />\n </div>\n\n {/* URL Bar */}\n <form\n onSubmit={handleSubmit}\n noValidate\n className={cn(\n inputVariants(),\n 'flex w-full gap-2 rounded-xl p-0.5! supports-[corner-shape:squircle]:rounded-2xl',\n 'bg-neutral/10 text-text/50 placeholder:text-neutral/80'\n )}\n >\n <label htmlFor=\"browser-url\" className=\"sr-only\">\n {content.urlLabel.value}\n </label>\n <Input\n id=\"browser-url\"\n type=\"text\"\n inputMode=\"url\"\n spellCheck={false}\n autoCapitalize=\"off\"\n variant=\"invisible\"\n className=\"ml-3 p-0!\"\n size=\"sm\"\n autoCorrect=\"off\"\n value={inputUrl}\n onChange={(e) => {\n setInputUrl(e.target.value);\n if (showError) setError(null);\n }}\n placeholder={content.urlPlaceholder.value}\n aria-label={content.urlLabel.value}\n aria-invalid={showError}\n aria-describedby={showError ? 'browser-url-error' : undefined}\n />\n\n <Button\n type=\"button\"\n onClick={handleReload}\n variant=\"hoverable\"\n size=\"icon-md\"\n className=\"p-1!\"\n label={'content.reloadButtonTitle.value'}\n Icon={RotateCw}\n />\n\n {/* invisible submit */}\n <button type=\"submit\" className=\"sr-only absolute\" tabIndex={-1} />\n </form>\n\n {/* Error Message Tooltip */}\n {showError && (\n <div className=\"absolute top-full left-4 z-20 mt-1\">\n <p\n id=\"browser-url-error\"\n role=\"alert\"\n aria-live=\"assertive\"\n className=\"rounded-md bg-red-900/90 px-3 py-1.5 text-red-100 text-xs shadow-md backdrop-blur-sm\"\n >\n {error}\n </p>\n </div>\n )}\n </div>\n\n {/* Iframe */}\n <div className=\"relative z-0 flex min-h-0 w-full flex-1 flex-col overflow-hidden rounded-b-xl bg-background\">\n <iframe\n ref={internalIframeRef}\n src={currentUrl}\n title={content.iframeTitle.value}\n className=\"size-full flex-1\"\n sandbox={sandbox}\n loading=\"lazy\"\n aria-live=\"polite\"\n {...props}\n />\n </div>\n </section>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Browser.mjs","names":[],"sources":["../../../../src/components/Browser/Browser.tsx"],"sourcesContent":["'use client';\n\nimport { Container } from '@components/Container';\nimport { cn } from '@utils/cn';\nimport {\n ArrowLeft,\n ArrowRight,\n Globe,\n List,\n RotateCw,\n ScanSearch,\n} from 'lucide-react';\nimport {\n type CSSProperties,\n type HTMLAttributes,\n type RefObject,\n type SubmitEvent,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport { Button } from '../Button';\nimport { ClickOutsideDiv } from '../ClickOutsideDiv';\nimport { DropDown } from '../DropDown';\nimport { Input, inputVariants } from '../Input';\n\nexport type BrowserProps = {\n initialUrl?: string;\n path?: string;\n className?: string;\n style?: CSSProperties;\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n 'aria-label'?: string;\n sandbox?: string;\n ref?: RefObject<HTMLIFrameElement | null>;\n domainRestriction?: string;\n} & HTMLAttributes<HTMLIFrameElement>;\n\nconst getUrlPath = (url: string) => {\n try {\n const { pathname, search, hash } = new URL(url);\n return `${pathname}${search}${hash}` || '/';\n } catch {\n return url;\n }\n};\n\nexport const Browser = ({\n initialUrl = 'https://example.com',\n path,\n className,\n style,\n size = 'md',\n 'aria-label': ariaLabel,\n sandbox = 'allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads',\n ref,\n domainRestriction,\n ...props\n}: BrowserProps) => {\n // --- State -----------------------------------------------------------------\n const [inputUrl, setInputUrl] = useState(initialUrl);\n const [currentUrl, setCurrentUrl] = useState(initialUrl);\n\n // History Management\n const [history, setHistory] = useState<string[]>([initialUrl]);\n const [currentIndex, setCurrentIndex] = useState(0);\n\n const [error, setError] = useState<string | null>(null);\n const [submitted, setSubmitted] = useState(false);\n const internalIframeRef = useRef<HTMLIFrameElement>(null);\n\n // Sitemap explorer state\n const [sitemapOpen, setSitemapOpen] = useState(false);\n const [sitemapUrls, setSitemapUrls] = useState<string[]>([]);\n const [sitemapSearch, setSitemapSearch] = useState('');\n const [sitemapLoading, setSitemapLoading] = useState(false);\n const [sitemapFetched, setSitemapFetched] = useState(false);\n const [sitemapError, setSitemapError] = useState(false);\n const sitemapInputRef = useRef<HTMLInputElement>(null);\n\n useImperativeHandle(ref, () => internalIframeRef.current!, []);\n const content = useIntlayer('browser');\n\n // --- Effects ---------------------------------------------------------------\n\n // Reset everything if initialUrl changes completely\n useEffect(() => {\n setInputUrl(initialUrl);\n setCurrentUrl(initialUrl);\n setHistory([initialUrl]);\n setCurrentIndex(0);\n setError(null);\n setSubmitted(false);\n setSitemapOpen(false);\n setSitemapUrls([]);\n setSitemapSearch('');\n setSitemapFetched(false);\n setSitemapError(false);\n }, [initialUrl]);\n\n // Sync external path changes with the URL bar and History\n useEffect(() => {\n if (!path) return;\n\n try {\n const baseOrigin = domainRestriction ?? initialUrl;\n const origin = new URL(baseOrigin).origin;\n const fullUrl = `${origin}${path}`;\n\n // Update Input (Always update the visual bar)\n setInputUrl(fullUrl);\n\n // Check internal iframe state to avoid reload if already there\n let isAlreadyAtUrl = false;\n if (internalIframeRef.current?.contentWindow) {\n try {\n const currentIframeHref =\n internalIframeRef.current.contentWindow.location.href;\n if (new URL(currentIframeHref).href === new URL(fullUrl).href) {\n isAlreadyAtUrl = true;\n }\n } catch {\n // Cross-origin access ignored\n }\n }\n\n // Update History Stack regardless of isAlreadyAtUrl so arrow navigation is always correct\n if (history[currentIndex] !== fullUrl) {\n setHistory((prev) => {\n const newHistory = prev.slice(0, currentIndex + 1);\n newHistory.push(fullUrl);\n return newHistory;\n });\n setCurrentIndex((prev) => prev + 1);\n }\n\n // Navigate only if NOT already there to avoid refreshing on internal iframe navigation\n if (!isAlreadyAtUrl) {\n setCurrentUrl(fullUrl);\n }\n\n setError(null);\n } catch {\n // Ignore invalid paths\n }\n }, [path, domainRestriction, initialUrl]); // Removed currentIndex dependency to prevent loops\n\n // Imperatively keep the iframe src in sync with currentUrl.\n // React's attribute reconciliation can be unreliable for cross-origin iframes after\n // internal navigation, so this effect is the source of truth for navigation.\n useEffect(() => {\n const iframe = internalIframeRef.current;\n if (!iframe) return;\n if (iframe.src !== currentUrl) {\n iframe.src = currentUrl;\n }\n }, [currentUrl]);\n\n // --- Navigation Logic ------------------------------------------------------\n\n const handleNavigateTo = (url: string) => {\n try {\n const validated = normalizeUrl(url);\n\n // If we are navigating to the exact same URL, just reload\n if (validated === currentUrl) {\n handleReload();\n return;\n }\n\n setCurrentUrl(validated);\n setInputUrl(validated);\n setError(null);\n\n // Update History: Slice future if we went back, then push new\n const newHistory = history.slice(0, currentIndex + 1);\n newHistory.push(validated);\n setHistory(newHistory);\n setCurrentIndex(newHistory.length - 1);\n } catch (e) {\n if (\n e instanceof Error &&\n e.message === 'URL does not match allowed domain' &&\n domainRestriction\n ) {\n setError(\n content.domainRestrictionError?.value ??\n `Only URLs from ${domainRestriction} are allowed.`\n );\n } else {\n setError(content.errorMessage.value);\n }\n }\n };\n\n const handleBack = () => {\n if (currentIndex > 0) {\n const newIndex = currentIndex - 1;\n const prevUrl = history[newIndex];\n setCurrentIndex(newIndex);\n setCurrentUrl(prevUrl);\n setInputUrl(prevUrl);\n setError(null);\n }\n };\n\n const handleForward = () => {\n if (currentIndex < history.length - 1) {\n const newIndex = currentIndex + 1;\n const nextUrl = history[newIndex];\n setCurrentIndex(newIndex);\n setCurrentUrl(nextUrl);\n setInputUrl(nextUrl);\n setError(null);\n }\n };\n\n const handleSubmit = (e: SubmitEvent<HTMLFormElement>) => {\n e.preventDefault();\n setSubmitted(true);\n handleNavigateTo(inputUrl);\n };\n\n const handleReload = () => {\n const iframe = internalIframeRef.current;\n if (!iframe) return;\n const src = iframe.src;\n iframe.src = '';\n setTimeout(() => {\n if (internalIframeRef.current) internalIframeRef.current.src = src;\n }, 50);\n };\n\n // --- Validation Helpers ----------------------------------------------------\n const isValidHostname = (host: string) => {\n if (host === 'localhost') return true;\n if (/^(\\d{1,3}\\.){3}\\d{1,3}$/.test(host)) return true;\n if (/^[a-f0-9:]+$/i.test(host)) return true;\n if (!/^[a-z0-9.-]+$/i.test(host)) return false;\n if (/^[-.]/.test(host) || /[-.]$/.test(host)) return false;\n if (host.includes('..')) return false;\n if (!host.includes('.')) return false;\n return true;\n };\n\n const getRestrictionOrigin = (): URL | null => {\n if (!domainRestriction) return null;\n try {\n return new URL(domainRestriction);\n } catch {\n return null;\n }\n };\n\n const normalizeUrl = (raw: string) => {\n const trimmed = raw.trim();\n if (!trimmed || /\\s/.test(trimmed)) throw new Error('Invalid');\n\n const restrictionOrigin = getRestrictionOrigin();\n const isRelativePath = trimmed.startsWith('/') && !trimmed.startsWith('//');\n\n if (isRelativePath) {\n if (restrictionOrigin) {\n return new URL(`${restrictionOrigin.origin}${trimmed}`).toString();\n }\n return new URL(`${new URL(currentUrl).origin}${trimmed}`).toString();\n }\n\n const hasProtocol = /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(trimmed);\n const candidate = hasProtocol ? trimmed : `https://${trimmed}`;\n const url = new URL(candidate);\n\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n throw new Error('Only http(s) is allowed');\n }\n\n if (!isValidHostname(url.hostname)) throw new Error('Invalid host');\n\n if (restrictionOrigin) {\n const urlMatches =\n url.hostname === restrictionOrigin.hostname &&\n url.protocol === restrictionOrigin.protocol &&\n (restrictionOrigin.port === '' ||\n url.port === restrictionOrigin.port ||\n url.host === restrictionOrigin.host);\n\n if (!urlMatches) throw new Error('URL does not match allowed domain');\n }\n\n return url.toString();\n };\n\n const handleSitemapToggle = async () => {\n const nextOpen = !sitemapOpen;\n setSitemapOpen(nextOpen);\n\n if (nextOpen && !sitemapFetched) {\n setSitemapLoading(true);\n setSitemapError(false);\n setSitemapFetched(true);\n try {\n const { extractUrlFromSitemap } = await import(\n './extractUrlFromSitemap'\n );\n const urls = await extractUrlFromSitemap(currentUrl);\n setSitemapUrls(urls);\n if (urls.length === 0) setSitemapError(false);\n } catch {\n setSitemapError(true);\n } finally {\n setSitemapLoading(false);\n }\n setTimeout(() => sitemapInputRef.current?.focus(), 50);\n }\n };\n\n const filteredSitemapUrls = useMemo(() => {\n const query = sitemapSearch.trim().toLowerCase();\n if (!query) return sitemapUrls;\n return sitemapUrls.filter((url) => url.toLowerCase().includes(query));\n }, [sitemapUrls, sitemapSearch]);\n\n const showError = submitted && !!error;\n const canGoBack = currentIndex > 0;\n const canGoForward = currentIndex < history.length - 1;\n\n return (\n <section\n className={cn(\n 'flex w-full flex-col overflow-hidden rounded-xl bg-background shadow-[0_4px_12px_rgba(0,0,0,0.4),0_0_1px_rgba(0,0,0,0.2)]',\n className\n )}\n style={style}\n aria-label={ariaLabel ?? content.ariaLabel.value}\n >\n {/* Top bar */}\n <div className=\"relative z-10 flex shrink-0 items-center gap-3 rounded-t-xl bg-text/15 px-4 py-2\">\n {/* Navigation Controls */}\n <div className=\"flex items-center gap-1\">\n <Button\n type=\"button\"\n onClick={handleBack}\n disabled={!canGoBack}\n variant=\"hoverable\"\n size=\"icon-md\"\n label={content.backButtonLabel.value}\n Icon={ArrowLeft}\n />\n <Button\n type=\"button\"\n onClick={handleForward}\n disabled={!canGoForward}\n variant=\"hoverable\"\n size=\"icon-md\"\n label={content.forwardButtonLabel.value}\n Icon={ArrowRight}\n />\n </div>\n\n {/* URL Bar */}\n <form\n onSubmit={handleSubmit}\n noValidate\n className={cn(\n inputVariants(),\n 'flex w-full gap-2 rounded-xl p-0.5! supports-[corner-shape:squircle]:rounded-2xl',\n 'bg-neutral/10 text-text/50 placeholder:text-neutral/80'\n )}\n >\n <label htmlFor=\"browser-url\" className=\"sr-only\">\n {content.urlLabel.value}\n </label>\n <Input\n id=\"browser-url\"\n type=\"text\"\n inputMode=\"url\"\n spellCheck={false}\n autoCapitalize=\"off\"\n variant=\"invisible\"\n className=\"ml-3 p-0!\"\n size=\"sm\"\n autoCorrect=\"off\"\n value={inputUrl}\n onChange={(e) => {\n setInputUrl(e.target.value);\n if (showError) setError(null);\n }}\n placeholder={content.urlPlaceholder.value}\n aria-label={content.urlLabel.value}\n aria-invalid={showError}\n aria-describedby={showError ? 'browser-url-error' : undefined}\n />\n\n <Button\n type=\"button\"\n onClick={handleReload}\n variant=\"hoverable\"\n size=\"icon-md\"\n className=\"p-1!\"\n label={'content.reloadButtonTitle.value'}\n Icon={RotateCw}\n />\n\n {/* invisible submit */}\n <button type=\"submit\" className=\"sr-only absolute\" tabIndex={-1} />\n </form>\n\n {/* Sitemap Explorer */}\n <ClickOutsideDiv\n onClickOutSide={() => setSitemapOpen(false)}\n disabled={!sitemapOpen}\n role=\"none\"\n >\n <DropDown identifier=\"sitemap-explorer\">\n <DropDown.Trigger\n identifier=\"sitemap-explorer-trigger\"\n type=\"button\"\n color=\"text\"\n onClick={handleSitemapToggle}\n variant=\"hoverable\"\n size=\"icon-md\"\n label={content.sitemapButtonLabel.value}\n Icon={ScanSearch}\n />\n\n <DropDown.Panel\n identifier=\"sitemap-explorer\"\n isHidden={!sitemapOpen}\n align=\"end\"\n isFocusable\n isOverable\n >\n <Container\n className=\"min-w-48 rounded-md!\"\n roundedSize=\"sm\"\n border\n borderColor=\"neutral\"\n >\n <div className=\"p-2\">\n <Input\n type=\"search\"\n ref={sitemapInputRef}\n aria-label={content.sitemapSearchAriaLabel.value}\n placeholder={content.sitemapSearchPlaceholder.value}\n onChange={(e) => setSitemapSearch(e.target.value)}\n value={sitemapSearch}\n size=\"sm\"\n />\n </div>\n <ul\n className=\"max-h-64 divide-y divide-dotted divide-neutral/30 overflow-y-auto p-1\"\n aria-label={content.sitemapButtonLabel.value}\n >\n {sitemapLoading ? (\n <li className=\"px-3 py-4 text-center text-neutral text-xs\">\n {content.sitemapLoading.value}\n </li>\n ) : sitemapError ||\n (!sitemapLoading && filteredSitemapUrls.length === 0) ? (\n <li className=\"px-3 py-4 text-center text-neutral text-xs\">\n {sitemapError\n ? content.sitemapError.value\n : content.sitemapEmpty.value}\n </li>\n ) : (\n filteredSitemapUrls.map((url) => (\n <li key={url} className=\"py-0.5\">\n <Button\n variant=\"hoverable\"\n color=\"text\"\n size=\"sm\"\n className=\"w-full justify-start\"\n label={url}\n onClick={() => {\n handleNavigateTo(url);\n setSitemapOpen(false);\n }}\n >\n <span className=\"max-w-64 truncate text-left text-base\">\n {getUrlPath(url)}\n </span>\n </Button>\n </li>\n ))\n )}\n </ul>\n </Container>\n </DropDown.Panel>\n </DropDown>\n </ClickOutsideDiv>\n\n {/* Error Message Tooltip */}\n {showError && (\n <div className=\"absolute top-full left-4 z-20 mt-1\">\n <p\n id=\"browser-url-error\"\n role=\"alert\"\n aria-live=\"assertive\"\n className=\"rounded-md bg-red-900/90 px-3 py-1.5 text-red-100 text-xs shadow-md backdrop-blur-sm\"\n >\n {error}\n </p>\n </div>\n )}\n </div>\n\n {/* Iframe */}\n <div className=\"relative z-0 flex min-h-0 w-full flex-1 flex-col overflow-hidden rounded-b-xl bg-background\">\n <iframe\n ref={internalIframeRef}\n src={currentUrl}\n title={content.iframeTitle.value}\n className=\"size-full flex-1\"\n sandbox={sandbox}\n loading=\"lazy\"\n aria-live=\"polite\"\n {...props}\n />\n </div>\n </section>\n );\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//#region src/components/Browser/extractUrlFromSitemap.ts
|
|
2
|
+
const fetchWithTimeout = (url, timeout = 5e3) => {
|
|
3
|
+
const controller = new AbortController();
|
|
4
|
+
const id = setTimeout(() => controller.abort(), timeout);
|
|
5
|
+
return fetch(url, { signal: controller.signal }).finally(() => clearTimeout(id));
|
|
6
|
+
};
|
|
7
|
+
const parseLocs = (xml) => {
|
|
8
|
+
return (xml.match(/<loc>([\s\S]*?)<\/loc>/g) ?? []).map((m) => m.replace(/<\/?loc>/g, "").trim()).filter(Boolean);
|
|
9
|
+
};
|
|
10
|
+
const fetchSitemapUrls = async (sitemapUrl, visited) => {
|
|
11
|
+
if (visited.has(sitemapUrl)) return [];
|
|
12
|
+
visited.add(sitemapUrl);
|
|
13
|
+
try {
|
|
14
|
+
const res = await fetchWithTimeout(sitemapUrl);
|
|
15
|
+
if (!res.ok) return [];
|
|
16
|
+
const xml = await res.text();
|
|
17
|
+
if (xml.includes("<sitemapindex")) {
|
|
18
|
+
const childUrls = parseLocs(xml);
|
|
19
|
+
return (await Promise.all(childUrls.map((url) => fetchSitemapUrls(url, visited)))).flat();
|
|
20
|
+
}
|
|
21
|
+
return parseLocs(xml);
|
|
22
|
+
} catch {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const extractUrlFromSitemap = async (pageUrl) => {
|
|
27
|
+
const origin = new URL(pageUrl).origin;
|
|
28
|
+
const candidateUrls = [];
|
|
29
|
+
try {
|
|
30
|
+
const res = await fetchWithTimeout(`${origin}/robots.txt`, 3e3);
|
|
31
|
+
if (res.ok) ((await res.text()).match(/^Sitemap:\s*(.+)$/gim) ?? []).forEach((m) => {
|
|
32
|
+
const url = m.replace(/^Sitemap:\s*/i, "").trim();
|
|
33
|
+
if (url) candidateUrls.push(url);
|
|
34
|
+
});
|
|
35
|
+
} catch {}
|
|
36
|
+
if (candidateUrls.length === 0) candidateUrls.push(`${origin}/sitemap.xml`);
|
|
37
|
+
const visited = /* @__PURE__ */ new Set();
|
|
38
|
+
const results = await Promise.all(candidateUrls.map((url) => fetchSitemapUrls(url, visited)));
|
|
39
|
+
return Array.from(new Set(results.flat())).sort();
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
export { extractUrlFromSitemap };
|
|
44
|
+
//# sourceMappingURL=extractUrlFromSitemap.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractUrlFromSitemap.mjs","names":[],"sources":["../../../../src/components/Browser/extractUrlFromSitemap.ts"],"sourcesContent":["const fetchWithTimeout = (url: string, timeout = 5000): Promise<Response> => {\n const controller = new AbortController();\n const id = setTimeout(() => controller.abort(), timeout);\n return fetch(url, { signal: controller.signal }).finally(() =>\n clearTimeout(id)\n );\n};\n\nconst parseLocs = (xml: string): string[] => {\n const matches = xml.match(/<loc>([\\s\\S]*?)<\\/loc>/g) ?? [];\n return matches.map((m) => m.replace(/<\\/?loc>/g, '').trim()).filter(Boolean);\n};\n\nconst fetchSitemapUrls = async (\n sitemapUrl: string,\n visited: Set<string>\n): Promise<string[]> => {\n if (visited.has(sitemapUrl)) return [];\n visited.add(sitemapUrl);\n\n try {\n const res = await fetchWithTimeout(sitemapUrl);\n if (!res.ok) return [];\n const xml = await res.text();\n\n if (xml.includes('<sitemapindex')) {\n const childUrls = parseLocs(xml);\n const results = await Promise.all(\n childUrls.map((url) => fetchSitemapUrls(url, visited))\n );\n return results.flat();\n }\n\n return parseLocs(xml);\n } catch {\n return [];\n }\n};\n\nexport const extractUrlFromSitemap = async (\n pageUrl: string\n): Promise<string[]> => {\n const origin = new URL(pageUrl).origin;\n const candidateUrls: string[] = [];\n\n try {\n const res = await fetchWithTimeout(`${origin}/robots.txt`, 3000);\n if (res.ok) {\n const text = await res.text();\n const matches = text.match(/^Sitemap:\\s*(.+)$/gim) ?? [];\n matches.forEach((m) => {\n const url = m.replace(/^Sitemap:\\s*/i, '').trim();\n if (url) candidateUrls.push(url);\n });\n }\n } catch {\n // Ignore network / CORS errors for robots.txt\n }\n\n if (candidateUrls.length === 0) {\n candidateUrls.push(`${origin}/sitemap.xml`);\n }\n\n const visited = new Set<string>();\n const results = await Promise.all(\n candidateUrls.map((url) => fetchSitemapUrls(url, visited))\n );\n\n return Array.from(new Set(results.flat())).sort();\n};\n"],"mappings":";AAAA,MAAM,oBAAoB,KAAa,UAAU,QAA4B;CAC3E,MAAM,aAAa,IAAI,gBAAgB;CACvC,MAAM,KAAK,iBAAiB,WAAW,MAAM,GAAG,OAAO;CACvD,OAAO,MAAM,KAAK,EAAE,QAAQ,WAAW,OAAO,CAAC,EAAE,cAC/C,aAAa,EAAE,CACjB;AACF;AAEA,MAAM,aAAa,QAA0B;CAE3C,QADgB,IAAI,MAAM,yBAAyB,KAAK,CAAC,GAC1C,KAAK,MAAM,EAAE,QAAQ,aAAa,EAAE,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAC7E;AAEA,MAAM,mBAAmB,OACvB,YACA,YACsB;CACtB,IAAI,QAAQ,IAAI,UAAU,GAAG,OAAO,CAAC;CACrC,QAAQ,IAAI,UAAU;CAEtB,IAAI;EACF,MAAM,MAAM,MAAM,iBAAiB,UAAU;EAC7C,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC;EACrB,MAAM,MAAM,MAAM,IAAI,KAAK;EAE3B,IAAI,IAAI,SAAS,eAAe,GAAG;GACjC,MAAM,YAAY,UAAU,GAAG;GAI/B,QAAO,MAHe,QAAQ,IAC5B,UAAU,KAAK,QAAQ,iBAAiB,KAAK,OAAO,CAAC,CACvD,GACe,KAAK;EACtB;EAEA,OAAO,UAAU,GAAG;CACtB,QAAQ;EACN,OAAO,CAAC;CACV;AACF;AAEA,MAAa,wBAAwB,OACnC,YACsB;CACtB,MAAM,SAAS,IAAI,IAAI,OAAO,EAAE;CAChC,MAAM,gBAA0B,CAAC;CAEjC,IAAI;EACF,MAAM,MAAM,MAAM,iBAAiB,GAAG,OAAO,cAAc,GAAI;EAC/D,IAAI,IAAI,IAGN,EADgB,MADG,IAAI,KAAK,GACP,MAAM,sBAAsB,KAAK,CAAC,GAC/C,SAAS,MAAM;GACrB,MAAM,MAAM,EAAE,QAAQ,iBAAiB,EAAE,EAAE,KAAK;GAChD,IAAI,KAAK,cAAc,KAAK,GAAG;EACjC,CAAC;CAEL,QAAQ,CAER;CAEA,IAAI,cAAc,WAAW,GAC3B,cAAc,KAAK,GAAG,OAAO,aAAa;CAG5C,MAAM,0BAAU,IAAI,IAAY;CAChC,MAAM,UAAU,MAAM,QAAQ,IAC5B,cAAc,KAAK,QAAQ,iBAAiB,KAAK,OAAO,CAAC,CAC3D;CAEA,OAAO,MAAM,KAAK,IAAI,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,KAAK;AAClD"}
|
|
@@ -9,6 +9,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
9
9
|
* Button size variants for different use cases
|
|
10
10
|
*/
|
|
11
11
|
let ButtonSize = /* @__PURE__ */ function(ButtonSize) {
|
|
12
|
+
ButtonSize["XS"] = "xs";
|
|
12
13
|
ButtonSize["SM"] = "sm";
|
|
13
14
|
ButtonSize["MD"] = "md";
|
|
14
15
|
ButtonSize["LG"] = "lg";
|
|
@@ -21,14 +22,15 @@ let ButtonSize = /* @__PURE__ */ function(ButtonSize) {
|
|
|
21
22
|
}({});
|
|
22
23
|
const buttonIconVariants = cva("flex-none shrink-0", {
|
|
23
24
|
variants: { size: {
|
|
25
|
+
[`xs`]: "size-2",
|
|
24
26
|
[`sm`]: "size-3",
|
|
25
27
|
[`md`]: "size-4",
|
|
26
28
|
[`lg`]: "size-5",
|
|
27
29
|
[`xl`]: "size-6",
|
|
28
30
|
[`icon-sm`]: "size-3",
|
|
29
31
|
[`icon-md`]: "size-4",
|
|
30
|
-
[`icon-lg`]: "size-
|
|
31
|
-
[`icon-xl`]: "size-
|
|
32
|
+
[`icon-lg`]: "size-5",
|
|
33
|
+
[`icon-xl`]: "size-6"
|
|
32
34
|
} },
|
|
33
35
|
defaultVariants: { size: "md" }
|
|
34
36
|
});
|
|
@@ -80,13 +82,14 @@ let ButtonTextAlign = /* @__PURE__ */ function(ButtonTextAlign) {
|
|
|
80
82
|
const buttonVariants = cva("relative inline-flex cursor-pointer items-center justify-center font-medium ring-0 transition-all duration-300 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50", {
|
|
81
83
|
variants: {
|
|
82
84
|
size: {
|
|
85
|
+
[`xs`]: "min-h-7 px-3 text-xs max-md:py-1",
|
|
83
86
|
[`sm`]: "min-h-7 px-3 text-xs max-md:py-1",
|
|
84
87
|
[`md`]: "min-h-8 px-6 text-sm max-md:py-2",
|
|
85
88
|
[`lg`]: "min-h-10 px-8 text-lg max-md:py-3",
|
|
86
89
|
[`xl`]: "min-h-11 px-10 text-xl max-md:py-4",
|
|
87
90
|
[`icon-sm`]: "p-1.5",
|
|
88
91
|
[`icon-md`]: "p-1.5",
|
|
89
|
-
[`icon-lg`]: "p-
|
|
92
|
+
[`icon-lg`]: "p-1.5",
|
|
90
93
|
[`icon-xl`]: "p-3"
|
|
91
94
|
},
|
|
92
95
|
color: {
|
|
@@ -253,7 +256,7 @@ const Button = ({ variant, size, color, children, Icon, IconRight, iconClassName
|
|
|
253
256
|
"aria-hidden": "true"
|
|
254
257
|
}),
|
|
255
258
|
/* @__PURE__ */ jsx("div", {
|
|
256
|
-
className: cn("flex items-center justify-center transition-[width] duration-300", isLoading && size === "sm" && "w-3", isLoading && size === "md" && "w-4", isLoading && size === "lg" && "w-
|
|
259
|
+
className: cn("flex items-center justify-center transition-[width] duration-300", isLoading && size === "sm" && "w-3", isLoading && size === "md" && "w-4", isLoading && size === "lg" && "w-6", isLoading && size === "xl" && "w-8"),
|
|
257
260
|
children: /* @__PURE__ */ jsx(Loader, {
|
|
258
261
|
className: buttonIconVariants({
|
|
259
262
|
size,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.mjs","names":[],"sources":["../../../../src/components/Button/Button.tsx"],"sourcesContent":["import { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport type { LucideIcon } from 'lucide-react';\nimport type { ButtonHTMLAttributes, DetailedHTMLProps, FC } from 'react';\nimport { ContainerRoundedSize as ButtonRoundedSize } from '../Container';\nimport { Loader } from '../Loader';\n\n/**\n * Button size variants for different use cases\n */\nexport enum ButtonSize {\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n ICON_SM = 'icon-sm',\n ICON_MD = 'icon-md',\n ICON_LG = 'icon-lg',\n ICON_XL = 'icon-xl',\n}\n\nconst buttonIconVariants = cva('flex-none shrink-0', {\n variants: {\n size: {\n [`${ButtonSize.SM}`]: 'size-3',\n [`${ButtonSize.MD}`]: 'size-4',\n [`${ButtonSize.LG}`]: 'size-5',\n [`${ButtonSize.XL}`]: 'size-6',\n [`${ButtonSize.ICON_SM}`]: 'size-3',\n [`${ButtonSize.ICON_MD}`]: 'size-4',\n [`${ButtonSize.ICON_LG}`]: 'size-4',\n [`${ButtonSize.ICON_XL}`]: 'size-5',\n },\n },\n defaultVariants: {\n size: ButtonSize.MD,\n },\n});\n\n/**\n * Button visual style variants\n */\nexport enum ButtonVariant {\n DEFAULT = 'default',\n NONE = 'none',\n OUTLINE = 'outline',\n LINK = 'link',\n INVISIBLE_LINK = 'invisible-link',\n HOVERABLE = 'hoverable',\n FADE = 'fade',\n INPUT = 'input',\n}\n\n/**\n * Button color themes that work with the design system\n */\nexport enum ButtonColor {\n PRIMARY = 'primary',\n SECONDARY = 'secondary',\n DESTRUCTIVE = 'destructive',\n NEUTRAL = 'neutral',\n LIGHT = 'light',\n DARK = 'dark',\n TEXT = 'text',\n CARD = 'card',\n TEXT_INVERSE = 'text-inverse',\n CURRENT = 'current',\n ERROR = 'error',\n SUCCESS = 'success',\n CUSTOM = 'custom',\n}\n\n/**\n * Text alignment options for button content\n */\nexport enum ButtonTextAlign {\n LEFT = 'left',\n CENTER = 'center',\n RIGHT = 'right',\n}\n\n/**\n * Enhanced button variants with improved accessibility and focus states\n */\nexport const buttonVariants = cva(\n 'relative inline-flex cursor-pointer items-center justify-center font-medium ring-0 transition-all duration-300 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n size: {\n [`${ButtonSize.SM}`]: 'min-h-7 px-3 text-xs max-md:py-1',\n [`${ButtonSize.MD}`]: 'min-h-8 px-6 text-sm max-md:py-2',\n [`${ButtonSize.LG}`]: 'min-h-10 px-8 text-lg max-md:py-3',\n [`${ButtonSize.XL}`]: 'min-h-11 px-10 text-xl max-md:py-4',\n [`${ButtonSize.ICON_SM}`]: 'p-1.5',\n [`${ButtonSize.ICON_MD}`]: 'p-1.5',\n [`${ButtonSize.ICON_LG}`]: 'p-2',\n [`${ButtonSize.ICON_XL}`]: 'p-3',\n },\n color: {\n [`${ButtonColor.PRIMARY}`]:\n 'hover-primary-500/20 text-primary ring-primary-500/20 *:text-text-light',\n [`${ButtonColor.SECONDARY}`]:\n 'hover-secondary-500/20 text-secondary ring-secondary-500/20 *:text-text-light',\n [`${ButtonColor.DESTRUCTIVE}`]:\n 'hover-destructive-500/20 text-destructive ring-destructive-500/20 *:text-text-light',\n [`${ButtonColor.NEUTRAL}`]:\n 'text-neutral ring-neutral-500/5 *:text-text-light',\n [`${ButtonColor.CARD}`]:\n 'hover-card-500/20 text-card ring-card-500/20 *:text-text-light',\n [`${ButtonColor.LIGHT}`]:\n 'hover-white-500/20 text-white ring-white/20 *:text-text-light',\n [`${ButtonColor.DARK}`]:\n 'text-neutral-800 ring-text-light/50 *:text-text-light',\n [`${ButtonColor.TEXT}`]: 'text-text ring-text/20 *:text-text-opposite',\n [`${ButtonColor.CURRENT}`]:\n 'hover-current-500/10 text-current ring-current/10 *:text-text-light',\n [`${ButtonColor.TEXT_INVERSE}`]:\n 'text-text-opposite ring-text-opposite/20 *:text-text',\n [`${ButtonColor.ERROR}`]:\n 'hover-error-500/20 text-error ring-error/20 *:text-text-light',\n [`${ButtonColor.SUCCESS}`]:\n 'hover-success-500/20 text-success ring-success/20 *:text-text-light',\n [`${ButtonColor.CUSTOM}`]: '',\n },\n roundedSize: {\n [`${ButtonRoundedSize.NONE}`]: 'rounded-none',\n [`${ButtonRoundedSize.SM}`]:\n 'rounded-lg [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-xl',\n [`${ButtonRoundedSize.MD}`]:\n 'rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl',\n [`${ButtonRoundedSize.LG}`]:\n 'rounded-2xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-3xl',\n [`${ButtonRoundedSize.XL}`]:\n 'rounded-3xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-4xl',\n [`${ButtonRoundedSize['2xl']}`]:\n 'rounded-4xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[2.5rem]',\n [`${ButtonRoundedSize['3xl']}`]:\n 'rounded-[2.5rem] [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[3rem]',\n [`${ButtonRoundedSize['4xl']}`]:\n 'rounded-[3rem] [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[4rem]',\n [`${ButtonRoundedSize['5xl']}`]:\n 'rounded-[4rem] [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[5rem]',\n [`${ButtonRoundedSize.FULL}`]: 'rounded-full',\n },\n variant: {\n [`${ButtonVariant.DEFAULT}`]: [\n 'bg-current',\n 'hover:bg-current/90',\n 'hover:ring-5',\n 'aria-selected:ring-5',\n ],\n\n [`${ButtonVariant.OUTLINE}`]: [\n 'rounded-2xl border-[1.3px] border-current bg-current/0 *:text-current!',\n 'hover:bg-current/20 focus-visible:bg-current/20',\n 'hover:ring-5 focus-visible:ring-5',\n 'aria-selected:ring-5',\n ],\n\n [`${ButtonVariant.NONE}`]:\n 'border-none bg-current/0 text-inherit hover:bg-current/0',\n\n [`${ButtonVariant.LINK}`]:\n 'h-auto justify-start border-inherit bg-transparent px-1 underline-offset-4 *:text-current! hover:bg-transparent hover:underline',\n\n [`${ButtonVariant.INVISIBLE_LINK}`]:\n 'h-auto justify-start border-inherit bg-transparent px-1 underline-offset-4 *:text-current! hover:bg-transparent',\n\n [`${ButtonVariant.HOVERABLE}`]:\n 'rounded-lg border-none bg-current/0 transition *:text-current! hover:bg-current/20 aria-[current]:bg-current/5',\n\n [`${ButtonVariant.FADE}`]: [\n 'rounded-lg border-none bg-current/10 ring-current/5 transition *:text-current! hover:bg-current/20 aria-[current]:bg-current/5',\n 'hover:ring-5 focus-visible:ring-5',\n 'aria-selected:ring-5',\n ],\n [`${ButtonVariant.INPUT}`]: [\n // base styles\n 'text-text',\n 'w-full select-text resize-none rounded-2xl text-base shadow-none outline-none supports-[corner-shape:squircle]:rounded-4xl',\n 'transition-shadow duration-100 md:text-sm',\n 'ring-0', // base ring\n 'disabled:opacity-50',\n\n 'text-text',\n 'bg-neutral-50 dark:bg-neutral-950',\n 'ring-neutral-100 dark:ring-neutral-700',\n\n // Hover ring (similar spirit to your input)\n 'hover:ring-3', // width\n 'aria-selected:ring-4',\n 'focus-visible:ring-3',\n 'disabled:ring-0',\n\n // Focus ring + animation\n 'focus-visible:outline-none',\n\n // Remove any weird box-shadow\n '[box-shadow:none] focus:[box-shadow:none]',\n\n // aria-invalid border color\n 'aria-invalid:border-error',\n ],\n },\n\n textAlign: {\n [`${ButtonTextAlign.LEFT}`]: 'justify-start text-left',\n [`${ButtonTextAlign.CENTER}`]: 'justify-center text-center',\n [`${ButtonTextAlign.RIGHT}`]: 'justify-end text-right',\n },\n\n isFullWidth: {\n true: 'w-full',\n false: '',\n },\n },\n defaultVariants: {\n variant: `${ButtonVariant.DEFAULT}`,\n size: `${ButtonSize.MD}`,\n color: `${ButtonColor.CUSTOM}`,\n roundedSize: `${ButtonRoundedSize.MD}`,\n textAlign: `${ButtonTextAlign.CENTER}`,\n isFullWidth: false,\n },\n }\n);\n\n/**\n * Enhanced Button component props with comprehensive type safety and accessibility features\n */\nexport type ButtonProps = DetailedHTMLProps<\n ButtonHTMLAttributes<HTMLButtonElement>,\n HTMLButtonElement\n> &\n VariantProps<typeof buttonVariants> & {\n /**\n * Accessible label for screen readers and assistive technologies.\n * This is required for accessibility compliance.\n */\n label: string | null;\n\n /**\n * Optional icon to display on the left side of the button\n */\n Icon?: FC | LucideIcon;\n\n /**\n * Optional icon to display on the right side of the button\n */\n IconRight?: FC | LucideIcon;\n\n /**\n * Additional CSS classes for icon styling\n */\n iconClassName?: string;\n\n /**\n * Shows loading spinner and disables button interaction when true\n */\n isLoading?: boolean;\n\n /**\n * Marks the button as active (useful for navigation or toggle states)\n */\n isActive?: boolean;\n\n /**\n * Marks the button as selected\n */\n isSelected?: boolean;\n\n /**\n * Makes the button span the full width of its container\n */\n isFullWidth?: boolean;\n\n /**\n * Additional description for complex buttons (optional)\n */\n 'aria-describedby'?: string;\n\n /**\n * Expanded state for collapsible sections (optional)\n */\n 'aria-expanded'?: boolean;\n\n /**\n * Controls whether the button has popup/menu (optional)\n */\n 'aria-haspopup'?:\n | boolean\n | 'true'\n | 'false'\n | 'menu'\n | 'listbox'\n | 'tree'\n | 'grid'\n | 'dialog';\n\n /**\n * Indicates if button controls are currently pressed (for toggle buttons)\n */\n 'aria-pressed'?: boolean;\n };\n\n/**\n * Button Component - A comprehensive, accessible button component\n *\n * Features:\n * - Full accessibility compliance with ARIA attributes\n * - Multiple variants and sizes for different use cases\n * - Icon support (left and right positioning)\n * - Loading states with spinner\n * - Keyboard navigation support\n * - Focus management with visible indicators\n * - Responsive design adaptations\n *\n * @example\n * ```tsx\n * // Basic button\n * <Button label=\"Click me\">Click me</Button>\n *\n * // Button with icon and loading state\n * <Button\n * label=\"Save document\"\n * Icon={SaveIcon}\n * isLoading={saving}\n * disabled={!hasChanges}\n * >\n * Save\n * </Button>\n *\n * // Destructive action button\n * <Button\n * variant={`${ButtonVariant.OUTLINE}`}\n * color={ButtonColor.DESTRUCTIVE}\n * label=\"Delete item permanently\"\n * aria-describedby=\"delete-warning\"\n * >\n * Delete\n * </Button>\n * ```\n */\nexport const Button: FC<ButtonProps> = ({\n variant,\n size,\n color,\n children,\n Icon,\n IconRight,\n iconClassName,\n isLoading = false,\n isActive,\n isSelected,\n isFullWidth,\n roundedSize,\n textAlign,\n disabled,\n label,\n className,\n type = 'button',\n 'aria-describedby': ariaDescribedBy,\n 'aria-expanded': ariaExpanded,\n 'aria-haspopup': ariaHasPopup,\n 'aria-pressed': ariaPressed,\n ...props\n}) => {\n const isLink =\n variant === `${ButtonVariant.LINK}` ||\n variant === `${ButtonVariant.INVISIBLE_LINK}`;\n const isIconOnly = !children && (Icon || IconRight);\n\n const accessibilityProps = {\n 'aria-label': isIconOnly ? (label ?? undefined) : undefined,\n 'aria-labelledby': !isIconOnly ? undefined : undefined,\n 'aria-describedby': ariaDescribedBy,\n 'aria-expanded': ariaExpanded,\n 'aria-haspopup': ariaHasPopup,\n 'aria-pressed': isActive !== undefined ? isActive : ariaPressed,\n 'aria-busy': isLoading,\n 'aria-current': (isActive ? 'page' : undefined) as 'page' | undefined,\n 'aria-disabled': disabled || isLoading,\n 'aria-selected': isSelected,\n };\n\n const isSquareButton =\n size === ButtonSize.ICON_SM ||\n size === ButtonSize.ICON_MD ||\n size === ButtonSize.ICON_LG ||\n size === ButtonSize.ICON_XL;\n\n return (\n <button\n disabled={isLoading || disabled}\n role={isLink ? 'link' : 'button'}\n type={type}\n className={buttonVariants({\n variant,\n size,\n color,\n isFullWidth,\n roundedSize,\n textAlign:\n textAlign ??\n (IconRight ? ButtonTextAlign.LEFT : ButtonTextAlign.CENTER),\n className,\n })}\n {...accessibilityProps}\n {...props}\n >\n {Icon && !isLoading && (\n <Icon\n className={buttonIconVariants({\n size,\n className: cn(!isSquareButton && 'mr-3', iconClassName),\n })}\n aria-hidden=\"true\"\n />\n )}\n\n <div\n className={cn(\n 'flex items-center justify-center transition-[width] duration-300',\n isLoading && size === ButtonSize.SM && 'w-3',\n isLoading && size === ButtonSize.MD && 'w-4',\n isLoading && size === ButtonSize.LG && 'w-5',\n isLoading && size === ButtonSize.XL && 'w-6'\n )}\n >\n <Loader\n className={buttonIconVariants({\n size,\n className: cn(!isSquareButton && 'mr-3', iconClassName),\n })}\n isLoading={isLoading}\n aria-hidden=\"true\"\n data-testid=\"loader\"\n />\n </div>\n\n {children && (\n <span className=\"flex-1 truncate whitespace-nowrap\">{children}</span>\n )}\n\n {!children && isIconOnly && <span className=\"sr-only\">{label}</span>}\n\n {IconRight && (\n <IconRight\n className={buttonIconVariants({\n size,\n className: cn(!isSquareButton && 'ml-3', iconClassName),\n })}\n aria-hidden=\"true\"\n />\n )}\n </button>\n );\n};\n"],"mappings":";;;;;;;;;;AAUA,IAAY,aAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;KACD;AAED,MAAM,qBAAqB,IAAI,sBAAsB;CACnD,UAAU,EACR,MAAM;GACH,OAAqB;GACrB,OAAqB;GACrB,OAAqB;GACrB,OAAqB;GACrB,YAA0B;GAC1B,YAA0B;GAC1B,YAA0B;GAC1B,YAA0B;EAC5B,EACF;CACD,iBAAiB,EACf,YACD;CACF,CAAC;;;;AAKF,IAAY,gBAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;KACD;;;;AAKD,IAAY,cAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;KACD;;;;AAKD,IAAY,kBAAL;CACL;CACA;CACA;;KACD;;;;AAKD,MAAa,iBAAiB,IAC5B,8LACA;CACE,UAAU;EACR,MAAM;IACH,OAAqB;IACrB,OAAqB;IACrB,OAAqB;IACrB,OAAqB;IACrB,YAA0B;IAC1B,YAA0B;IAC1B,YAA0B;IAC1B,YAA0B;GAC5B;EACD,OAAO;IACJ,YACC;IACD,cACC;IACD,gBACC;IACD,YACC;IACD,SACC;IACD,UACC;IACD,SACC;IACD,SAAwB;IACxB,YACC;IACD,iBACC;IACD,UACC;IACD,YACC;IACD,WAA0B;GAC5B;EACD,aAAa;IACV,cAA8B;IAC9B,YACC;IACD,YACC;IACD,YACC;IACD,YACC;IACD,aACC;IACD,aACC;IACD,aACC;IACD,aACC;IACD,cAA8B;GAChC;EACD,SAAS;IACN,YAA6B;IAC5B;IACA;IACA;IACA;IACD;IAEA,YAA6B;IAC5B;IACA;IACA;IACA;IACD;IAEA,SACC;IAED,SACC;IAED,mBACC;IAED,cACC;IAED,SAA0B;IACzB;IACA;IACA;IACD;IACA,UAA2B;IAE1B;IACA;IACA;IACA;IACA;IAEA;IACA;IACA;IAGA;IACA;IACA;IACA;IAGA;IAGA;IAGA;IACD;GACF;EAED,WAAW;IACR,SAA4B;IAC5B,WAA8B;IAC9B,UAA6B;GAC/B;EAED,aAAa;GACX,MAAM;GACN,OAAO;GACR;EACF;CACD,iBAAiB;EACf,SAAS;EACT,MAAM;EACN,OAAO;EACP,aAAa;EACb,WAAW;EACX,aAAa;EACd;CACF,CACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsHD,MAAa,UAA2B,EACtC,SACA,MACA,OACA,UACA,MACA,WACA,eACA,YAAY,OACZ,UACA,YACA,aACA,aACA,WACA,UACA,OACA,WACA,OAAO,UACP,oBAAoB,iBACpB,iBAAiB,cACjB,iBAAiB,cACjB,gBAAgB,aAChB,GAAG,YACC;CACJ,MAAM,SACJ,YAAY,UACZ,YAAY;CACd,MAAM,aAAa,CAAC,aAAa,QAAQ;CAEzC,MAAM,qBAAqB;EACzB,cAAc,aAAc,SAAS,SAAa;EAClD,mBAAmB,CAAC,aAAa,SAAY;EAC7C,oBAAoB;EACpB,iBAAiB;EACjB,iBAAiB;EACjB,gBAAgB,aAAa,SAAY,WAAW;EACpD,aAAa;EACb,gBAAiB,WAAW,SAAS;EACrC,iBAAiB,YAAY;EAC7B,iBAAiB;EAClB;CAED,MAAM,iBACJ,sBACA,sBACA,sBACA;CAEF,OACE,qBAAC,UAAD;EACE,UAAU,aAAa;EACvB,MAAM,SAAS,SAAS;EAClB;EACN,WAAW,eAAe;GACxB;GACA;GACA;GACA;GACA;GACA,WACE,cACC;GACH;GACD,CAAC;EACF,GAAI;EACJ,GAAI;YAhBN;GAkBG,QAAQ,CAAC,aACR,oBAAC,MAAD;IACE,WAAW,mBAAmB;KAC5B;KACA,WAAW,GAAG,CAAC,kBAAkB,QAAQ,cAAc;KACxD,CAAC;IACF,eAAY;IACZ;GAGJ,oBAAC,OAAD;IACE,WAAW,GACT,oEACA,aAAa,iBAA0B,OACvC,aAAa,iBAA0B,OACvC,aAAa,iBAA0B,OACvC,aAAa,iBAA0B,MACxC;cAED,oBAAC,QAAD;KACE,WAAW,mBAAmB;MAC5B;MACA,WAAW,GAAG,CAAC,kBAAkB,QAAQ,cAAc;MACxD,CAAC;KACS;KACX,eAAY;KACZ,eAAY;KACZ;IACE;GAEL,YACC,oBAAC,QAAD;IAAM,WAAU;IAAqC;IAAgB;GAGtE,CAAC,YAAY,cAAc,oBAAC,QAAD;IAAM,WAAU;cAAW;IAAa;GAEnE,aACC,oBAAC,WAAD;IACE,WAAW,mBAAmB;KAC5B;KACA,WAAW,GAAG,CAAC,kBAAkB,QAAQ,cAAc;KACxD,CAAC;IACF,eAAY;IACZ;GAEG"}
|
|
1
|
+
{"version":3,"file":"Button.mjs","names":[],"sources":["../../../../src/components/Button/Button.tsx"],"sourcesContent":["import { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport type { LucideIcon } from 'lucide-react';\nimport type { ButtonHTMLAttributes, DetailedHTMLProps, FC } from 'react';\nimport { ContainerRoundedSize as ButtonRoundedSize } from '../Container';\nimport { Loader } from '../Loader';\n\n/**\n * Button size variants for different use cases\n */\nexport enum ButtonSize {\n XS = 'xs',\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n ICON_SM = 'icon-sm',\n ICON_MD = 'icon-md',\n ICON_LG = 'icon-lg',\n ICON_XL = 'icon-xl',\n}\n\nconst buttonIconVariants = cva('flex-none shrink-0', {\n variants: {\n size: {\n [`${ButtonSize.XS}`]: 'size-2',\n [`${ButtonSize.SM}`]: 'size-3',\n [`${ButtonSize.MD}`]: 'size-4',\n [`${ButtonSize.LG}`]: 'size-5',\n [`${ButtonSize.XL}`]: 'size-6',\n [`${ButtonSize.ICON_SM}`]: 'size-3',\n [`${ButtonSize.ICON_MD}`]: 'size-4',\n [`${ButtonSize.ICON_LG}`]: 'size-5',\n [`${ButtonSize.ICON_XL}`]: 'size-6',\n },\n },\n defaultVariants: {\n size: ButtonSize.MD,\n },\n});\n\n/**\n * Button visual style variants\n */\nexport enum ButtonVariant {\n DEFAULT = 'default',\n NONE = 'none',\n OUTLINE = 'outline',\n LINK = 'link',\n INVISIBLE_LINK = 'invisible-link',\n HOVERABLE = 'hoverable',\n FADE = 'fade',\n INPUT = 'input',\n}\n\n/**\n * Button color themes that work with the design system\n */\nexport enum ButtonColor {\n PRIMARY = 'primary',\n SECONDARY = 'secondary',\n DESTRUCTIVE = 'destructive',\n NEUTRAL = 'neutral',\n LIGHT = 'light',\n DARK = 'dark',\n TEXT = 'text',\n CARD = 'card',\n TEXT_INVERSE = 'text-inverse',\n CURRENT = 'current',\n ERROR = 'error',\n SUCCESS = 'success',\n CUSTOM = 'custom',\n}\n\n/**\n * Text alignment options for button content\n */\nexport enum ButtonTextAlign {\n LEFT = 'left',\n CENTER = 'center',\n RIGHT = 'right',\n}\n\n/**\n * Enhanced button variants with improved accessibility and focus states\n */\nexport const buttonVariants = cva(\n 'relative inline-flex cursor-pointer items-center justify-center font-medium ring-0 transition-all duration-300 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n size: {\n [`${ButtonSize.XS}`]: 'min-h-7 px-3 text-xs max-md:py-1',\n [`${ButtonSize.SM}`]: 'min-h-7 px-3 text-xs max-md:py-1',\n [`${ButtonSize.MD}`]: 'min-h-8 px-6 text-sm max-md:py-2',\n [`${ButtonSize.LG}`]: 'min-h-10 px-8 text-lg max-md:py-3',\n [`${ButtonSize.XL}`]: 'min-h-11 px-10 text-xl max-md:py-4',\n [`${ButtonSize.ICON_SM}`]: 'p-1.5',\n [`${ButtonSize.ICON_MD}`]: 'p-1.5',\n [`${ButtonSize.ICON_LG}`]: 'p-1.5',\n [`${ButtonSize.ICON_XL}`]: 'p-3',\n },\n color: {\n [`${ButtonColor.PRIMARY}`]:\n 'hover-primary-500/20 text-primary ring-primary-500/20 *:text-text-light',\n [`${ButtonColor.SECONDARY}`]:\n 'hover-secondary-500/20 text-secondary ring-secondary-500/20 *:text-text-light',\n [`${ButtonColor.DESTRUCTIVE}`]:\n 'hover-destructive-500/20 text-destructive ring-destructive-500/20 *:text-text-light',\n [`${ButtonColor.NEUTRAL}`]:\n 'text-neutral ring-neutral-500/5 *:text-text-light',\n [`${ButtonColor.CARD}`]:\n 'hover-card-500/20 text-card ring-card-500/20 *:text-text-light',\n [`${ButtonColor.LIGHT}`]:\n 'hover-white-500/20 text-white ring-white/20 *:text-text-light',\n [`${ButtonColor.DARK}`]:\n 'text-neutral-800 ring-text-light/50 *:text-text-light',\n [`${ButtonColor.TEXT}`]: 'text-text ring-text/20 *:text-text-opposite',\n [`${ButtonColor.CURRENT}`]:\n 'hover-current-500/10 text-current ring-current/10 *:text-text-light',\n [`${ButtonColor.TEXT_INVERSE}`]:\n 'text-text-opposite ring-text-opposite/20 *:text-text',\n [`${ButtonColor.ERROR}`]:\n 'hover-error-500/20 text-error ring-error/20 *:text-text-light',\n [`${ButtonColor.SUCCESS}`]:\n 'hover-success-500/20 text-success ring-success/20 *:text-text-light',\n [`${ButtonColor.CUSTOM}`]: '',\n },\n roundedSize: {\n [`${ButtonRoundedSize.NONE}`]: 'rounded-none',\n [`${ButtonRoundedSize.SM}`]:\n 'rounded-lg [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-xl',\n [`${ButtonRoundedSize.MD}`]:\n 'rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl',\n [`${ButtonRoundedSize.LG}`]:\n 'rounded-2xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-3xl',\n [`${ButtonRoundedSize.XL}`]:\n 'rounded-3xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-4xl',\n [`${ButtonRoundedSize['2xl']}`]:\n 'rounded-4xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[2.5rem]',\n [`${ButtonRoundedSize['3xl']}`]:\n 'rounded-[2.5rem] [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[3rem]',\n [`${ButtonRoundedSize['4xl']}`]:\n 'rounded-[3rem] [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[4rem]',\n [`${ButtonRoundedSize['5xl']}`]:\n 'rounded-[4rem] [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[5rem]',\n [`${ButtonRoundedSize.FULL}`]: 'rounded-full',\n },\n variant: {\n [`${ButtonVariant.DEFAULT}`]: [\n 'bg-current',\n 'hover:bg-current/90',\n 'hover:ring-5',\n 'aria-selected:ring-5',\n ],\n\n [`${ButtonVariant.OUTLINE}`]: [\n 'rounded-2xl border-[1.3px] border-current bg-current/0 *:text-current!',\n 'hover:bg-current/20 focus-visible:bg-current/20',\n 'hover:ring-5 focus-visible:ring-5',\n 'aria-selected:ring-5',\n ],\n\n [`${ButtonVariant.NONE}`]:\n 'border-none bg-current/0 text-inherit hover:bg-current/0',\n\n [`${ButtonVariant.LINK}`]:\n 'h-auto justify-start border-inherit bg-transparent px-1 underline-offset-4 *:text-current! hover:bg-transparent hover:underline',\n\n [`${ButtonVariant.INVISIBLE_LINK}`]:\n 'h-auto justify-start border-inherit bg-transparent px-1 underline-offset-4 *:text-current! hover:bg-transparent',\n\n [`${ButtonVariant.HOVERABLE}`]:\n 'rounded-lg border-none bg-current/0 transition *:text-current! hover:bg-current/20 aria-[current]:bg-current/5',\n\n [`${ButtonVariant.FADE}`]: [\n 'rounded-lg border-none bg-current/10 ring-current/5 transition *:text-current! hover:bg-current/20 aria-[current]:bg-current/5',\n 'hover:ring-5 focus-visible:ring-5',\n 'aria-selected:ring-5',\n ],\n [`${ButtonVariant.INPUT}`]: [\n // base styles\n 'text-text',\n 'w-full select-text resize-none rounded-2xl text-base shadow-none outline-none supports-[corner-shape:squircle]:rounded-4xl',\n 'transition-shadow duration-100 md:text-sm',\n 'ring-0', // base ring\n 'disabled:opacity-50',\n\n 'text-text',\n 'bg-neutral-50 dark:bg-neutral-950',\n 'ring-neutral-100 dark:ring-neutral-700',\n\n // Hover ring (similar spirit to your input)\n 'hover:ring-3', // width\n 'aria-selected:ring-4',\n 'focus-visible:ring-3',\n 'disabled:ring-0',\n\n // Focus ring + animation\n 'focus-visible:outline-none',\n\n // Remove any weird box-shadow\n '[box-shadow:none] focus:[box-shadow:none]',\n\n // aria-invalid border color\n 'aria-invalid:border-error',\n ],\n },\n\n textAlign: {\n [`${ButtonTextAlign.LEFT}`]: 'justify-start text-left',\n [`${ButtonTextAlign.CENTER}`]: 'justify-center text-center',\n [`${ButtonTextAlign.RIGHT}`]: 'justify-end text-right',\n },\n\n isFullWidth: {\n true: 'w-full',\n false: '',\n },\n },\n defaultVariants: {\n variant: `${ButtonVariant.DEFAULT}`,\n size: `${ButtonSize.MD}`,\n color: `${ButtonColor.CUSTOM}`,\n roundedSize: `${ButtonRoundedSize.MD}`,\n textAlign: `${ButtonTextAlign.CENTER}`,\n isFullWidth: false,\n },\n }\n);\n\n/**\n * Enhanced Button component props with comprehensive type safety and accessibility features\n */\nexport type ButtonProps = DetailedHTMLProps<\n ButtonHTMLAttributes<HTMLButtonElement>,\n HTMLButtonElement\n> &\n VariantProps<typeof buttonVariants> & {\n /**\n * Accessible label for screen readers and assistive technologies.\n * This is required for accessibility compliance.\n */\n label: string | null;\n\n /**\n * Optional icon to display on the left side of the button\n */\n Icon?: FC | LucideIcon;\n\n /**\n * Optional icon to display on the right side of the button\n */\n IconRight?: FC | LucideIcon;\n\n /**\n * Additional CSS classes for icon styling\n */\n iconClassName?: string;\n\n /**\n * Shows loading spinner and disables button interaction when true\n */\n isLoading?: boolean;\n\n /**\n * Marks the button as active (useful for navigation or toggle states)\n */\n isActive?: boolean;\n\n /**\n * Marks the button as selected\n */\n isSelected?: boolean;\n\n /**\n * Makes the button span the full width of its container\n */\n isFullWidth?: boolean;\n\n /**\n * Additional description for complex buttons (optional)\n */\n 'aria-describedby'?: string;\n\n /**\n * Expanded state for collapsible sections (optional)\n */\n 'aria-expanded'?: boolean;\n\n /**\n * Controls whether the button has popup/menu (optional)\n */\n 'aria-haspopup'?:\n | boolean\n | 'true'\n | 'false'\n | 'menu'\n | 'listbox'\n | 'tree'\n | 'grid'\n | 'dialog';\n\n /**\n * Indicates if button controls are currently pressed (for toggle buttons)\n */\n 'aria-pressed'?: boolean;\n };\n\n/**\n * Button Component - A comprehensive, accessible button component\n *\n * Features:\n * - Full accessibility compliance with ARIA attributes\n * - Multiple variants and sizes for different use cases\n * - Icon support (left and right positioning)\n * - Loading states with spinner\n * - Keyboard navigation support\n * - Focus management with visible indicators\n * - Responsive design adaptations\n *\n * @example\n * ```tsx\n * // Basic button\n * <Button label=\"Click me\">Click me</Button>\n *\n * // Button with icon and loading state\n * <Button\n * label=\"Save document\"\n * Icon={SaveIcon}\n * isLoading={saving}\n * disabled={!hasChanges}\n * >\n * Save\n * </Button>\n *\n * // Destructive action button\n * <Button\n * variant={`${ButtonVariant.OUTLINE}`}\n * color={ButtonColor.DESTRUCTIVE}\n * label=\"Delete item permanently\"\n * aria-describedby=\"delete-warning\"\n * >\n * Delete\n * </Button>\n * ```\n */\nexport const Button: FC<ButtonProps> = ({\n variant,\n size,\n color,\n children,\n Icon,\n IconRight,\n iconClassName,\n isLoading = false,\n isActive,\n isSelected,\n isFullWidth,\n roundedSize,\n textAlign,\n disabled,\n label,\n className,\n type = 'button',\n 'aria-describedby': ariaDescribedBy,\n 'aria-expanded': ariaExpanded,\n 'aria-haspopup': ariaHasPopup,\n 'aria-pressed': ariaPressed,\n ...props\n}) => {\n const isLink =\n variant === `${ButtonVariant.LINK}` ||\n variant === `${ButtonVariant.INVISIBLE_LINK}`;\n const isIconOnly = !children && (Icon || IconRight);\n\n const accessibilityProps = {\n 'aria-label': isIconOnly ? (label ?? undefined) : undefined,\n 'aria-labelledby': !isIconOnly ? undefined : undefined,\n 'aria-describedby': ariaDescribedBy,\n 'aria-expanded': ariaExpanded,\n 'aria-haspopup': ariaHasPopup,\n 'aria-pressed': isActive !== undefined ? isActive : ariaPressed,\n 'aria-busy': isLoading,\n 'aria-current': (isActive ? 'page' : undefined) as 'page' | undefined,\n 'aria-disabled': disabled || isLoading,\n 'aria-selected': isSelected,\n };\n\n const isSquareButton =\n size === ButtonSize.ICON_SM ||\n size === ButtonSize.ICON_MD ||\n size === ButtonSize.ICON_LG ||\n size === ButtonSize.ICON_XL;\n\n return (\n <button\n disabled={isLoading || disabled}\n role={isLink ? 'link' : 'button'}\n type={type}\n className={buttonVariants({\n variant,\n size,\n color,\n isFullWidth,\n roundedSize,\n textAlign:\n textAlign ??\n (IconRight ? ButtonTextAlign.LEFT : ButtonTextAlign.CENTER),\n className,\n })}\n {...accessibilityProps}\n {...props}\n >\n {Icon && !isLoading && (\n <Icon\n className={buttonIconVariants({\n size,\n className: cn(!isSquareButton && 'mr-3', iconClassName),\n })}\n aria-hidden=\"true\"\n />\n )}\n\n <div\n className={cn(\n 'flex items-center justify-center transition-[width] duration-300',\n isLoading && size === ButtonSize.SM && 'w-3',\n isLoading && size === ButtonSize.MD && 'w-4',\n isLoading && size === ButtonSize.LG && 'w-6',\n isLoading && size === ButtonSize.XL && 'w-8'\n )}\n >\n <Loader\n className={buttonIconVariants({\n size,\n className: cn(!isSquareButton && 'mr-3', iconClassName),\n })}\n isLoading={isLoading}\n aria-hidden=\"true\"\n data-testid=\"loader\"\n />\n </div>\n\n {children && (\n <span className=\"flex-1 truncate whitespace-nowrap\">{children}</span>\n )}\n\n {!children && isIconOnly && <span className=\"sr-only\">{label}</span>}\n\n {IconRight && (\n <IconRight\n className={buttonIconVariants({\n size,\n className: cn(!isSquareButton && 'ml-3', iconClassName),\n })}\n aria-hidden=\"true\"\n />\n )}\n </button>\n );\n};\n"],"mappings":";;;;;;;;;;AAUA,IAAY,aAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;AACF;AAEA,MAAM,qBAAqB,IAAI,sBAAsB;CACnD,UAAU,EACR,MAAM;GACH,OAAqB;GACrB,OAAqB;GACrB,OAAqB;GACrB,OAAqB;GACrB,OAAqB;GACrB,YAA0B;GAC1B,YAA0B;GAC1B,YAA0B;GAC1B,YAA0B;CAC7B,EACF;CACA,iBAAiB,EACf,WACF;AACF,CAAC;;;;AAKD,IAAY,gBAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;AACF;;;;AAKA,IAAY,cAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;AACF;;;;AAKA,IAAY,kBAAL;CACL;CACA;CACA;;AACF;;;;AAKA,MAAa,iBAAiB,IAC5B,8LACA;CACE,UAAU;EACR,MAAM;IACH,OAAqB;IACrB,OAAqB;IACrB,OAAqB;IACrB,OAAqB;IACrB,OAAqB;IACrB,YAA0B;IAC1B,YAA0B;IAC1B,YAA0B;IAC1B,YAA0B;EAC7B;EACA,OAAO;IACJ,YACC;IACD,cACC;IACD,gBACC;IACD,YACC;IACD,SACC;IACD,UACC;IACD,SACC;IACD,SAAwB;IACxB,YACC;IACD,iBACC;IACD,UACC;IACD,YACC;IACD,WAA0B;EAC7B;EACA,aAAa;IACV,cAA8B;IAC9B,YACC;IACD,YACC;IACD,YACC;IACD,YACC;IACD,aACC;IACD,aACC;IACD,aACC;IACD,aACC;IACD,cAA8B;EACjC;EACA,SAAS;IACN,YAA6B;IAC5B;IACA;IACA;IACA;GACF;IAEC,YAA6B;IAC5B;IACA;IACA;IACA;GACF;IAEC,SACC;IAED,SACC;IAED,mBACC;IAED,cACC;IAED,SAA0B;IACzB;IACA;IACA;GACF;IACC,UAA2B;IAE1B;IACA;IACA;IACA;IACA;IAEA;IACA;IACA;IAGA;IACA;IACA;IACA;IAGA;IAGA;IAGA;GACF;EACF;EAEA,WAAW;IACR,SAA4B;IAC5B,WAA8B;IAC9B,UAA6B;EAChC;EAEA,aAAa;GACX,MAAM;GACN,OAAO;EACT;CACF;CACA,iBAAiB;EACf,SAAS;EACT,MAAM;EACN,OAAO;EACP,aAAa;EACb,WAAW;EACX,aAAa;CACf;AACF,CACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsHA,MAAa,UAA2B,EACtC,SACA,MACA,OACA,UACA,MACA,WACA,eACA,YAAY,OACZ,UACA,YACA,aACA,aACA,WACA,UACA,OACA,WACA,OAAO,UACP,oBAAoB,iBACpB,iBAAiB,cACjB,iBAAiB,cACjB,gBAAgB,aAChB,GAAG,YACC;CACJ,MAAM,SACJ,YAAY,UACZ,YAAY;CACd,MAAM,aAAa,CAAC,aAAa,QAAQ;CAEzC,MAAM,qBAAqB;EACzB,cAAc,aAAc,SAAS,SAAa;EAClD,mBAAmB,CAAC,aAAa,SAAY;EAC7C,oBAAoB;EACpB,iBAAiB;EACjB,iBAAiB;EACjB,gBAAgB,aAAa,SAAY,WAAW;EACpD,aAAa;EACb,gBAAiB,WAAW,SAAS;EACrC,iBAAiB,YAAY;EAC7B,iBAAiB;CACnB;CAEA,MAAM,iBACJ,sBACA,sBACA,sBACA;CAEF,OACE,qBAAC,UAAD;EACE,UAAU,aAAa;EACvB,MAAM,SAAS,SAAS;EAClB;EACN,WAAW,eAAe;GACxB;GACA;GACA;GACA;GACA;GACA,WACE,cACC;GACH;EACF,CAAC;EACD,GAAI;EACJ,GAAI;YAhBN;GAkBG,QAAQ,CAAC,aACR,oBAAC,MAAD;IACE,WAAW,mBAAmB;KAC5B;KACA,WAAW,GAAG,CAAC,kBAAkB,QAAQ,aAAa;IACxD,CAAC;IACD,eAAY;GACb;GAGH,oBAAC,OAAD;IACE,WAAW,GACT,oEACA,aAAa,iBAA0B,OACvC,aAAa,iBAA0B,OACvC,aAAa,iBAA0B,OACvC,aAAa,iBAA0B,KACzC;cAEA,oBAAC,QAAD;KACE,WAAW,mBAAmB;MAC5B;MACA,WAAW,GAAG,CAAC,kBAAkB,QAAQ,aAAa;KACxD,CAAC;KACU;KACX,eAAY;KACZ,eAAY;IACb;GACE;GAEJ,YACC,oBAAC,QAAD;IAAM,WAAU;IAAqC;GAAe;GAGrE,CAAC,YAAY,cAAc,oBAAC,QAAD;IAAM,WAAU;cAAW;GAAY;GAElE,aACC,oBAAC,WAAD;IACE,WAAW,mBAAmB;KAC5B;KACA,WAAW,GAAG,CAAC,kBAAkB,QAAQ,aAAa;IACxD,CAAC;IACD,eAAY;GACb;EAEG;;AAEZ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.content.mjs","names":[],"sources":["../../../../src/components/Carousel/index.content.ts"],"sourcesContent":["import { type Dictionary, insert, t } from 'intlayer';\n\nconst carouselContent = {\n key: 'carousel',\n content: {\n goToSlide: insert(\n t({\n ar: 'انتقل إلى الشريحة رقم {{index}}',\n de: 'Zu Folie {{index}} wechseln',\n en: 'Go to slide {{index}}',\n 'en-GB': 'Go to slide {{index}}',\n es: 'Ir a la diapositiva {{index}}',\n fr: 'Aller à la diapositive {{index}}',\n hi: '{{index}} स्लाइड पर जाएँ',\n id: 'Ke slide {{index}}',\n it: 'Vai alla diapositiva {{index}}',\n ja: '{{index}}枚目のスライドへ',\n ko: '{{index}}번 슬라이드로 이동',\n pl: 'Idź do slajdu {{index}}',\n pt: 'Ir para o slide {{index}}',\n ru: 'Перейти к слайду {{index}}',\n tr: '{{index}}. slayta git',\n uk: 'Перейти до слайду {{index}}',\n vi: 'Đi tới slide {{index}}',\n zh: '跳转到第{{index}}张幻灯片',\n })\n ),\n previousSlide: t({\n en: 'Previous slide',\n 'en-GB': 'Previous slide',\n ru: 'Предыдущий слайд',\n ja: '前のスライド',\n fr: 'Diapositive précédente',\n ko: '이전 슬라이드',\n zh: '上一张幻灯片',\n es: 'Diapositiva anterior',\n de: 'Vorherige Folie',\n ar: 'الشريحة السابقة',\n it: 'Diapositiva precedente',\n pt: 'Diapositiva anterior',\n hi: 'पिछली स्लाइड',\n tr: 'Önceki slayt',\n pl: 'Poprzedni slajd',\n id: 'Slide sebelumnya',\n vi: 'Slide trước',\n uk: 'Попередній слайд',\n }),\n nextSlide: t({\n en: 'Next slide',\n 'en-GB': 'Next slide',\n ru: 'Следующий слайд',\n ja: '次のスライド',\n fr: 'Diapositive suivante',\n ko: '다음 슬라이드',\n zh: '下一张幻灯片',\n es: 'Diapositiva siguiente',\n de: 'Nächste Folie',\n ar: 'الشريحة التالية',\n it: 'Diapositiva successiva',\n pt: 'Diapositiva seguinte',\n hi: 'अगली स्लाइड',\n tr: 'Sonraki slayt',\n pl: 'Następny slajd',\n id: 'Slide berikutnya',\n vi: 'Slide tiếp theo',\n uk: 'Наступний слайд',\n }),\n },\n title: 'Carousel component',\n description:\n \"Localization strings for the Carousel component controls, including labels for 'Go to slide', 'Previous slide', and 'Next slide'.\",\n tags: ['component', 'carousel', 'ui', 'i18n'],\n} satisfies Dictionary;\n\nexport default carouselContent;\n"],"mappings":";;;AAEA,MAAM,kBAAkB;CACtB,KAAK;CACL,SAAS;EACP,WAAW,OACT,EAAE;GACA,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,SAAS;GACT,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;
|
|
1
|
+
{"version":3,"file":"index.content.mjs","names":[],"sources":["../../../../src/components/Carousel/index.content.ts"],"sourcesContent":["import { type Dictionary, insert, t } from 'intlayer';\n\nconst carouselContent = {\n key: 'carousel',\n content: {\n goToSlide: insert(\n t({\n ar: 'انتقل إلى الشريحة رقم {{index}}',\n de: 'Zu Folie {{index}} wechseln',\n en: 'Go to slide {{index}}',\n 'en-GB': 'Go to slide {{index}}',\n es: 'Ir a la diapositiva {{index}}',\n fr: 'Aller à la diapositive {{index}}',\n hi: '{{index}} स्लाइड पर जाएँ',\n id: 'Ke slide {{index}}',\n it: 'Vai alla diapositiva {{index}}',\n ja: '{{index}}枚目のスライドへ',\n ko: '{{index}}번 슬라이드로 이동',\n pl: 'Idź do slajdu {{index}}',\n pt: 'Ir para o slide {{index}}',\n ru: 'Перейти к слайду {{index}}',\n tr: '{{index}}. slayta git',\n uk: 'Перейти до слайду {{index}}',\n vi: 'Đi tới slide {{index}}',\n zh: '跳转到第{{index}}张幻灯片',\n })\n ),\n previousSlide: t({\n en: 'Previous slide',\n 'en-GB': 'Previous slide',\n ru: 'Предыдущий слайд',\n ja: '前のスライド',\n fr: 'Diapositive précédente',\n ko: '이전 슬라이드',\n zh: '上一张幻灯片',\n es: 'Diapositiva anterior',\n de: 'Vorherige Folie',\n ar: 'الشريحة السابقة',\n it: 'Diapositiva precedente',\n pt: 'Diapositiva anterior',\n hi: 'पिछली स्लाइड',\n tr: 'Önceki slayt',\n pl: 'Poprzedni slajd',\n id: 'Slide sebelumnya',\n vi: 'Slide trước',\n uk: 'Попередній слайд',\n }),\n nextSlide: t({\n en: 'Next slide',\n 'en-GB': 'Next slide',\n ru: 'Следующий слайд',\n ja: '次のスライド',\n fr: 'Diapositive suivante',\n ko: '다음 슬라이드',\n zh: '下一张幻灯片',\n es: 'Diapositiva siguiente',\n de: 'Nächste Folie',\n ar: 'الشريحة التالية',\n it: 'Diapositiva successiva',\n pt: 'Diapositiva seguinte',\n hi: 'अगली स्लाइड',\n tr: 'Sonraki slayt',\n pl: 'Następny slajd',\n id: 'Slide berikutnya',\n vi: 'Slide tiếp theo',\n uk: 'Наступний слайд',\n }),\n },\n title: 'Carousel component',\n description:\n \"Localization strings for the Carousel component controls, including labels for 'Go to slide', 'Previous slide', and 'Next slide'.\",\n tags: ['component', 'carousel', 'ui', 'i18n'],\n} satisfies Dictionary;\n\nexport default carouselContent;\n"],"mappings":";;;AAEA,MAAM,kBAAkB;CACtB,KAAK;CACL,SAAS;EACP,WAAW,OACT,EAAE;GACA,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,SAAS;GACT,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN,CAAC,CACH;EACA,eAAe,EAAE;GACf,IAAI;GACJ,SAAS;GACT,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN,CAAC;EACD,WAAW,EAAE;GACX,IAAI;GACJ,SAAS;GACT,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN,CAAC;CACH;CACA,OAAO;CACP,aACE;CACF,MAAM;EAAC;EAAa;EAAY;EAAM;CAAM;AAC9C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/components/Carousel/index.tsx"],"sourcesContent":["'use client';\n\nimport {\n Button,\n ButtonColor,\n ButtonSize,\n ButtonVariant,\n} from '@components/Button';\nimport { KeyboardShortcut } from '@components/KeyboardShortcut';\nimport { Popover } from '@components/Popover';\nimport { cn } from '@utils/cn';\nimport { ChevronLeft, ChevronRight } from 'lucide-react';\nimport {\n Children,\n createContext,\n type FC,\n type HTMLAttributes,\n isValidElement,\n type MouseEventHandler,\n type ReactElement,\n type ReactNode,\n type TouchEventHandler,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { useIntlayer } from 'react-intlayer';\n\n// ------------------------------------------------------------------\n// Configuration\n// ------------------------------------------------------------------\nconst SWIPE_THRESHOLD_DIVISOR = 5;\nconst TRANSITION_DELAY_MS = 50;\n\n// ------------------------------------------------------------------\n// Context Definition\n// ------------------------------------------------------------------\ntype CarouselContextValue = {\n selectedIndex: number;\n setSelectedIndex: (index: number) => void;\n totalItems: number;\n handlePrev: () => void;\n handleNext: () => void;\n};\n\nconst CarouselContext = createContext<CarouselContextValue | null>(null);\n\nconst useCarousel = () => {\n const context = useContext(CarouselContext);\n if (!context) {\n throw new Error('useCarousel must be used within a Carousel');\n }\n return context;\n};\n\n// ------------------------------------------------------------------\n// Helper Functions\n// ------------------------------------------------------------------\nconst getCardStyle = (index: number, displayedIndex: number) => {\n const diff = Math.abs(index - displayedIndex);\n switch (diff) {\n case 0:\n return 'opacity-100 z-40';\n case 1:\n return 'opacity-75 z-30 cursor-pointer';\n case 2:\n return 'opacity-50 z-20 pointer-events-none';\n default:\n return 'opacity-0 z-10 pointer-events-none';\n }\n};\n\nconst getCardScale = (index: number, displayedIndex: number) => {\n const diff = Math.abs(index - displayedIndex);\n switch (diff) {\n case 0:\n return 1;\n case 1:\n return 0.9;\n case 2:\n return 0.8;\n default:\n return 0.7;\n }\n};\n\n// This allows the calculation to work on SSR without hydration mismatch.\n// Your original logic: (3 * screenWidth) / 10 === 30% of viewport width\nconst getCardPositionX = (\n index: number,\n displayedIndex: number,\n containerWidth: number\n) => {\n const diff = index - displayedIndex;\n const gapPercentage = containerWidth < 600 ? 0.15 : 0.3; // Dropped to 15% for a tighter cluster\n const step = Math.min(containerWidth * gapPercentage, 300);\n\n // The 'px' here is mandatory\n return `${diff * step}px`;\n};\n\n// ------------------------------------------------------------------\n// Sub-Component: Item\n// ------------------------------------------------------------------\ntype CarouselItemProps = HTMLAttributes<HTMLDivElement> & {\n children: ReactNode;\n};\n\nconst CarouselItem: FC<CarouselItemProps> = ({\n children,\n className,\n ...props\n}) => {\n return (\n <div className={cn('h-full w-full', className)} {...props}>\n {children}\n </div>\n );\n};\n\n// ------------------------------------------------------------------\n// Sub-Component: Indicators (Controller)\n// ------------------------------------------------------------------\ntype CarouselIndicatorsProps = HTMLAttributes<HTMLDivElement> & {\n disableKeyboardShortcuts?: boolean;\n};\n\nconst CarouselIndicators: FC<CarouselIndicatorsProps> = ({\n className,\n disableKeyboardShortcuts = false,\n ...props\n}) => {\n const {\n selectedIndex,\n setSelectedIndex,\n totalItems,\n handlePrev,\n handleNext,\n } = useCarousel();\n const { goToSlide, previousSlide, nextSlide } = useIntlayer('carousel');\n\n if (totalItems <= 1) return null;\n\n return (\n <div\n className={cn(\n 'absolute bottom-4 left-1/2 z-50 flex -translate-x-1/2 flex-row items-center gap-2',\n className\n )}\n {...props}\n >\n <Popover identifier=\"carousel-prev\">\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.NEUTRAL}\n label={previousSlide.value}\n roundedSize=\"full\"\n onClick={(e) => {\n e.stopPropagation();\n handlePrev();\n }}\n Icon={ChevronLeft}\n size={ButtonSize.ICON_MD}\n disabled={selectedIndex === 0}\n />\n\n <Popover.Detail identifier=\"carousel-prev\">\n <div className=\"flex items-center gap-2 p-2\">\n <span className=\"whitespace-nowrap text-neutral text-xs\">\n {previousSlide.value}\n </span>\n <KeyboardShortcut\n shortcut=\"ArrowLeft\"\n disabled={disableKeyboardShortcuts}\n size=\"sm\"\n onTriggered={handlePrev}\n />\n </div>\n </Popover.Detail>\n </Popover>\n\n {Array.from({ length: totalItems }).map((_, index) => {\n const isActive = index === selectedIndex;\n return (\n <button\n key={index}\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n setSelectedIndex(index);\n }}\n aria-label={goToSlide({ index: index + 1 }).value}\n className={cn(\n 'h-2.5 w-2.5 rounded-full transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-neutral-400 focus:ring-offset-2',\n isActive ? 'scale-110 bg-text' : 'bg-text/20 hover:bg-text/40'\n )}\n />\n );\n })}\n\n <Popover identifier=\"carousel-next\">\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.NEUTRAL}\n roundedSize=\"full\"\n label={nextSlide.value}\n onClick={(e) => {\n e.stopPropagation();\n handleNext();\n }}\n Icon={ChevronRight}\n size={ButtonSize.ICON_MD}\n disabled={selectedIndex === totalItems - 1}\n />\n\n <Popover.Detail identifier=\"carousel-next\">\n <div className=\"flex items-center gap-2 p-2\">\n <span className=\"whitespace-nowrap text-neutral text-xs\">\n {nextSlide.value}\n </span>\n <KeyboardShortcut\n shortcut=\"ArrowRight\"\n size=\"sm\"\n onTriggered={handleNext}\n disabled={disableKeyboardShortcuts}\n />\n </div>\n </Popover.Detail>\n </Popover>\n </div>\n );\n};\n\n// ------------------------------------------------------------------\n// Main Component: Carousel Root\n// ------------------------------------------------------------------\ntype CarouselProps = HTMLAttributes<HTMLDivElement> & {\n children: ReactNode;\n initialIndex?: number;\n onIndexChange?: (index: number) => void;\n};\n\nconst partitionCarouselChildren = (\n children: ReactNode[]\n): [ReactElement[], ReactNode[]] => {\n const slides: ReactElement[] = [];\n const others: ReactNode[] = [];\n\n children.forEach((child) => {\n if (isValidElement(child) && child.type === CarouselItem) {\n slides.push(child);\n } else {\n others.push(child);\n }\n });\n\n return [slides, others];\n};\n\nconst CarouselRoot: FC<CarouselProps> = ({\n children,\n className,\n initialIndex = 0,\n onIndexChange,\n ...props\n}) => {\n const allChildren = Children.toArray(children);\n const [slides, others] = partitionCarouselChildren(allChildren);\n const totalItems = slides.length;\n\n // State Management\n const [selectedIndex, setSelectedIndex] = useState<number>(initialIndex);\n const [displayedIndex, setDisplayedIndex] = useState<number>(initialIndex);\n const [containerHeight, setContainerHeight] = useState<number>(0);\n const [containerWidth, setContainerWidth] = useState<number>(0);\n\n useEffect(() => {\n const calculateDimensions = () => {\n if (!containerRef.current) return;\n\n // Track Width\n const width = containerRef.current.clientWidth;\n setContainerWidth(width);\n\n // Track Height (existing logic)\n const heights = itemsRef.current.map((item) => item?.offsetHeight || 0);\n const maxHeight = Math.max(0, ...heights);\n if (maxHeight > 0) {\n setContainerHeight(maxHeight + 40);\n }\n };\n\n calculateDimensions();\n\n const observer = new ResizeObserver(() => {\n calculateDimensions();\n });\n\n if (containerRef.current) observer.observe(containerRef.current);\n itemsRef.current.forEach((item) => {\n if (item) observer.observe(item);\n });\n\n return () => observer.disconnect();\n }, [totalItems]);\n\n // Drag State\n const [startX, setStartX] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n\n // Refs\n const containerRef = useRef<HTMLDivElement>(null);\n const itemsRef = useRef<(HTMLDivElement | null)[]>([]);\n\n // Navigation Logic\n const handleSwitchItem = (diff: number) => {\n if (containerWidth === 0) return;\n\n // Use container width for the threshold\n const swipeStep = containerWidth / SWIPE_THRESHOLD_DIVISOR;\n const numSwipe = Math.round(diff / swipeStep);\n\n if (Math.abs(numSwipe) >= 1) {\n const newIndex = displayedIndex - numSwipe;\n const clampedIndex = Math.max(0, Math.min(newIndex, totalItems - 1));\n\n if (clampedIndex !== selectedIndex) {\n setSelectedIndex(clampedIndex);\n setStartX((prev) => prev + diff);\n }\n }\n };\n\n const handleNext = () => {\n setSelectedIndex((prev) => Math.min(prev + 1, totalItems - 1));\n };\n\n const handlePrev = () => {\n setSelectedIndex((prev) => Math.max(prev - 1, 0));\n };\n\n // Input Handlers\n const handleMouseDown: MouseEventHandler<HTMLDivElement> = (e) => {\n setIsDragging(true);\n setStartX(e.clientX);\n };\n const handleMouseMove: MouseEventHandler<HTMLDivElement> = (e) => {\n if (isDragging) handleSwitchItem(e.clientX - startX);\n };\n const handleDragEnd = () => setIsDragging(false);\n const handleTouchStart: TouchEventHandler<HTMLDivElement> = (e) => {\n setIsDragging(true);\n setStartX(e.touches[0].clientX);\n };\n const handleTouchMove: TouchEventHandler<HTMLDivElement> = (e) => {\n if (isDragging) handleSwitchItem(e.touches[0].clientX - startX);\n };\n\n // Effects\n useEffect(() => {\n if (selectedIndex) onIndexChange?.(selectedIndex);\n }, [selectedIndex, onIndexChange]);\n\n useEffect(() => {\n let interval: NodeJS.Timeout;\n\n if (selectedIndex !== displayedIndex) {\n interval = setInterval(() => {\n setDisplayedIndex((prev) => {\n if (prev === selectedIndex) {\n clearInterval(interval);\n return prev;\n }\n return prev < selectedIndex ? prev + 1 : prev - 1;\n });\n }, TRANSITION_DELAY_MS);\n }\n return () => clearInterval(interval);\n }, [selectedIndex, displayedIndex]);\n\n // Calculate height based on the MAX height of ALL items\n useEffect(() => {\n const calculateMaxHeight = () => {\n const heights = itemsRef.current.map((item) => item?.offsetHeight || 0);\n const maxHeight = Math.max(0, ...heights);\n\n if (maxHeight > 0) {\n setContainerHeight(maxHeight + 40);\n }\n };\n\n calculateMaxHeight();\n\n const observer = new ResizeObserver(() => {\n calculateMaxHeight();\n });\n\n itemsRef.current.forEach((item) => {\n if (item) observer.observe(item);\n });\n\n return () => observer.disconnect();\n }, [totalItems]); // Removed isMounted dependency\n\n return (\n <CarouselContext.Provider\n value={{\n selectedIndex,\n setSelectedIndex,\n totalItems,\n handlePrev,\n handleNext,\n }}\n >\n <div\n ref={containerRef}\n className={cn(\n 'relative flex w-full cursor-grab select-none items-center overflow-hidden outline-none transition-[height] duration-300 ease-in-out focus:outline-none focus:outline-none focus:ring-0 active:cursor-grabbing',\n 'max-w-[1400px]',\n className\n )}\n style={{\n height: containerHeight > 0 ? containerHeight : 'auto',\n minHeight: '400px',\n }}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleDragEnd}\n onMouseLeave={handleDragEnd}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleDragEnd}\n role=\"region\"\n aria-label=\"Carousel\"\n {...props}\n >\n {slides.map((child, index) => {\n return (\n <div\n key={index}\n role=\"button\"\n tabIndex={0}\n ref={(el) => {\n itemsRef.current[index] = el;\n }}\n // FIX 2: Removed isMounted checks and invisible classes.\n // CSS units allow correct SSR rendering.\n className={cn(\n 'absolute left-1/2 -translate-x-1/2 transition-all duration-300 ease-in-out',\n 'outline-none ring-0 focus:outline-none focus:ring-0 focus:ring-offset-0 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0',\n getCardStyle(index, displayedIndex)\n )}\n onClick={(e) => {\n e.stopPropagation();\n setSelectedIndex(index);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') setSelectedIndex(index);\n }}\n style={{\n transform: `\n translateX(${getCardPositionX(\n index,\n displayedIndex,\n containerWidth\n )})\n scale(${getCardScale(index, displayedIndex)})\n `,\n }}\n >\n {child}\n </div>\n );\n })}\n\n {others}\n </div>\n </CarouselContext.Provider>\n );\n};\n\nexport const Carousel = Object.assign(CarouselRoot, {\n Item: CarouselItem,\n Indicators: CarouselIndicators,\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/components/Carousel/index.tsx"],"sourcesContent":["'use client';\n\nimport {\n Button,\n ButtonColor,\n ButtonSize,\n ButtonVariant,\n} from '@components/Button';\nimport { KeyboardShortcut } from '@components/KeyboardShortcut';\nimport { Popover } from '@components/Popover';\nimport { cn } from '@utils/cn';\nimport { ChevronLeft, ChevronRight } from 'lucide-react';\nimport {\n Children,\n createContext,\n type FC,\n type HTMLAttributes,\n isValidElement,\n type MouseEventHandler,\n type ReactElement,\n type ReactNode,\n type TouchEventHandler,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { useIntlayer } from 'react-intlayer';\n\n// ------------------------------------------------------------------\n// Configuration\n// ------------------------------------------------------------------\nconst SWIPE_THRESHOLD_DIVISOR = 5;\nconst TRANSITION_DELAY_MS = 50;\n\n// ------------------------------------------------------------------\n// Context Definition\n// ------------------------------------------------------------------\ntype CarouselContextValue = {\n selectedIndex: number;\n setSelectedIndex: (index: number) => void;\n totalItems: number;\n handlePrev: () => void;\n handleNext: () => void;\n};\n\nconst CarouselContext = createContext<CarouselContextValue | null>(null);\n\nconst useCarousel = () => {\n const context = useContext(CarouselContext);\n if (!context) {\n throw new Error('useCarousel must be used within a Carousel');\n }\n return context;\n};\n\n// ------------------------------------------------------------------\n// Helper Functions\n// ------------------------------------------------------------------\nconst getCardStyle = (index: number, displayedIndex: number) => {\n const diff = Math.abs(index - displayedIndex);\n switch (diff) {\n case 0:\n return 'opacity-100 z-40';\n case 1:\n return 'opacity-75 z-30 cursor-pointer';\n case 2:\n return 'opacity-50 z-20 pointer-events-none';\n default:\n return 'opacity-0 z-10 pointer-events-none';\n }\n};\n\nconst getCardScale = (index: number, displayedIndex: number) => {\n const diff = Math.abs(index - displayedIndex);\n switch (diff) {\n case 0:\n return 1;\n case 1:\n return 0.9;\n case 2:\n return 0.8;\n default:\n return 0.7;\n }\n};\n\n// This allows the calculation to work on SSR without hydration mismatch.\n// Your original logic: (3 * screenWidth) / 10 === 30% of viewport width\nconst getCardPositionX = (\n index: number,\n displayedIndex: number,\n containerWidth: number\n) => {\n const diff = index - displayedIndex;\n const gapPercentage = containerWidth < 600 ? 0.15 : 0.3; // Dropped to 15% for a tighter cluster\n const step = Math.min(containerWidth * gapPercentage, 300);\n\n // The 'px' here is mandatory\n return `${diff * step}px`;\n};\n\n// ------------------------------------------------------------------\n// Sub-Component: Item\n// ------------------------------------------------------------------\ntype CarouselItemProps = HTMLAttributes<HTMLDivElement> & {\n children: ReactNode;\n};\n\nconst CarouselItem: FC<CarouselItemProps> = ({\n children,\n className,\n ...props\n}) => {\n return (\n <div className={cn('h-full w-full', className)} {...props}>\n {children}\n </div>\n );\n};\n\n// ------------------------------------------------------------------\n// Sub-Component: Indicators (Controller)\n// ------------------------------------------------------------------\ntype CarouselIndicatorsProps = HTMLAttributes<HTMLDivElement> & {\n disableKeyboardShortcuts?: boolean;\n};\n\nconst CarouselIndicators: FC<CarouselIndicatorsProps> = ({\n className,\n disableKeyboardShortcuts = false,\n ...props\n}) => {\n const {\n selectedIndex,\n setSelectedIndex,\n totalItems,\n handlePrev,\n handleNext,\n } = useCarousel();\n const { goToSlide, previousSlide, nextSlide } = useIntlayer('carousel');\n\n if (totalItems <= 1) return null;\n\n return (\n <div\n className={cn(\n 'absolute bottom-4 left-1/2 z-50 flex -translate-x-1/2 flex-row items-center gap-2',\n className\n )}\n {...props}\n >\n <Popover identifier=\"carousel-prev\">\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.NEUTRAL}\n label={previousSlide.value}\n roundedSize=\"full\"\n onClick={(e) => {\n e.stopPropagation();\n handlePrev();\n }}\n Icon={ChevronLeft}\n size={ButtonSize.ICON_MD}\n disabled={selectedIndex === 0}\n />\n\n <Popover.Detail identifier=\"carousel-prev\">\n <div className=\"flex items-center gap-2 p-2\">\n <span className=\"whitespace-nowrap text-neutral text-xs\">\n {previousSlide.value}\n </span>\n <KeyboardShortcut\n shortcut=\"ArrowLeft\"\n disabled={disableKeyboardShortcuts}\n size=\"sm\"\n onTriggered={handlePrev}\n />\n </div>\n </Popover.Detail>\n </Popover>\n\n {Array.from({ length: totalItems }).map((_, index) => {\n const isActive = index === selectedIndex;\n return (\n <button\n key={index}\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n setSelectedIndex(index);\n }}\n aria-label={goToSlide({ index: index + 1 }).value}\n className={cn(\n 'h-2.5 w-2.5 rounded-full transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-neutral-400 focus:ring-offset-2',\n isActive ? 'scale-110 bg-text' : 'bg-text/20 hover:bg-text/40'\n )}\n />\n );\n })}\n\n <Popover identifier=\"carousel-next\">\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.NEUTRAL}\n roundedSize=\"full\"\n label={nextSlide.value}\n onClick={(e) => {\n e.stopPropagation();\n handleNext();\n }}\n Icon={ChevronRight}\n size={ButtonSize.ICON_MD}\n disabled={selectedIndex === totalItems - 1}\n />\n\n <Popover.Detail identifier=\"carousel-next\">\n <div className=\"flex items-center gap-2 p-2\">\n <span className=\"whitespace-nowrap text-neutral text-xs\">\n {nextSlide.value}\n </span>\n <KeyboardShortcut\n shortcut=\"ArrowRight\"\n size=\"sm\"\n onTriggered={handleNext}\n disabled={disableKeyboardShortcuts}\n />\n </div>\n </Popover.Detail>\n </Popover>\n </div>\n );\n};\n\n// ------------------------------------------------------------------\n// Main Component: Carousel Root\n// ------------------------------------------------------------------\ntype CarouselProps = HTMLAttributes<HTMLDivElement> & {\n children: ReactNode;\n initialIndex?: number;\n onIndexChange?: (index: number) => void;\n};\n\nconst partitionCarouselChildren = (\n children: ReactNode[]\n): [ReactElement[], ReactNode[]] => {\n const slides: ReactElement[] = [];\n const others: ReactNode[] = [];\n\n children.forEach((child) => {\n if (isValidElement(child) && child.type === CarouselItem) {\n slides.push(child);\n } else {\n others.push(child);\n }\n });\n\n return [slides, others];\n};\n\nconst CarouselRoot: FC<CarouselProps> = ({\n children,\n className,\n initialIndex = 0,\n onIndexChange,\n ...props\n}) => {\n const allChildren = Children.toArray(children);\n const [slides, others] = partitionCarouselChildren(allChildren);\n const totalItems = slides.length;\n\n // State Management\n const [selectedIndex, setSelectedIndex] = useState<number>(initialIndex);\n const [displayedIndex, setDisplayedIndex] = useState<number>(initialIndex);\n const [containerHeight, setContainerHeight] = useState<number>(0);\n const [containerWidth, setContainerWidth] = useState<number>(0);\n\n useEffect(() => {\n const calculateDimensions = () => {\n if (!containerRef.current) return;\n\n // Track Width\n const width = containerRef.current.clientWidth;\n setContainerWidth(width);\n\n // Track Height (existing logic)\n const heights = itemsRef.current.map((item) => item?.offsetHeight || 0);\n const maxHeight = Math.max(0, ...heights);\n if (maxHeight > 0) {\n setContainerHeight(maxHeight + 40);\n }\n };\n\n calculateDimensions();\n\n const observer = new ResizeObserver(() => {\n calculateDimensions();\n });\n\n if (containerRef.current) observer.observe(containerRef.current);\n itemsRef.current.forEach((item) => {\n if (item) observer.observe(item);\n });\n\n return () => observer.disconnect();\n }, [totalItems]);\n\n // Drag State\n const [startX, setStartX] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n\n // Refs\n const containerRef = useRef<HTMLDivElement>(null);\n const itemsRef = useRef<(HTMLDivElement | null)[]>([]);\n\n // Navigation Logic\n const handleSwitchItem = (diff: number) => {\n if (containerWidth === 0) return;\n\n // Use container width for the threshold\n const swipeStep = containerWidth / SWIPE_THRESHOLD_DIVISOR;\n const numSwipe = Math.round(diff / swipeStep);\n\n if (Math.abs(numSwipe) >= 1) {\n const newIndex = displayedIndex - numSwipe;\n const clampedIndex = Math.max(0, Math.min(newIndex, totalItems - 1));\n\n if (clampedIndex !== selectedIndex) {\n setSelectedIndex(clampedIndex);\n setStartX((prev) => prev + diff);\n }\n }\n };\n\n const handleNext = () => {\n setSelectedIndex((prev) => Math.min(prev + 1, totalItems - 1));\n };\n\n const handlePrev = () => {\n setSelectedIndex((prev) => Math.max(prev - 1, 0));\n };\n\n // Input Handlers\n const handleMouseDown: MouseEventHandler<HTMLDivElement> = (e) => {\n setIsDragging(true);\n setStartX(e.clientX);\n };\n const handleMouseMove: MouseEventHandler<HTMLDivElement> = (e) => {\n if (isDragging) handleSwitchItem(e.clientX - startX);\n };\n const handleDragEnd = () => setIsDragging(false);\n const handleTouchStart: TouchEventHandler<HTMLDivElement> = (e) => {\n setIsDragging(true);\n setStartX(e.touches[0].clientX);\n };\n const handleTouchMove: TouchEventHandler<HTMLDivElement> = (e) => {\n if (isDragging) handleSwitchItem(e.touches[0].clientX - startX);\n };\n\n // Effects\n useEffect(() => {\n if (selectedIndex) onIndexChange?.(selectedIndex);\n }, [selectedIndex, onIndexChange]);\n\n useEffect(() => {\n let interval: NodeJS.Timeout;\n\n if (selectedIndex !== displayedIndex) {\n interval = setInterval(() => {\n setDisplayedIndex((prev) => {\n if (prev === selectedIndex) {\n clearInterval(interval);\n return prev;\n }\n return prev < selectedIndex ? prev + 1 : prev - 1;\n });\n }, TRANSITION_DELAY_MS);\n }\n return () => clearInterval(interval);\n }, [selectedIndex, displayedIndex]);\n\n // Calculate height based on the MAX height of ALL items\n useEffect(() => {\n const calculateMaxHeight = () => {\n const heights = itemsRef.current.map((item) => item?.offsetHeight || 0);\n const maxHeight = Math.max(0, ...heights);\n\n if (maxHeight > 0) {\n setContainerHeight(maxHeight + 40);\n }\n };\n\n calculateMaxHeight();\n\n const observer = new ResizeObserver(() => {\n calculateMaxHeight();\n });\n\n itemsRef.current.forEach((item) => {\n if (item) observer.observe(item);\n });\n\n return () => observer.disconnect();\n }, [totalItems]); // Removed isMounted dependency\n\n return (\n <CarouselContext.Provider\n value={{\n selectedIndex,\n setSelectedIndex,\n totalItems,\n handlePrev,\n handleNext,\n }}\n >\n <div\n ref={containerRef}\n className={cn(\n 'relative flex w-full cursor-grab select-none items-center overflow-hidden outline-none transition-[height] duration-300 ease-in-out focus:outline-none focus:outline-none focus:ring-0 active:cursor-grabbing',\n 'max-w-[1400px]',\n className\n )}\n style={{\n height: containerHeight > 0 ? containerHeight : 'auto',\n minHeight: '400px',\n }}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleDragEnd}\n onMouseLeave={handleDragEnd}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleDragEnd}\n role=\"region\"\n aria-label=\"Carousel\"\n {...props}\n >\n {slides.map((child, index) => {\n return (\n <div\n key={index}\n role=\"button\"\n tabIndex={0}\n ref={(el) => {\n itemsRef.current[index] = el;\n }}\n // FIX 2: Removed isMounted checks and invisible classes.\n // CSS units allow correct SSR rendering.\n className={cn(\n 'absolute left-1/2 -translate-x-1/2 transition-all duration-300 ease-in-out',\n 'outline-none ring-0 focus:outline-none focus:ring-0 focus:ring-offset-0 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0',\n getCardStyle(index, displayedIndex)\n )}\n onClick={(e) => {\n e.stopPropagation();\n setSelectedIndex(index);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') setSelectedIndex(index);\n }}\n style={{\n transform: `\n translateX(${getCardPositionX(\n index,\n displayedIndex,\n containerWidth\n )})\n scale(${getCardScale(index, displayedIndex)})\n `,\n }}\n >\n {child}\n </div>\n );\n })}\n\n {others}\n </div>\n </CarouselContext.Provider>\n );\n};\n\nexport const Carousel = Object.assign(CarouselRoot, {\n Item: CarouselItem,\n Indicators: CarouselIndicators,\n});\n"],"mappings":";;;;;;;;;;;;AAgCA,MAAM,0BAA0B;AAChC,MAAM,sBAAsB;AAa5B,MAAM,kBAAkB,cAA2C,IAAI;AAEvE,MAAM,oBAAoB;CACxB,MAAM,UAAU,WAAW,eAAe;CAC1C,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,4CAA4C;CAE9D,OAAO;AACT;AAKA,MAAM,gBAAgB,OAAe,mBAA2B;CAE9D,QADa,KAAK,IAAI,QAAQ,cACnB,GAAX;EACE,KAAK,GACH,OAAO;EACT,KAAK,GACH,OAAO;EACT,KAAK,GACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAEA,MAAM,gBAAgB,OAAe,mBAA2B;CAE9D,QADa,KAAK,IAAI,QAAQ,cACnB,GAAX;EACE,KAAK,GACH,OAAO;EACT,KAAK,GACH,OAAO;EACT,KAAK,GACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAIA,MAAM,oBACJ,OACA,gBACA,mBACG;CAMH,OAAO,IALM,QAAQ,kBAER,KAAK,IAAI,kBADA,iBAAiB,MAAM,MAAO,KACE,GAGlC,EAAE;AACxB;AASA,MAAM,gBAAuC,EAC3C,UACA,WACA,GAAG,YACC;CACJ,OACE,oBAAC,OAAD;EAAK,WAAW,GAAG,iBAAiB,SAAS;EAAG,GAAI;EACjD;CACE;AAET;AASA,MAAM,sBAAmD,EACvD,WACA,2BAA2B,OAC3B,GAAG,YACC;CACJ,MAAM,EACJ,eACA,kBACA,YACA,YACA,eACE,YAAY;CAChB,MAAM,EAAE,WAAW,eAAe,cAAc,YAAY,UAAU;CAEtE,IAAI,cAAc,GAAG,OAAO;CAE5B,OACE,qBAAC,OAAD;EACE,WAAW,GACT,qFACA,SACF;EACA,GAAI;YALN;GAOE,qBAAC,SAAD;IAAS,YAAW;cAApB,CACE,oBAAC,QAAD;KACE;KACA;KACA,OAAO,cAAc;KACrB,aAAY;KACZ,UAAU,MAAM;MACd,EAAE,gBAAgB;MAClB,WAAW;KACb;KACA,MAAM;KACN;KACA,UAAU,kBAAkB;IAC7B,IAED,oBAAC,QAAQ,QAAT;KAAgB,YAAW;eACzB,qBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,oBAAC,QAAD;OAAM,WAAU;iBACb,cAAc;MACX,IACN,oBAAC,kBAAD;OACE,UAAS;OACT,UAAU;OACV,MAAK;OACL,aAAa;MACd,EACE;;IACS,EACT;;GAER,MAAM,KAAK,EAAE,QAAQ,WAAW,CAAC,EAAE,KAAK,GAAG,UAAU;IACpD,MAAM,WAAW,UAAU;IAC3B,OACE,oBAAC,UAAD;KAEE,MAAK;KACL,UAAU,MAAM;MACd,EAAE,gBAAgB;MAClB,iBAAiB,KAAK;KACxB;KACA,cAAY,UAAU,EAAE,OAAO,QAAQ,EAAE,CAAC,EAAE;KAC5C,WAAW,GACT,mIACA,WAAW,sBAAsB,6BACnC;IACD,GAXM,KAWN;GAEL,CAAC;GAED,qBAAC,SAAD;IAAS,YAAW;cAApB,CACE,oBAAC,QAAD;KACE;KACA;KACA,aAAY;KACZ,OAAO,UAAU;KACjB,UAAU,MAAM;MACd,EAAE,gBAAgB;MAClB,WAAW;KACb;KACA,MAAM;KACN;KACA,UAAU,kBAAkB,aAAa;IAC1C,IAED,oBAAC,QAAQ,QAAT;KAAgB,YAAW;eACzB,qBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,oBAAC,QAAD;OAAM,WAAU;iBACb,UAAU;MACP,IACN,oBAAC,kBAAD;OACE,UAAS;OACT,MAAK;OACL,aAAa;OACb,UAAU;MACX,EACE;;IACS,EACT;;EACN;;AAET;AAWA,MAAM,6BACJ,aACkC;CAClC,MAAM,SAAyB,CAAC;CAChC,MAAM,SAAsB,CAAC;CAE7B,SAAS,SAAS,UAAU;EAC1B,IAAI,eAAe,KAAK,KAAK,MAAM,SAAS,cAC1C,OAAO,KAAK,KAAK;OAEjB,OAAO,KAAK,KAAK;CAErB,CAAC;CAED,OAAO,CAAC,QAAQ,MAAM;AACxB;AAEA,MAAM,gBAAmC,EACvC,UACA,WACA,eAAe,GACf,eACA,GAAG,YACC;CAEJ,MAAM,CAAC,QAAQ,UAAU,0BADL,SAAS,QAAQ,QACwB,CAAC;CAC9D,MAAM,aAAa,OAAO;CAG1B,MAAM,CAAC,eAAe,oBAAoB,SAAiB,YAAY;CACvE,MAAM,CAAC,gBAAgB,qBAAqB,SAAiB,YAAY;CACzE,MAAM,CAAC,iBAAiB,sBAAsB,SAAiB,CAAC;CAChE,MAAM,CAAC,gBAAgB,qBAAqB,SAAiB,CAAC;CAE9D,gBAAgB;EACd,MAAM,4BAA4B;GAChC,IAAI,CAAC,aAAa,SAAS;GAG3B,MAAM,QAAQ,aAAa,QAAQ;GACnC,kBAAkB,KAAK;GAGvB,MAAM,UAAU,SAAS,QAAQ,KAAK,SAAS,MAAM,gBAAgB,CAAC;GACtE,MAAM,YAAY,KAAK,IAAI,GAAG,GAAG,OAAO;GACxC,IAAI,YAAY,GACd,mBAAmB,YAAY,EAAE;EAErC;EAEA,oBAAoB;EAEpB,MAAM,WAAW,IAAI,qBAAqB;GACxC,oBAAoB;EACtB,CAAC;EAED,IAAI,aAAa,SAAS,SAAS,QAAQ,aAAa,OAAO;EAC/D,SAAS,QAAQ,SAAS,SAAS;GACjC,IAAI,MAAM,SAAS,QAAQ,IAAI;EACjC,CAAC;EAED,aAAa,SAAS,WAAW;CACnC,GAAG,CAAC,UAAU,CAAC;CAGf,MAAM,CAAC,QAAQ,aAAa,SAAS,CAAC;CACtC,MAAM,CAAC,YAAY,iBAAiB,SAAS,KAAK;CAGlD,MAAM,eAAe,OAAuB,IAAI;CAChD,MAAM,WAAW,OAAkC,CAAC,CAAC;CAGrD,MAAM,oBAAoB,SAAiB;EACzC,IAAI,mBAAmB,GAAG;EAG1B,MAAM,YAAY,iBAAiB;EACnC,MAAM,WAAW,KAAK,MAAM,OAAO,SAAS;EAE5C,IAAI,KAAK,IAAI,QAAQ,KAAK,GAAG;GAC3B,MAAM,WAAW,iBAAiB;GAClC,MAAM,eAAe,KAAK,IAAI,GAAG,KAAK,IAAI,UAAU,aAAa,CAAC,CAAC;GAEnE,IAAI,iBAAiB,eAAe;IAClC,iBAAiB,YAAY;IAC7B,WAAW,SAAS,OAAO,IAAI;GACjC;EACF;CACF;CAEA,MAAM,mBAAmB;EACvB,kBAAkB,SAAS,KAAK,IAAI,OAAO,GAAG,aAAa,CAAC,CAAC;CAC/D;CAEA,MAAM,mBAAmB;EACvB,kBAAkB,SAAS,KAAK,IAAI,OAAO,GAAG,CAAC,CAAC;CAClD;CAGA,MAAM,mBAAsD,MAAM;EAChE,cAAc,IAAI;EAClB,UAAU,EAAE,OAAO;CACrB;CACA,MAAM,mBAAsD,MAAM;EAChE,IAAI,YAAY,iBAAiB,EAAE,UAAU,MAAM;CACrD;CACA,MAAM,sBAAsB,cAAc,KAAK;CAC/C,MAAM,oBAAuD,MAAM;EACjE,cAAc,IAAI;EAClB,UAAU,EAAE,QAAQ,GAAG,OAAO;CAChC;CACA,MAAM,mBAAsD,MAAM;EAChE,IAAI,YAAY,iBAAiB,EAAE,QAAQ,GAAG,UAAU,MAAM;CAChE;CAGA,gBAAgB;EACd,IAAI,eAAe,gBAAgB,aAAa;CAClD,GAAG,CAAC,eAAe,aAAa,CAAC;CAEjC,gBAAgB;EACd,IAAI;EAEJ,IAAI,kBAAkB,gBACpB,WAAW,kBAAkB;GAC3B,mBAAmB,SAAS;IAC1B,IAAI,SAAS,eAAe;KAC1B,cAAc,QAAQ;KACtB,OAAO;IACT;IACA,OAAO,OAAO,gBAAgB,OAAO,IAAI,OAAO;GAClD,CAAC;EACH,GAAG,mBAAmB;EAExB,aAAa,cAAc,QAAQ;CACrC,GAAG,CAAC,eAAe,cAAc,CAAC;CAGlC,gBAAgB;EACd,MAAM,2BAA2B;GAC/B,MAAM,UAAU,SAAS,QAAQ,KAAK,SAAS,MAAM,gBAAgB,CAAC;GACtE,MAAM,YAAY,KAAK,IAAI,GAAG,GAAG,OAAO;GAExC,IAAI,YAAY,GACd,mBAAmB,YAAY,EAAE;EAErC;EAEA,mBAAmB;EAEnB,MAAM,WAAW,IAAI,qBAAqB;GACxC,mBAAmB;EACrB,CAAC;EAED,SAAS,QAAQ,SAAS,SAAS;GACjC,IAAI,MAAM,SAAS,QAAQ,IAAI;EACjC,CAAC;EAED,aAAa,SAAS,WAAW;CACnC,GAAG,CAAC,UAAU,CAAC;CAEf,OACE,oBAAC,gBAAgB,UAAjB;EACE,OAAO;GACL;GACA;GACA;GACA;GACA;EACF;YAEA,qBAAC,OAAD;GACE,KAAK;GACL,WAAW,GACT,iNACA,kBACA,SACF;GACA,OAAO;IACL,QAAQ,kBAAkB,IAAI,kBAAkB;IAChD,WAAW;GACb;GACA,aAAa;GACb,aAAa;GACb,WAAW;GACX,cAAc;GACd,cAAc;GACd,aAAa;GACb,YAAY;GACZ,MAAK;GACL,cAAW;GACX,GAAI;aApBN,CAsBG,OAAO,KAAK,OAAO,UAAU;IAC5B,OACE,oBAAC,OAAD;KAEE,MAAK;KACL,UAAU;KACV,MAAM,OAAO;MACX,SAAS,QAAQ,SAAS;KAC5B;KAGA,WAAW,GACT,8EACA,uJACA,aAAa,OAAO,cAAc,CACpC;KACA,UAAU,MAAM;MACd,EAAE,gBAAgB;MAClB,iBAAiB,KAAK;KACxB;KACA,YAAY,MAAM;MAChB,IAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK,iBAAiB,KAAK;KAChE;KACA,OAAO,EACL,WAAW;+BACI,iBACX,OACA,gBACA,cACF,EAAE;0BACM,aAAa,OAAO,cAAc,EAAE;kBAEhD;eAEC;IACE,GAhCE,KAgCF;GAET,CAAC,GAEA,MACE;;CACmB;AAE9B;AAEA,MAAa,WAAW,OAAO,OAAO,cAAc;CAClD,MAAM;CACN,YAAY;AACd,CAAC"}
|