@intlayer/design-system 9.4.0 → 9.4.2
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/README.md +1 -1
- package/dist/esm/api/index.mjs +2 -2
- package/dist/esm/api/useUser/index.mjs +1 -1
- package/dist/esm/components/Avatar/index.mjs +1 -1
- package/dist/esm/components/Avatar/index.mjs.map +1 -1
- package/dist/esm/components/Badge/index.mjs +3 -3
- package/dist/esm/components/Badge/index.mjs.map +1 -1
- package/dist/esm/components/Breadcrumb/index.mjs +5 -5
- package/dist/esm/components/Breadcrumb/index.mjs.map +1 -1
- package/dist/esm/components/Browser/Browser.mjs +4 -4
- package/dist/esm/components/Browser/Browser.mjs.map +1 -1
- package/dist/esm/components/Button/Button.mjs +1 -0
- package/dist/esm/components/Button/Button.mjs.map +1 -1
- package/dist/esm/components/Carousel/index.mjs +5 -5
- package/dist/esm/components/Carousel/index.mjs.map +1 -1
- package/dist/esm/components/CollapsibleTable/CollapsibleTable.mjs +5 -5
- package/dist/esm/components/CollapsibleTable/CollapsibleTable.mjs.map +1 -1
- package/dist/esm/components/Container/index.mjs +2 -2
- package/dist/esm/components/Container/index.mjs.map +1 -1
- package/dist/esm/components/ContentEditor/ContentEditorTextArea.mjs +1 -1
- package/dist/esm/components/DictionaryEditor/ItemLayout.mjs +1 -1
- package/dist/esm/components/DictionaryEditor/ItemLayout.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/TextEditor.mjs +7 -7
- package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/TextEditor.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryCreationForm/DictionaryCreationForm.mjs +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/DictionaryDetailsForm.mjs +9 -9
- package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/DictionaryDetailsForm.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryFieldEditor.mjs +4 -4
- package/dist/esm/components/DictionaryFieldEditor/DictionaryFieldEditor.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs +1 -1
- package/dist/esm/components/DictionaryFieldEditor/{ContentEditor.mjs → NodeEditor.mjs} +9 -9
- package/dist/esm/components/DictionaryFieldEditor/NodeEditor.mjs.map +1 -0
- package/dist/esm/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs +3 -3
- package/dist/esm/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/StructureView/StructureView.mjs +2 -2
- package/dist/esm/components/DictionaryFieldEditor/StructureView/StructureView.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/VersionSwitcherDropDown/VersionSwitcher.mjs +2 -2
- package/dist/esm/components/DictionaryFieldEditor/VersionSwitcherDropDown/VersionSwitcher.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/index.mjs +3 -3
- package/dist/esm/components/Footer/index.mjs +5 -3
- package/dist/esm/components/Footer/index.mjs.map +1 -1
- package/dist/esm/components/Form/elements/OTPElement.mjs +1 -1
- package/dist/esm/components/HeightResizer/index.mjs +1 -1
- package/dist/esm/components/HeightResizer/index.mjs.map +1 -1
- package/dist/esm/components/IDE/Code.mjs +1 -1
- package/dist/esm/components/IDE/Code.mjs.map +1 -1
- package/dist/esm/components/IDE/FileList.mjs +1 -1
- package/dist/esm/components/IDE/FileList.mjs.map +1 -1
- package/dist/esm/components/IDE/FileTree.mjs +1 -1
- package/dist/esm/components/IDE/FileTree.mjs.map +1 -1
- package/dist/esm/components/IDE/IDE.mjs +10 -7
- package/dist/esm/components/IDE/IDE.mjs.map +1 -1
- package/dist/esm/components/IDE/MarkDownRender.mjs +4 -3
- package/dist/esm/components/IDE/MarkDownRender.mjs.map +1 -1
- package/dist/esm/components/Input/Checkbox.mjs +4 -4
- package/dist/esm/components/Input/Checkbox.mjs.map +1 -1
- package/dist/esm/components/Input/Input.mjs +2 -2
- package/dist/esm/components/Input/Input.mjs.map +1 -1
- package/dist/esm/components/Input/OTPInput.mjs +1 -1
- package/dist/esm/components/Input/OTPInput.mjs.map +1 -1
- package/dist/esm/components/KeyboardShortcut/KeyboardShortcut.mjs +2 -2
- package/dist/esm/components/KeyboardShortcut/KeyboardShortcut.mjs.map +1 -1
- package/dist/esm/components/LanguageBackground/LanguageSection.mjs +6 -8
- package/dist/esm/components/LanguageBackground/LanguageSection.mjs.map +1 -1
- package/dist/esm/components/LanguageBackground/index.mjs +2 -2
- package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.mjs +3 -3
- package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.mjs.map +1 -1
- package/dist/esm/components/MarkDownRender/MarkDownIframe.mjs +1 -1
- package/dist/esm/components/MarkDownRender/MarkDownIframe.mjs.map +1 -1
- package/dist/esm/components/MarkDownRender/MarkDownRender.mjs +9 -8
- package/dist/esm/components/MarkDownRender/MarkDownRender.mjs.map +1 -1
- package/dist/esm/components/MarkdownEditor/MarkdownEditor.mjs +2 -2
- package/dist/esm/components/MarkdownEditor/MarkdownEditor.mjs.map +1 -1
- package/dist/esm/components/MarkdownEditor/generative/AISelector.mjs +3 -3
- package/dist/esm/components/MarkdownEditor/generative/AISelector.mjs.map +1 -1
- package/dist/esm/components/MarkdownEditor/generative/AISelectorCommands.mjs +2 -2
- package/dist/esm/components/MarkdownEditor/generative/AISelectorCommands.mjs.map +1 -1
- package/dist/esm/components/MarkdownEditor/generative/GenerativeMenuSwitch.mjs +2 -2
- package/dist/esm/components/MarkdownEditor/generative/GenerativeMenuSwitch.mjs.map +1 -1
- package/dist/esm/components/Modal/Modal.mjs +2 -3
- package/dist/esm/components/Modal/Modal.mjs.map +1 -1
- package/dist/esm/components/Navbar/DesktopNavbar.mjs +3 -3
- package/dist/esm/components/Navbar/DesktopNavbar.mjs.map +1 -1
- package/dist/esm/components/Navbar/MobileNavbar.mjs +2 -2
- package/dist/esm/components/Navbar/MobileNavbar.mjs.map +1 -1
- package/dist/esm/components/Pagination/Pagination.mjs +1 -1
- package/dist/esm/components/Pattern/GridDistortionPattern.mjs +2 -2
- package/dist/esm/components/Pattern/GridDistortionPattern.mjs.map +1 -1
- package/dist/esm/components/Pattern/GridPattern.mjs +1 -1
- package/dist/esm/components/Pattern/GridPattern.mjs.map +1 -1
- package/dist/esm/components/RightDrawer/RightDrawer.mjs +5 -5
- package/dist/esm/components/RightDrawer/RightDrawer.mjs.map +1 -1
- package/dist/esm/components/Select/Multiselect.mjs +2 -2
- package/dist/esm/components/Select/Multiselect.mjs.map +1 -1
- package/dist/esm/components/Select/Select.mjs +2 -2
- package/dist/esm/components/Select/Select.mjs.map +1 -1
- package/dist/esm/components/Status/index.mjs +28 -0
- package/dist/esm/components/Status/index.mjs.map +1 -0
- package/dist/esm/components/Steps/index.mjs +3 -3
- package/dist/esm/components/Steps/index.mjs.map +1 -1
- package/dist/esm/components/SwitchSelector/SwitchSelector.mjs +12 -11
- package/dist/esm/components/SwitchSelector/SwitchSelector.mjs.map +1 -1
- package/dist/esm/components/SwitchSelector/VerticalSwitchSelector.mjs +6 -6
- package/dist/esm/components/SwitchSelector/VerticalSwitchSelector.mjs.map +1 -1
- package/dist/esm/components/Tab/Tab.mjs +2 -2
- package/dist/esm/components/Tab/Tab.mjs.map +1 -1
- package/dist/esm/components/TabSelector/TabSelector.mjs +5 -5
- package/dist/esm/components/TabSelector/TabSelector.mjs.map +1 -1
- package/dist/esm/components/Table/SmartTable.mjs +2 -2
- package/dist/esm/components/Table/SmartTable.mjs.map +1 -1
- package/dist/esm/components/Table/Table.mjs +1 -1
- package/dist/esm/components/Table/Table.mjs.map +1 -1
- package/dist/esm/components/Table/TableElements.mjs +2 -2
- package/dist/esm/components/Table/TableElements.mjs.map +1 -1
- package/dist/esm/components/Tag/index.mjs +1 -1
- package/dist/esm/components/Tag/index.mjs.map +1 -1
- package/dist/esm/components/TechLogo/TechLogo.mjs +2 -0
- package/dist/esm/components/TechLogo/TechLogo.mjs.map +1 -1
- package/dist/esm/components/TechLogo/logos/HTMX.mjs +31 -0
- package/dist/esm/components/TechLogo/logos/HTMX.mjs.map +1 -0
- package/dist/esm/components/TechLogo/logos/Remix.mjs +22 -0
- package/dist/esm/components/TechLogo/logos/Remix.mjs.map +1 -0
- package/dist/esm/components/TechLogo/techLogos.mjs +5 -1
- package/dist/esm/components/TechLogo/techLogos.mjs.map +1 -1
- package/dist/esm/components/Terminal/Terminal.mjs +4 -4
- package/dist/esm/components/Terminal/Terminal.mjs.map +1 -1
- package/dist/esm/components/TextArea/TextArea.mjs.map +1 -1
- package/dist/esm/components/Toaster/Toast.mjs +4 -4
- package/dist/esm/components/Toaster/Toast.mjs.map +1 -1
- package/dist/esm/components/index.mjs +8 -7
- package/dist/esm/hooks/index.mjs +7 -7
- package/dist/esm/hooks/usePersistedStore.mjs +6 -18
- package/dist/esm/hooks/usePersistedStore.mjs.map +1 -1
- package/dist/esm/providers/ReactQueryProvider.mjs +10 -2
- package/dist/esm/providers/ReactQueryProvider.mjs.map +1 -1
- package/dist/esm/providers/ThemeProvider.mjs +27 -15
- package/dist/esm/providers/ThemeProvider.mjs.map +1 -1
- package/dist/esm/routes.mjs +3 -1
- package/dist/esm/routes.mjs.map +1 -1
- package/dist/esm/structured-data/buildItemListJsonLd.mjs +27 -0
- package/dist/esm/structured-data/buildItemListJsonLd.mjs.map +1 -0
- package/dist/esm/structured-data/index.mjs +2 -1
- package/dist/types/components/Badge/index.d.ts.map +1 -1
- package/dist/types/components/Button/Button.d.ts +2 -2
- package/dist/types/components/Button/Button.d.ts.map +1 -1
- package/dist/types/components/Container/index.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/ContentEditorView/TextEditor.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/NodeEditor.d.ts +10 -0
- package/dist/types/components/DictionaryFieldEditor/NodeEditor.d.ts.map +1 -0
- package/dist/types/components/DictionaryFieldEditor/index.d.ts +2 -2
- package/dist/types/components/Footer/index.d.ts.map +1 -1
- package/dist/types/components/Form/FormBase.d.ts +1 -1
- package/dist/types/components/IDE/MarkDownRender.d.ts +1 -0
- package/dist/types/components/IDE/MarkDownRender.d.ts.map +1 -1
- package/dist/types/components/LanguageBackground/LanguageSection.d.ts +5 -1
- package/dist/types/components/LanguageBackground/LanguageSection.d.ts.map +1 -1
- package/dist/types/components/LanguageBackground/index.d.ts +2 -2
- package/dist/types/components/MarkDownRender/MarkDownRender.d.ts.map +1 -1
- package/dist/types/components/Status/index.d.ts +8 -0
- package/dist/types/components/Status/index.d.ts.map +1 -0
- package/dist/types/components/SwitchSelector/SwitchSelector.d.ts +3 -3
- package/dist/types/components/SwitchSelector/SwitchSelector.d.ts.map +1 -1
- package/dist/types/components/Table/TableElements.d.ts.map +1 -1
- package/dist/types/components/TechLogo/TechLogo.d.ts.map +1 -1
- package/dist/types/components/TechLogo/logos/HTMX.d.ts +6 -0
- package/dist/types/components/TechLogo/logos/HTMX.d.ts.map +1 -0
- package/dist/types/components/TechLogo/logos/Remix.d.ts +6 -0
- package/dist/types/components/TechLogo/logos/Remix.d.ts.map +1 -0
- package/dist/types/components/TechLogo/techLogos.d.ts +4 -2
- package/dist/types/components/TechLogo/types.d.ts +1 -1
- package/dist/types/components/TextArea/TextArea.d.ts +1 -1
- package/dist/types/components/index.d.ts +3 -2
- package/dist/types/providers/ThemeProvider.d.ts.map +1 -1
- package/dist/types/routes.d.ts +3 -1
- package/dist/types/routes.d.ts.map +1 -1
- package/dist/types/structured-data/buildItemListJsonLd.d.ts +36 -0
- package/dist/types/structured-data/buildItemListJsonLd.d.ts.map +1 -0
- package/dist/types/structured-data/index.d.ts +2 -1
- package/package.json +53 -53
- package/src/components/MarkdownEditor/markdown-editor.css +16 -16
- package/styles/globals.css +71 -0
- package/dist/esm/components/DictionaryFieldEditor/ContentEditor.mjs.map +0 -1
- package/dist/types/components/DictionaryFieldEditor/ContentEditor.d.ts +0 -10
- package/dist/types/components/DictionaryFieldEditor/ContentEditor.d.ts.map +0 -1
- package/tailwind.css +0 -269
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Code.mjs","names":[],"sources":["../../../../src/components/IDE/Code.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport type { FC, HTMLAttributes, ReactNode } from 'react';\nimport { useEffect, useMemo, useState } from 'react';\nimport { Container } from '../Container';\nimport { ExpandCollapse } from '../ExpandCollapse';\nimport { CodeBlock } from './CodeBlockClient';\nimport { CodeBlockHighlight } from './CodeBlockHighlight';\nimport { CodeConditionalRender } from './CodeConditionalRenderer';\nimport type {\n CodeFormat,\n ContentDeclarationFormat,\n PackageManager,\n} from './CodeContext';\nimport { useCodeContext } from './CodeContext';\nimport { CodeFormatSelector } from './CodeFormatSelector';\nimport { ContentDeclarationFormatSelector } from './ContentDeclarationFormatSelector';\nimport { CopyCode } from './CopyCode';\nimport { PackageManagerSelector } from './PackageManagerSelector';\nimport type { CodeLanguage } from './shikiLanguages';\n\nexport type CodeCompAttributes = {\n fileName?: string;\n packageManager?: PackageManager;\n /** Single format, a JSON-array string, or an array of formats. */\n codeFormat?: CodeFormat | string | string[];\n contentDeclarationFormat?: ContentDeclarationFormat | string | string[];\n};\n\ntype CodeCompProps = {\n children: ReactNode;\n fileName?: string;\n language: CodeLanguage;\n /**\n * Markup for `children`, highlighted by Shiki ahead of time. When present the\n * block paints straight from it and the highlighter is never downloaded —\n * except when the reader switches the block to a non-TypeScript format.\n */\n highlightedHtml?: string;\n showHeader?: boolean;\n showLineNumbers?: boolean;\n isRollable?: boolean;\n} & CodeCompAttributes &\n HTMLAttributes<HTMLDivElement>;\n\nconst MIN_HEIGHT = 700;\n\n/** Languages that use JSX syntax — CommonJS doesn't make sense for these. */\nconst JSX_LANGUAGES = new Set(['tsx', 'jsx']);\n\n/** Parse a codeFormat prop that may be a single value, a JSON-array string, or already an array. */\nconst parseFormats = (\n raw: string | string[] | undefined\n): CodeFormat[] | undefined => {\n if (!raw) return undefined;\n if (Array.isArray(raw)) return raw as CodeFormat[];\n if (typeof raw === 'string' && raw.startsWith('[')) {\n try {\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) return parsed as CodeFormat[];\n } catch {\n /* ignore */\n }\n }\n return [raw as CodeFormat];\n};\n\nexport const Code: FC<CodeCompProps> = ({\n children,\n language,\n highlightedHtml,\n showHeader = true,\n showLineNumbers = true,\n className,\n fileName,\n packageManager,\n codeFormat: rawCodeFormat,\n contentDeclarationFormat: rawContentDeclarationFormat,\n isRollable = true,\n lang, // Destructure html lang prop to prevent passing invalid BCP-47 language tag to Code component\n ...props\n}) => {\n const {\n codeFormat: selectedCodeFormat,\n contentDeclarationFormat: selectedContentDeclarationFormat,\n } = useCodeContext();\n\n // Parse whichever attribute is present as an array of formats.\n const codeFormats = useMemo(\n () => parseFormats(rawCodeFormat as string | undefined),\n [rawCodeFormat]\n );\n const contentFormats = useMemo(\n () => parseFormats(rawContentDeclarationFormat as string | undefined),\n [rawContentDeclarationFormat]\n );\n\n // A block is \"multi-format\" when it has multiple formats including TypeScript\n // (the canonical source). Such blocks transform at runtime.\n const isMultiCodeFormat =\n codeFormats !== undefined &&\n codeFormats.length > 1 &&\n codeFormats.includes('typescript');\n\n const isMultiContentFormat =\n contentFormats !== undefined &&\n contentFormats.length > 1 &&\n contentFormats.includes('typescript');\n\n const isMultiFormat = isMultiCodeFormat || isMultiContentFormat;\n\n // Determine which context format drives this block's selection.\n // content declaration blocks use selectedContentDeclarationFormat;\n // regular code blocks use selectedCodeFormat.\n const selectedFormat: CodeFormat = isMultiContentFormat\n ? (selectedContentDeclarationFormat as CodeFormat)\n : selectedCodeFormat;\n\n // The formats actually relevant for transformation (no 'json', no 'commonjs' for JSX).\n const effectiveFormats = useMemo<CodeFormat[] | undefined>(() => {\n const base = isMultiContentFormat ? contentFormats : codeFormats;\n if (!base) return base;\n let filtered = base.filter((f) => f !== 'json') as CodeFormat[];\n if (JSX_LANGUAGES.has(language as string)) {\n filtered = filtered.filter((f) => f !== 'commonjs');\n }\n return filtered;\n }, [isMultiContentFormat, contentFormats, codeFormats, language]);\n\n // When the globally-selected format isn't valid for this block\n // (e.g. CJS selected but this is a JSX file), fall back to the last valid one.\n const resolvedFormat: Exclude<CodeFormat, 'json'> = useMemo(() => {\n if (!effectiveFormats || effectiveFormats.includes(selectedFormat)) {\n return selectedFormat as Exclude<CodeFormat, 'json'>;\n }\n return (effectiveFormats[effectiveFormats.length - 1] ??\n 'typescript') as Exclude<CodeFormat, 'json'>;\n }, [effectiveFormats, selectedFormat]);\n\n // ── Async filename derivation (dynamic import of transformer) ──────────────\n // We derive the displayed fileName so the header updates when format changes.\n // deriveFileName is tiny but it lives inside codeTransformer, which is only\n // imported when actually needed (non-TypeScript selection).\n const [displayedFileName, setDisplayedFileName] = useState<\n string | undefined\n >(fileName);\n\n useEffect(() => {\n if (!isMultiFormat || resolvedFormat === 'typescript') {\n setDisplayedFileName(fileName);\n return;\n }\n if (!fileName) return;\n\n let cancelled = false;\n (async () => {\n const { deriveFileName } = await import('./codeTransformer');\n if (!cancelled)\n setDisplayedFileName(deriveFileName(fileName, resolvedFormat));\n })();\n return () => {\n cancelled = true;\n };\n }, [fileName, isMultiFormat, resolvedFormat]);\n\n // ── Async copy text (transformed code for CopyCode) ───────────────────────\n const rawCode = useMemo(() => {\n const code = Array.isArray(children) ? children.join('') : String(children);\n return code.endsWith('\\n') ? code.slice(0, -1) : code;\n }, [children]);\n\n const [copyCode, setCopyCode] = useState<string>(rawCode);\n\n useEffect(() => {\n if (!isMultiFormat || resolvedFormat === 'typescript') {\n setCopyCode(rawCode);\n return;\n }\n let cancelled = false;\n (async () => {\n const { transformCode } = await import('./codeTransformer');\n if (!cancelled) setCopyCode(transformCode(rawCode, resolvedFormat));\n })();\n return () => {\n cancelled = true;\n };\n }, [rawCode, isMultiFormat, resolvedFormat]);\n\n const hadSelectInHeader =\n packageManager || rawCodeFormat || rawContentDeclarationFormat;\n\n return (\n <CodeConditionalRender\n packageManager={packageManager}\n codeFormat={rawCodeFormat as string | undefined}\n contentDeclarationFormat={\n rawContentDeclarationFormat as string | undefined\n }\n >\n <Container\n className={cn(\n 'relative min-w-0 max-w-full text-sm leading-6',\n showLineNumbers && 'with-line-number ml-0',\n className\n )}\n transparency=\"lg\"\n {...props}\n >\n {showHeader && (\n <>\n <div className=\"grid w-full grid-cols-[1fr_auto] items-center justify-between rounded-t-xl bg-card/50 py-1.5 pr-12 pl-4 text-neutral text-xs\">\n <span className=\"truncate\">{displayedFileName ?? language}</span>\n <div className=\"flex items-center gap-2\">\n {packageManager && <PackageManagerSelector />}\n {rawCodeFormat && (\n <CodeFormatSelector availableFormats={effectiveFormats} />\n )}\n {rawContentDeclarationFormat && (\n <ContentDeclarationFormatSelector />\n )}\n </div>\n </div>\n <div className=\"sticky top-46 z-20\">\n <div\n className={cn(\n 'absolute right-2 bottom-0 flex h-7 items-center',\n hadSelectInHeader && 'h-11'\n )}\n >\n <CopyCode code={copyCode} />\n </div>\n </div>\n </>\n )}\n <ExpandCollapse\n minHeight={MIN_HEIGHT}\n isRollable={isRollable}\n className=\"min-w-0 max-w-full overflow-x-auto p-2\"\n >\n {isMultiFormat ? (\n /*\n * Multi-format: CodeBlockHighlight manages both the transformation\n * (dynamic import of codeTransformer) and the Shiki highlighting in\n * a single useEffect. The previous highlighted output stays visible\n * while the new one loads — no white-text flash.\n */\n <CodeBlockHighlight\n originalLang={language}\n targetFormat={resolvedFormat}\n initialHtml={highlightedHtml}\n >\n {rawCode}\n </CodeBlockHighlight>\n ) : (\n /*\n * Single-format: paint the pre-highlighted markup when it was\n * supplied, otherwise fall back to the Suspense-based async Shiki\n * renderer.\n */\n <CodeBlock lang={language} highlightedHtml={highlightedHtml}>\n {rawCode}\n </CodeBlock>\n )}\n </ExpandCollapse>\n </Container>\n </CodeConditionalRender>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Code.mjs","names":[],"sources":["../../../../src/components/IDE/Code.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport type { FC, HTMLAttributes, ReactNode } from 'react';\nimport { useEffect, useMemo, useState } from 'react';\nimport { Container } from '../Container';\nimport { ExpandCollapse } from '../ExpandCollapse';\nimport { CodeBlock } from './CodeBlockClient';\nimport { CodeBlockHighlight } from './CodeBlockHighlight';\nimport { CodeConditionalRender } from './CodeConditionalRenderer';\nimport type {\n CodeFormat,\n ContentDeclarationFormat,\n PackageManager,\n} from './CodeContext';\nimport { useCodeContext } from './CodeContext';\nimport { CodeFormatSelector } from './CodeFormatSelector';\nimport { ContentDeclarationFormatSelector } from './ContentDeclarationFormatSelector';\nimport { CopyCode } from './CopyCode';\nimport { PackageManagerSelector } from './PackageManagerSelector';\nimport type { CodeLanguage } from './shikiLanguages';\n\nexport type CodeCompAttributes = {\n fileName?: string;\n packageManager?: PackageManager;\n /** Single format, a JSON-array string, or an array of formats. */\n codeFormat?: CodeFormat | string | string[];\n contentDeclarationFormat?: ContentDeclarationFormat | string | string[];\n};\n\ntype CodeCompProps = {\n children: ReactNode;\n fileName?: string;\n language: CodeLanguage;\n /**\n * Markup for `children`, highlighted by Shiki ahead of time. When present the\n * block paints straight from it and the highlighter is never downloaded —\n * except when the reader switches the block to a non-TypeScript format.\n */\n highlightedHtml?: string;\n showHeader?: boolean;\n showLineNumbers?: boolean;\n isRollable?: boolean;\n} & CodeCompAttributes &\n HTMLAttributes<HTMLDivElement>;\n\nconst MIN_HEIGHT = 700;\n\n/** Languages that use JSX syntax — CommonJS doesn't make sense for these. */\nconst JSX_LANGUAGES = new Set(['tsx', 'jsx']);\n\n/** Parse a codeFormat prop that may be a single value, a JSON-array string, or already an array. */\nconst parseFormats = (\n raw: string | string[] | undefined\n): CodeFormat[] | undefined => {\n if (!raw) return undefined;\n if (Array.isArray(raw)) return raw as CodeFormat[];\n if (typeof raw === 'string' && raw.startsWith('[')) {\n try {\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) return parsed as CodeFormat[];\n } catch {\n /* ignore */\n }\n }\n return [raw as CodeFormat];\n};\n\nexport const Code: FC<CodeCompProps> = ({\n children,\n language,\n highlightedHtml,\n showHeader = true,\n showLineNumbers = true,\n className,\n fileName,\n packageManager,\n codeFormat: rawCodeFormat,\n contentDeclarationFormat: rawContentDeclarationFormat,\n isRollable = true,\n lang, // Destructure html lang prop to prevent passing invalid BCP-47 language tag to Code component\n ...props\n}) => {\n const {\n codeFormat: selectedCodeFormat,\n contentDeclarationFormat: selectedContentDeclarationFormat,\n } = useCodeContext();\n\n // Parse whichever attribute is present as an array of formats.\n const codeFormats = useMemo(\n () => parseFormats(rawCodeFormat as string | undefined),\n [rawCodeFormat]\n );\n const contentFormats = useMemo(\n () => parseFormats(rawContentDeclarationFormat as string | undefined),\n [rawContentDeclarationFormat]\n );\n\n // A block is \"multi-format\" when it has multiple formats including TypeScript\n // (the canonical source). Such blocks transform at runtime.\n const isMultiCodeFormat =\n codeFormats !== undefined &&\n codeFormats.length > 1 &&\n codeFormats.includes('typescript');\n\n const isMultiContentFormat =\n contentFormats !== undefined &&\n contentFormats.length > 1 &&\n contentFormats.includes('typescript');\n\n const isMultiFormat = isMultiCodeFormat || isMultiContentFormat;\n\n // Determine which context format drives this block's selection.\n // content declaration blocks use selectedContentDeclarationFormat;\n // regular code blocks use selectedCodeFormat.\n const selectedFormat: CodeFormat = isMultiContentFormat\n ? (selectedContentDeclarationFormat as CodeFormat)\n : selectedCodeFormat;\n\n // The formats actually relevant for transformation (no 'json', no 'commonjs' for JSX).\n const effectiveFormats = useMemo<CodeFormat[] | undefined>(() => {\n const base = isMultiContentFormat ? contentFormats : codeFormats;\n if (!base) return base;\n let filtered = base.filter((f) => f !== 'json') as CodeFormat[];\n if (JSX_LANGUAGES.has(language as string)) {\n filtered = filtered.filter((f) => f !== 'commonjs');\n }\n return filtered;\n }, [isMultiContentFormat, contentFormats, codeFormats, language]);\n\n // When the globally-selected format isn't valid for this block\n // (e.g. CJS selected but this is a JSX file), fall back to the last valid one.\n const resolvedFormat: Exclude<CodeFormat, 'json'> = useMemo(() => {\n if (!effectiveFormats || effectiveFormats.includes(selectedFormat)) {\n return selectedFormat as Exclude<CodeFormat, 'json'>;\n }\n return (effectiveFormats[effectiveFormats.length - 1] ??\n 'typescript') as Exclude<CodeFormat, 'json'>;\n }, [effectiveFormats, selectedFormat]);\n\n // ── Async filename derivation (dynamic import of transformer) ──────────────\n // We derive the displayed fileName so the header updates when format changes.\n // deriveFileName is tiny but it lives inside codeTransformer, which is only\n // imported when actually needed (non-TypeScript selection).\n const [displayedFileName, setDisplayedFileName] = useState<\n string | undefined\n >(fileName);\n\n useEffect(() => {\n if (!isMultiFormat || resolvedFormat === 'typescript') {\n setDisplayedFileName(fileName);\n return;\n }\n if (!fileName) return;\n\n let cancelled = false;\n (async () => {\n const { deriveFileName } = await import('./codeTransformer');\n if (!cancelled)\n setDisplayedFileName(deriveFileName(fileName, resolvedFormat));\n })();\n return () => {\n cancelled = true;\n };\n }, [fileName, isMultiFormat, resolvedFormat]);\n\n // ── Async copy text (transformed code for CopyCode) ───────────────────────\n const rawCode = useMemo(() => {\n const code = Array.isArray(children) ? children.join('') : String(children);\n return code.endsWith('\\n') ? code.slice(0, -1) : code;\n }, [children]);\n\n const [copyCode, setCopyCode] = useState<string>(rawCode);\n\n useEffect(() => {\n if (!isMultiFormat || resolvedFormat === 'typescript') {\n setCopyCode(rawCode);\n return;\n }\n let cancelled = false;\n (async () => {\n const { transformCode } = await import('./codeTransformer');\n if (!cancelled) setCopyCode(transformCode(rawCode, resolvedFormat));\n })();\n return () => {\n cancelled = true;\n };\n }, [rawCode, isMultiFormat, resolvedFormat]);\n\n const hadSelectInHeader =\n packageManager || rawCodeFormat || rawContentDeclarationFormat;\n\n return (\n <CodeConditionalRender\n packageManager={packageManager}\n codeFormat={rawCodeFormat as string | undefined}\n contentDeclarationFormat={\n rawContentDeclarationFormat as string | undefined\n }\n >\n <Container\n className={cn(\n 'relative min-w-0 max-w-full text-sm leading-6',\n showLineNumbers && 'with-line-number ml-0',\n className\n )}\n transparency=\"lg\"\n {...props}\n >\n {showHeader && (\n <>\n <div className=\"grid w-full grid-cols-[1fr_auto] items-center justify-between rounded-t-xl border-b bg-card/50 py-1.5 pr-12 pl-4 text-muted-foreground text-xs\">\n <span className=\"truncate\">{displayedFileName ?? language}</span>\n <div className=\"flex items-center gap-2\">\n {packageManager && <PackageManagerSelector />}\n {rawCodeFormat && (\n <CodeFormatSelector availableFormats={effectiveFormats} />\n )}\n {rawContentDeclarationFormat && (\n <ContentDeclarationFormatSelector />\n )}\n </div>\n </div>\n <div className=\"sticky top-46 z-20\">\n <div\n className={cn(\n 'absolute right-2 bottom-0 flex h-7 items-center',\n hadSelectInHeader && 'h-11'\n )}\n >\n <CopyCode code={copyCode} />\n </div>\n </div>\n </>\n )}\n <ExpandCollapse\n minHeight={MIN_HEIGHT}\n isRollable={isRollable}\n className=\"min-w-0 max-w-full overflow-x-auto p-2\"\n >\n {isMultiFormat ? (\n /*\n * Multi-format: CodeBlockHighlight manages both the transformation\n * (dynamic import of codeTransformer) and the Shiki highlighting in\n * a single useEffect. The previous highlighted output stays visible\n * while the new one loads — no white-text flash.\n */\n <CodeBlockHighlight\n originalLang={language}\n targetFormat={resolvedFormat}\n initialHtml={highlightedHtml}\n >\n {rawCode}\n </CodeBlockHighlight>\n ) : (\n /*\n * Single-format: paint the pre-highlighted markup when it was\n * supplied, otherwise fall back to the Suspense-based async Shiki\n * renderer.\n */\n <CodeBlock lang={language} highlightedHtml={highlightedHtml}>\n {rawCode}\n </CodeBlock>\n )}\n </ExpandCollapse>\n </Container>\n </CodeConditionalRender>\n );\n};\n"],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@ const FileList = ({ filePaths, ...props }) => /* @__PURE__ */ jsxs(Container, {
|
|
|
9
9
|
transparency: "none",
|
|
10
10
|
...props,
|
|
11
11
|
children: [/* @__PURE__ */ jsx("div", {
|
|
12
|
-
className: "flex w-auto flex-row items-center justify-start gap-1 rounded-t-3xl bg-neutral-200 text-
|
|
12
|
+
className: "flex w-auto flex-row items-center justify-start gap-1 rounded-t-3xl bg-neutral-200 text-muted-foreground text-xs dark:bg-neutral-950",
|
|
13
13
|
children: /* @__PURE__ */ jsxs("div", {
|
|
14
14
|
className: "mx-2 flex items-center justify-start gap-2 p-1",
|
|
15
15
|
children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileList.mjs","names":[],"sources":["../../../../src/components/IDE/FileList.tsx"],"sourcesContent":["import type { FC, HTMLAttributes } from 'react';\nimport { Container } from '../Container';\nimport { FileTree } from './FileTree';\n\nexport type FileListProps = {\n filePaths: string[];\n} & HTMLAttributes<HTMLDivElement>;\n\nexport const FileList: FC<FileListProps> = ({ filePaths, ...props }) => (\n <Container\n className=\"flex size-full flex-col justify-start overflow-auto shadow-lg\"\n roundedSize=\"3xl\"\n transparency=\"none\"\n {...props}\n >\n <div className=\"flex w-auto flex-row items-center justify-start gap-1 rounded-t-3xl bg-neutral-200 text-
|
|
1
|
+
{"version":3,"file":"FileList.mjs","names":[],"sources":["../../../../src/components/IDE/FileList.tsx"],"sourcesContent":["import type { FC, HTMLAttributes } from 'react';\nimport { Container } from '../Container';\nimport { FileTree } from './FileTree';\n\nexport type FileListProps = {\n filePaths: string[];\n} & HTMLAttributes<HTMLDivElement>;\n\nexport const FileList: FC<FileListProps> = ({ filePaths, ...props }) => (\n <Container\n className=\"flex size-full flex-col justify-start overflow-auto shadow-lg\"\n roundedSize=\"3xl\"\n transparency=\"none\"\n {...props}\n >\n <div className=\"flex w-auto flex-row items-center justify-start gap-1 rounded-t-3xl bg-neutral-200 text-muted-foreground text-xs dark:bg-neutral-950\">\n <div className=\"mx-2 flex items-center justify-start gap-2 p-1\">\n <div className=\"size-3 rounded-full bg-error\" />\n <div className=\"size-3 rounded-full bg-yellow-500\" />\n <div className=\"size-3 rounded-full bg-green-500\" />\n </div>\n </div>\n <div className=\"relative flex size-full flex-1 flex-row justify-start shadow-lg\">\n <div className=\"absolute top-0 left-0 size-full\">\n <div className=\"flex size-full\">\n <FileTree filesPaths={filePaths} />\n </div>\n </div>\n </div>\n </Container>\n);\n"],"mappings":";;;;;AAQA,MAAa,YAA+B,EAAE,WAAW,GAAG,YAC1D,qBAAC,WAAD;CACE,WAAU;CACV,aAAY;CACZ,cAAa;CACb,GAAI;WAJN,CAME,oBAAC,OAAD;EAAK,WAAU;YACb,qBAAC,OAAD;GAAK,WAAU;aAAf;IACE,oBAAC,OAAD,EAAK,WAAU,+BAAgC;IAC/C,oBAAC,OAAD,EAAK,WAAU,oCAAqC;IACpD,oBAAC,OAAD,EAAK,WAAU,mCAAoC;GAChD;;CACF,IACL,oBAAC,OAAD;EAAK,WAAU;YACb,oBAAC,OAAD;GAAK,WAAU;aACb,oBAAC,OAAD;IAAK,WAAU;cACb,oBAAC,UAAD,EAAU,YAAY,UAAY;GAC/B;EACF;CACF,EACI"}
|
|
@@ -48,7 +48,7 @@ const FileItem = ({ filesPaths, path, subPath, onClickFile, activeFile, prePaths
|
|
|
48
48
|
const FileTree = ({ filesPaths, activeFile, onClickFile, prePaths = [] }) => {
|
|
49
49
|
const fileTree = createFileTree(filesPaths);
|
|
50
50
|
return /* @__PURE__ */ jsx("div", {
|
|
51
|
-
className: "flex size-full flex-col items-start justify-start py-1 text-
|
|
51
|
+
className: "flex size-full flex-col items-start justify-start py-1 text-muted-foreground",
|
|
52
52
|
children: fileTree.map(({ path, subPath, isFile }) => /* @__PURE__ */ jsx(FileItem, {
|
|
53
53
|
isFile,
|
|
54
54
|
subPath,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileTree.mjs","names":[],"sources":["../../../../src/components/IDE/FileTree.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport { ChevronRight } from 'lucide-react';\nimport { type FC, useState } from 'react';\nimport { MaxHeightSmoother } from '../MaxHeightSmoother';\nimport { createFileTree, type FilePath } from './createFileTree';\n\ntype FileTreeProps = {\n filesPaths: string[];\n activeFile?: string;\n onClickFile?: (filePath: string) => void;\n prePaths?: string[];\n};\n\nconst concatFilePath = (paths: string[]) => paths.join('/');\n\ntype FileItemProps = {\n filesPaths: string[];\n subPath?: FilePath[];\n path: string;\n onClickFile?: (title: string) => void;\n activeFile?: string;\n prePaths: string[];\n isFile: boolean;\n};\n\nconst FileItem: FC<FileItemProps> = ({\n filesPaths,\n path,\n subPath,\n onClickFile,\n activeFile,\n prePaths,\n isFile,\n}) => {\n const [subPathOpen, setSubPathOpen] = useState(true);\n\n const level = prePaths.length + 1;\n const currentPath = concatFilePath([\n ...prePaths.slice(level - 1, level),\n path,\n ]);\n const totalPath = concatFilePath([...prePaths, path]);\n\n const filteredFilePaths = filesPaths\n .map(\n (path) => path.replace(/^\\/?/, '') // This regex matches the first slash, if it exists, at the start of the string)\n )\n .filter((filePath) => filePath.startsWith(currentPath));\n\n const newPath = filteredFilePaths.map((path) =>\n path.replace(currentPath, '').replace(/^\\/?/, '')\n );\n\n const isActive = totalPath === activeFile;\n\n const indentation = new Array(level).fill(' ').join('');\n\n return (\n <>\n <button\n className={cn(\n 'flex w-full items-start justify-start whitespace-pre text-nowrap px-2 py-1 text-xs transition',\n isActive\n ? 'bg-neutral-200 dark:bg-neutral-800'\n : 'cursor-pointer hover:bg-neutral-300 dark:hover:bg-neutral-900'\n )}\n key={path}\n onClick={() => {\n if (isFile) {\n onClickFile?.(totalPath);\n } else {\n setSubPathOpen(!subPathOpen);\n }\n }}\n >\n <span className={cn('whitespace-pre', isFile && 'ml-2')}>\n {indentation}\n </span>\n\n {!isFile && (\n <ChevronRight\n className={cn(`transition`, subPathOpen && `rotate-90 transform`)}\n size={16}\n />\n )}\n {path}\n </button>\n {subPath && (\n <MaxHeightSmoother\n isHidden={!subPathOpen}\n className=\"overflow-x-hidden\"\n >\n <FileTree\n filesPaths={newPath}\n activeFile={activeFile}\n onClickFile={onClickFile}\n prePaths={[...prePaths, path]}\n />\n </MaxHeightSmoother>\n )}\n </>\n );\n};\n\nexport const FileTree: FC<FileTreeProps> = ({\n filesPaths,\n activeFile,\n onClickFile,\n prePaths = [],\n}) => {\n const fileTree = createFileTree(filesPaths);\n\n return (\n <div className=\"flex size-full flex-col items-start justify-start py-1 text-
|
|
1
|
+
{"version":3,"file":"FileTree.mjs","names":[],"sources":["../../../../src/components/IDE/FileTree.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport { ChevronRight } from 'lucide-react';\nimport { type FC, useState } from 'react';\nimport { MaxHeightSmoother } from '../MaxHeightSmoother';\nimport { createFileTree, type FilePath } from './createFileTree';\n\ntype FileTreeProps = {\n filesPaths: string[];\n activeFile?: string;\n onClickFile?: (filePath: string) => void;\n prePaths?: string[];\n};\n\nconst concatFilePath = (paths: string[]) => paths.join('/');\n\ntype FileItemProps = {\n filesPaths: string[];\n subPath?: FilePath[];\n path: string;\n onClickFile?: (title: string) => void;\n activeFile?: string;\n prePaths: string[];\n isFile: boolean;\n};\n\nconst FileItem: FC<FileItemProps> = ({\n filesPaths,\n path,\n subPath,\n onClickFile,\n activeFile,\n prePaths,\n isFile,\n}) => {\n const [subPathOpen, setSubPathOpen] = useState(true);\n\n const level = prePaths.length + 1;\n const currentPath = concatFilePath([\n ...prePaths.slice(level - 1, level),\n path,\n ]);\n const totalPath = concatFilePath([...prePaths, path]);\n\n const filteredFilePaths = filesPaths\n .map(\n (path) => path.replace(/^\\/?/, '') // This regex matches the first slash, if it exists, at the start of the string)\n )\n .filter((filePath) => filePath.startsWith(currentPath));\n\n const newPath = filteredFilePaths.map((path) =>\n path.replace(currentPath, '').replace(/^\\/?/, '')\n );\n\n const isActive = totalPath === activeFile;\n\n const indentation = new Array(level).fill(' ').join('');\n\n return (\n <>\n <button\n className={cn(\n 'flex w-full items-start justify-start whitespace-pre text-nowrap px-2 py-1 text-xs transition',\n isActive\n ? 'bg-neutral-200 dark:bg-neutral-800'\n : 'cursor-pointer hover:bg-neutral-300 dark:hover:bg-neutral-900'\n )}\n key={path}\n onClick={() => {\n if (isFile) {\n onClickFile?.(totalPath);\n } else {\n setSubPathOpen(!subPathOpen);\n }\n }}\n >\n <span className={cn('whitespace-pre', isFile && 'ml-2')}>\n {indentation}\n </span>\n\n {!isFile && (\n <ChevronRight\n className={cn(`transition`, subPathOpen && `rotate-90 transform`)}\n size={16}\n />\n )}\n {path}\n </button>\n {subPath && (\n <MaxHeightSmoother\n isHidden={!subPathOpen}\n className=\"overflow-x-hidden\"\n >\n <FileTree\n filesPaths={newPath}\n activeFile={activeFile}\n onClickFile={onClickFile}\n prePaths={[...prePaths, path]}\n />\n </MaxHeightSmoother>\n )}\n </>\n );\n};\n\nexport const FileTree: FC<FileTreeProps> = ({\n filesPaths,\n activeFile,\n onClickFile,\n prePaths = [],\n}) => {\n const fileTree = createFileTree(filesPaths);\n\n return (\n <div className=\"flex size-full flex-col items-start justify-start py-1 text-muted-foreground\">\n {fileTree.map(({ path, subPath, isFile }) => (\n <FileItem\n key={path}\n isFile={isFile}\n subPath={subPath}\n path={path}\n onClickFile={onClickFile}\n activeFile={activeFile}\n prePaths={prePaths}\n filesPaths={filesPaths}\n />\n ))}\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;AAeA,MAAM,kBAAkB,UAAoB,MAAM,KAAK,GAAG;AAY1D,MAAM,YAA+B,EACnC,YACA,MACA,SACA,aACA,YACA,UACA,aACI;CACJ,MAAM,CAAC,aAAa,kBAAkB,SAAS,IAAI;CAEnD,MAAM,QAAQ,SAAS,SAAS;CAChC,MAAM,cAAc,eAAe,CACjC,GAAG,SAAS,MAAM,QAAQ,GAAG,KAAK,GAClC,IACF,CAAC;CACD,MAAM,YAAY,eAAe,CAAC,GAAG,UAAU,IAAI,CAAC;CAQpD,MAAM,UANoB,WACvB,KACE,SAAS,KAAK,QAAQ,QAAQ,EAAE,CACnC,CAAC,CACA,QAAQ,aAAa,SAAS,WAAW,WAAW,CAEvB,CAAC,CAAC,KAAK,SACrC,KAAK,QAAQ,aAAa,EAAE,CAAC,CAAC,QAAQ,QAAQ,EAAE,CAClD;CAEA,MAAM,WAAW,cAAc;CAE/B,MAAM,cAAc,IAAI,MAAM,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,EAAE;CAEvD,OACE,8CACE,qBAAC,UAAD;EACE,WAAW,GACT,iGACA,WACI,uCACA,+DACN;EAEA,eAAe;GACb,IAAI,QACF,cAAc,SAAS;QAEvB,eAAe,CAAC,WAAW;EAE/B;YAdF;GAgBE,oBAAC,QAAD;IAAM,WAAW,GAAG,kBAAkB,UAAU,MAAM;cACnD;GACG;GAEL,CAAC,UACA,oBAAC,cAAD;IACE,WAAW,GAAG,cAAc,eAAe,qBAAqB;IAChE,MAAM;GACP;GAEF;EACK;IApBD,IAoBC,GACP,WACC,oBAAC,mBAAD;EACE,UAAU,CAAC;EACX,WAAU;YAEV,oBAAC,UAAD;GACE,YAAY;GACA;GACC;GACb,UAAU,CAAC,GAAG,UAAU,IAAI;EAC7B;CACgB,EAErB;AAEN;AAEA,MAAa,YAA+B,EAC1C,YACA,YACA,aACA,WAAW,CAAC,QACR;CACJ,MAAM,WAAW,eAAe,UAAU;CAE1C,OACE,oBAAC,OAAD;EAAK,WAAU;YACZ,SAAS,KAAK,EAAE,MAAM,SAAS,aAC9B,oBAAC,UAAD;GAEU;GACC;GACH;GACO;GACD;GACF;GACE;EACb,GARM,IAQN,CACF;CACE;AAET"}
|
|
@@ -33,12 +33,12 @@ const IDE = ({ pages: initialPages, className, activeTab: defaultActiveTab, ...p
|
|
|
33
33
|
setActiveTab(newPageIndex);
|
|
34
34
|
};
|
|
35
35
|
return /* @__PURE__ */ jsxs(Container, {
|
|
36
|
-
className: cn("flex size-full flex-col justify-start overflow-hidden
|
|
37
|
-
roundedSize: "
|
|
36
|
+
className: cn("flex size-full flex-col justify-start overflow-hidden border", className),
|
|
37
|
+
roundedSize: "lg",
|
|
38
38
|
transparency: "none",
|
|
39
39
|
...props,
|
|
40
40
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
41
|
-
className: "flex w-auto flex-row items-center justify-start gap-1 bg-
|
|
41
|
+
className: "flex w-auto flex-row items-center justify-start gap-1 border-b bg-card text-muted-foreground text-xs",
|
|
42
42
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
43
43
|
className: "mx-2 flex items-center justify-start gap-2 p-1",
|
|
44
44
|
children: [
|
|
@@ -47,12 +47,12 @@ const IDE = ({ pages: initialPages, className, activeTab: defaultActiveTab, ...p
|
|
|
47
47
|
/* @__PURE__ */ jsx("div", { className: "size-3 rounded-full bg-green-500" })
|
|
48
48
|
]
|
|
49
49
|
}), /* @__PURE__ */ jsx("div", {
|
|
50
|
-
className: "flex
|
|
50
|
+
className: "flex h-full divide-x overflow-y-auto border-x",
|
|
51
51
|
children: tabs.map(({ path }, index) => {
|
|
52
52
|
const fullPath = path.split("/");
|
|
53
53
|
const title = fullPath[fullPath.length - 1];
|
|
54
54
|
return /* @__PURE__ */ jsx("button", {
|
|
55
|
-
className: cn("flex h-8 min-w-20 max-w-
|
|
55
|
+
className: cn("flex h-8 min-w-20 max-w-100 items-center justify-start truncate text-nowrap px-3 py-1 transition", index === activeTab ? "bg-background font-medium text-foreground" : "cursor-pointer opacity-80 hover:text-foreground hover:opacity-100"),
|
|
56
56
|
onClick: () => setActiveTab(index),
|
|
57
57
|
children: title
|
|
58
58
|
}, title);
|
|
@@ -75,8 +75,11 @@ const IDE = ({ pages: initialPages, className, activeTab: defaultActiveTab, ...p
|
|
|
75
75
|
})
|
|
76
76
|
})
|
|
77
77
|
}), /* @__PURE__ */ jsx("div", {
|
|
78
|
-
className: "size-full flex-1 overflow-auto
|
|
79
|
-
children: /* @__PURE__ */ jsx(MarkdownRenderer, {
|
|
78
|
+
className: "size-full flex-1 overflow-auto bg-background text-xs",
|
|
79
|
+
children: content && /* @__PURE__ */ jsx(MarkdownRenderer, {
|
|
80
|
+
codeClassName: "bg-background rounded-none",
|
|
81
|
+
children: content
|
|
82
|
+
})
|
|
80
83
|
})]
|
|
81
84
|
})
|
|
82
85
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IDE.mjs","names":[],"sources":["../../../../src/components/IDE/IDE.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport { type FC, type HTMLAttributes, useEffect, useState } from 'react';\nimport { Container } from '../Container';\nimport { WithResizer } from '../WithResizer';\nimport { FileTree } from './FileTree';\nimport { MarkdownRenderer } from './MarkDownRender';\n\nexport type IDEProps = {\n pages: {\n path: string;\n content: string;\n isOpen?: boolean;\n }[];\n activeTab?: number;\n} & HTMLAttributes<HTMLDivElement>;\n\nexport const IDE: FC<IDEProps> = ({\n pages: initialPages,\n className,\n activeTab: defaultActiveTab,\n ...props\n}) => {\n const [pages, setPages] = useState(initialPages);\n const tabs = pages.filter(({ isOpen }) => isOpen);\n\n const firstTabIndex = tabs.findIndex(({ isOpen }) => isOpen);\n const [activeTab, setActiveTab] = useState(defaultActiveTab ?? firstTabIndex);\n\n useEffect(() => {\n setActiveTab(defaultActiveTab ?? firstTabIndex);\n }, [initialPages, defaultActiveTab]);\n\n const { content, path } = pages[activeTab] ?? {};\n const filePaths = initialPages.map(({ path: title }) => title);\n\n const handleClickFile = (title: string) => {\n const page = pages.find(({ path: tabTitle }) => tabTitle === title);\n if (!page) return;\n\n const newPages = pages.map((page) => {\n if (page.path === title) {\n return { ...page, isOpen: true };\n }\n return page;\n });\n\n setPages(newPages);\n\n const newPageIndex = newPages.findIndex(\n ({ path: tabTitle }) => tabTitle === title\n );\n\n setActiveTab(newPageIndex);\n };\n\n return (\n <Container\n className={cn(\n 'flex size-full flex-col justify-start overflow-hidden
|
|
1
|
+
{"version":3,"file":"IDE.mjs","names":[],"sources":["../../../../src/components/IDE/IDE.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport { type FC, type HTMLAttributes, useEffect, useState } from 'react';\nimport { Container } from '../Container';\nimport { WithResizer } from '../WithResizer';\nimport { FileTree } from './FileTree';\nimport { MarkdownRenderer } from './MarkDownRender';\n\nexport type IDEProps = {\n pages: {\n path: string;\n content: string;\n isOpen?: boolean;\n }[];\n activeTab?: number;\n} & HTMLAttributes<HTMLDivElement>;\n\nexport const IDE: FC<IDEProps> = ({\n pages: initialPages,\n className,\n activeTab: defaultActiveTab,\n ...props\n}) => {\n const [pages, setPages] = useState(initialPages);\n const tabs = pages.filter(({ isOpen }) => isOpen);\n\n const firstTabIndex = tabs.findIndex(({ isOpen }) => isOpen);\n const [activeTab, setActiveTab] = useState(defaultActiveTab ?? firstTabIndex);\n\n useEffect(() => {\n setActiveTab(defaultActiveTab ?? firstTabIndex);\n }, [initialPages, defaultActiveTab]);\n\n const { content, path } = pages[activeTab] ?? {};\n const filePaths = initialPages.map(({ path: title }) => title);\n\n const handleClickFile = (title: string) => {\n const page = pages.find(({ path: tabTitle }) => tabTitle === title);\n if (!page) return;\n\n const newPages = pages.map((page) => {\n if (page.path === title) {\n return { ...page, isOpen: true };\n }\n return page;\n });\n\n setPages(newPages);\n\n const newPageIndex = newPages.findIndex(\n ({ path: tabTitle }) => tabTitle === title\n );\n\n setActiveTab(newPageIndex);\n };\n\n return (\n <Container\n className={cn(\n 'flex size-full flex-col justify-start overflow-hidden border',\n className\n )}\n roundedSize=\"lg\"\n transparency=\"none\"\n {...props}\n >\n <div className=\"flex w-auto flex-row items-center justify-start gap-1 border-b bg-card text-muted-foreground text-xs\">\n <div className=\"mx-2 flex items-center justify-start gap-2 p-1\">\n <div className=\"size-3 rounded-full bg-error\" />\n <div className=\"size-3 rounded-full bg-yellow-500\" />\n <div className=\"size-3 rounded-full bg-green-500\" />\n </div>\n <div className=\"flex h-full divide-x overflow-y-auto border-x\">\n {tabs.map(({ path }, index) => {\n const fullPath = path.split('/');\n const title = fullPath[fullPath.length - 1];\n const isActive = index === activeTab;\n\n return (\n <button\n className={cn(\n 'flex h-8 min-w-20 max-w-100 items-center justify-start truncate text-nowrap px-3 py-1 transition',\n isActive\n ? 'bg-background font-medium text-foreground'\n : 'cursor-pointer opacity-80 hover:text-foreground hover:opacity-100'\n )}\n key={title}\n onClick={() => setActiveTab(index)}\n >\n {title}\n </button>\n );\n })}\n </div>\n </div>\n <div className=\"relative flex size-full flex-1 flex-row justify-start\">\n <div className=\"absolute top-0 left-0 size-full\">\n <div className=\"flex size-full\">\n <WithResizer initialWidth={150}>\n <div className=\"max-h-full flex-1 overflow-y-auto\">\n <FileTree\n filesPaths={filePaths}\n activeFile={path}\n onClickFile={handleClickFile}\n />\n </div>\n </WithResizer>\n\n <div className=\"size-full flex-1 overflow-auto bg-background text-xs\">\n {content && (\n <MarkdownRenderer codeClassName=\"bg-background rounded-none\">\n {content}\n </MarkdownRenderer>\n )}\n </div>\n </div>\n </div>\n </div>\n </Container>\n );\n};\n"],"mappings":";;;;;;;;;;;AAkBA,MAAa,OAAqB,EAChC,OAAO,cACP,WACA,WAAW,kBACX,GAAG,YACC;CACJ,MAAM,CAAC,OAAO,YAAY,SAAS,YAAY;CAC/C,MAAM,OAAO,MAAM,QAAQ,EAAE,aAAa,MAAM;CAEhD,MAAM,gBAAgB,KAAK,WAAW,EAAE,aAAa,MAAM;CAC3D,MAAM,CAAC,WAAW,gBAAgB,SAAS,oBAAoB,aAAa;CAE5E,gBAAgB;EACd,aAAa,oBAAoB,aAAa;CAChD,GAAG,CAAC,cAAc,gBAAgB,CAAC;CAEnC,MAAM,EAAE,SAAS,SAAS,MAAM,cAAc,CAAC;CAC/C,MAAM,YAAY,aAAa,KAAK,EAAE,MAAM,YAAY,KAAK;CAE7D,MAAM,mBAAmB,UAAkB;EAEzC,IAAI,CADS,MAAM,MAAM,EAAE,MAAM,eAAe,aAAa,KACrD,GAAG;EAEX,MAAM,WAAW,MAAM,KAAK,SAAS;GACnC,IAAI,KAAK,SAAS,OAChB,OAAO;IAAE,GAAG;IAAM,QAAQ;GAAK;GAEjC,OAAO;EACT,CAAC;EAED,SAAS,QAAQ;EAEjB,MAAM,eAAe,SAAS,WAC3B,EAAE,MAAM,eAAe,aAAa,KACvC;EAEA,aAAa,YAAY;CAC3B;CAEA,OACE,qBAAC,WAAD;EACE,WAAW,GACT,gEACA,SACF;EACA,aAAY;EACZ,cAAa;EACb,GAAI;YAPN,CASE,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,qBAAC,OAAD;IAAK,WAAU;cAAf;KACE,oBAAC,OAAD,EAAK,WAAU,+BAAgC;KAC/C,oBAAC,OAAD,EAAK,WAAU,oCAAqC;KACpD,oBAAC,OAAD,EAAK,WAAU,mCAAoC;IAChD;OACL,oBAAC,OAAD;IAAK,WAAU;cACZ,KAAK,KAAK,EAAE,QAAQ,UAAU;KAC7B,MAAM,WAAW,KAAK,MAAM,GAAG;KAC/B,MAAM,QAAQ,SAAS,SAAS,SAAS;KAGzC,OACE,oBAAC,UAAD;MACE,WAAW,GACT,oGALW,UAAU,YAOjB,8CACA,mEACN;MAEA,eAAe,aAAa,KAAK;gBAEhC;KACK,GAJD,KAIC;IAEZ,CAAC;GACE,EACF;MACL,oBAAC,OAAD;GAAK,WAAU;aACb,oBAAC,OAAD;IAAK,WAAU;cACb,qBAAC,OAAD;KAAK,WAAU;eAAf,CACE,oBAAC,aAAD;MAAa,cAAc;gBACzB,oBAAC,OAAD;OAAK,WAAU;iBACb,oBAAC,UAAD;QACE,YAAY;QACZ,YAAY;QACZ,aAAa;OACd;MACE;KACM,IAEb,oBAAC,OAAD;MAAK,WAAU;gBACZ,WACC,oBAAC,kBAAD;OAAkB,eAAc;iBAC7B;MACe;KAEjB,EACF;;GACF;EACF,EACI;;AAEf"}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { Code } from "./Code.mjs";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import
|
|
3
|
+
import cn from "cnfast";
|
|
4
|
+
import { MarkdownRenderer as MarkdownRenderer$1 } from "react-intlayer/markdown";
|
|
4
5
|
|
|
5
6
|
//#region src/components/IDE/MarkDownRender.tsx
|
|
6
|
-
const MarkdownRenderer = ({ children }) => /* @__PURE__ */ jsx(MarkdownRenderer$1, {
|
|
7
|
+
const MarkdownRenderer = ({ children, codeClassName }) => /* @__PURE__ */ jsx(MarkdownRenderer$1, {
|
|
7
8
|
components: {
|
|
8
9
|
code: (props) => /* @__PURE__ */ jsx(Code, {
|
|
9
10
|
...props,
|
|
10
11
|
language: props.className?.replace("lang-", ""),
|
|
11
12
|
showHeader: false,
|
|
12
|
-
className: "text-xs leading-5",
|
|
13
|
+
className: cn("text-xs leading-5", codeClassName),
|
|
13
14
|
children: props.children
|
|
14
15
|
}),
|
|
15
16
|
pre: (props) => props.children
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkDownRender.mjs","names":["MarkdownRendererIntlayer"],"sources":["../../../../src/components/IDE/MarkDownRender.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { MarkdownRenderer as MarkdownRendererIntlayer } from 'react-intlayer';\nimport { Code } from './Code';\nimport type { CodeLanguage } from './shikiLanguages';\n\ntype MarkdownRendererProps = {\n children: string;\n};\n\nexport const MarkdownRenderer: FC<MarkdownRendererProps> = ({
|
|
1
|
+
{"version":3,"file":"MarkDownRender.mjs","names":["MarkdownRendererIntlayer"],"sources":["../../../../src/components/IDE/MarkDownRender.tsx"],"sourcesContent":["import cn from 'cnfast';\nimport type { FC } from 'react';\nimport { MarkdownRenderer as MarkdownRendererIntlayer } from 'react-intlayer/markdown';\nimport { Code } from './Code';\nimport type { CodeLanguage } from './shikiLanguages';\n\ntype MarkdownRendererProps = {\n codeClassName?: string;\n children: string;\n};\n\nexport const MarkdownRenderer: FC<MarkdownRendererProps> = ({\n children,\n codeClassName,\n}) => (\n <MarkdownRendererIntlayer\n components={{\n code: (props) => (\n <Code\n {...props}\n language={props.className?.replace('lang-', '') as CodeLanguage}\n showHeader={false}\n className={cn('text-xs leading-5', codeClassName)}\n >\n {props.children as string}\n </Code>\n ),\n pre: (props) => props.children,\n }}\n >\n {children ?? ''}\n </MarkdownRendererIntlayer>\n);\n"],"mappings":";;;;;;AAWA,MAAa,oBAA+C,EAC1D,UACA,oBAEA,oBAACA,oBAAD;CACE,YAAY;EACV,OAAO,UACL,oBAAC,MAAD;GACE,GAAI;GACJ,UAAU,MAAM,WAAW,QAAQ,SAAS,EAAE;GAC9C,YAAY;GACZ,WAAW,GAAG,qBAAqB,aAAa;aAE/C,MAAM;EACH;EAER,MAAM,UAAU,MAAM;CACxB;WAEC,YAAY;AACW"}
|
|
@@ -14,7 +14,7 @@ const checkboxVariants = cva([
|
|
|
14
14
|
"ring-0 transition-all duration-300 ease-in-out hover:ring-4 focus-visible:ring-6",
|
|
15
15
|
"checked:before:absolute checked:before:inset-0 checked:before:content-['✓']",
|
|
16
16
|
"checked:before:flex checked:before:items-center checked:before:justify-center",
|
|
17
|
-
"checked:before:text-
|
|
17
|
+
"checked:before:text-foreground-opposite/80",
|
|
18
18
|
"rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl",
|
|
19
19
|
"after:absolute after:-inset-2 after:content-['']"
|
|
20
20
|
].join(" "), {
|
|
@@ -29,10 +29,10 @@ const checkboxVariants = cva([
|
|
|
29
29
|
color: {
|
|
30
30
|
primary: "border-primary/30 text-primary ring-primary/20 checked:border-primary checked:bg-primary",
|
|
31
31
|
secondary: "border-secondary/30 text-secondary ring-secondary/20 checked:border-secondary checked:bg-secondary",
|
|
32
|
-
neutral: "border-neutral/30 text-
|
|
32
|
+
neutral: "border-neutral/30 text-muted-foreground ring-neutral/20 checked:border-neutral checked:bg-neutral",
|
|
33
33
|
light: "border-white/30 text-white ring-white/20 checked:border-white checked:bg-white",
|
|
34
|
-
text: "border-text/30 text-
|
|
35
|
-
"text-inverse": "border-text-inverse/30 text-
|
|
34
|
+
text: "border-text/30 text-foreground ring-text/20 checked:border-text checked:bg-text",
|
|
35
|
+
"text-inverse": "border-text-inverse/30 text-foreground-inverse ring-text-inverse/20 checked:border-text-inverse checked:bg-text-inverse",
|
|
36
36
|
dark: "border-neutral-800/30 text-neutral-800 ring-neutral-800/20 checked:border-neutral-800 checked:bg-neutral-800",
|
|
37
37
|
error: "border-error/30 text-error ring-error/20 checked:border-error checked:bg-error",
|
|
38
38
|
success: "border-success/30 text-success ring-success/20 checked:border-success checked:bg-success",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Checkbox.mjs","names":[],"sources":["../../../../src/components/Input/Checkbox.tsx"],"sourcesContent":["import { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport type {\n DetailedHTMLProps,\n FC,\n InputHTMLAttributes,\n ReactNode,\n} from 'react';\n\nexport const checkboxVariants = cva(\n [\n 'appearance-none',\n 'relative cursor-pointer border-2',\n 'focus:outline-0',\n 'checked:hover:opacity-80',\n 'ring-offset-background',\n 'hover:bg-neutral-500/10',\n 'disabled:opacity-50',\n\n // Ring + animation\n 'ring-0 transition-all duration-300 ease-in-out hover:ring-4 focus-visible:ring-6',\n\n // centered custom checkmark with text-opposite color\n \"checked:before:absolute checked:before:inset-0 checked:before:content-['✓']\",\n 'checked:before:flex checked:before:items-center checked:before:justify-center',\n 'checked:before:text-
|
|
1
|
+
{"version":3,"file":"Checkbox.mjs","names":[],"sources":["../../../../src/components/Input/Checkbox.tsx"],"sourcesContent":["import { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport type {\n DetailedHTMLProps,\n FC,\n InputHTMLAttributes,\n ReactNode,\n} from 'react';\n\nexport const checkboxVariants = cva(\n [\n 'appearance-none',\n 'relative cursor-pointer border-2',\n 'focus:outline-0',\n 'checked:hover:opacity-80',\n 'ring-offset-background',\n 'hover:bg-neutral-500/10',\n 'disabled:opacity-50',\n\n // Ring + animation\n 'ring-0 transition-all duration-300 ease-in-out hover:ring-4 focus-visible:ring-6',\n\n // centered custom checkmark with text-opposite color\n \"checked:before:absolute checked:before:inset-0 checked:before:content-['✓']\",\n 'checked:before:flex checked:before:items-center checked:before:justify-center',\n 'checked:before:text-foreground-opposite/80',\n\n // Corner shape\n 'rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl',\n\n \"after:absolute after:-inset-2 after:content-['']\",\n ].join(' '),\n {\n variants: {\n variant: {\n default: '',\n },\n size: {\n xs: 'size-3 rounded-sm',\n sm: 'size-4 rounded-md',\n md: 'size-5 rounded-lg',\n lg: 'size-6 rounded-xl',\n },\n color: {\n primary:\n 'border-primary/30 text-primary ring-primary/20 checked:border-primary checked:bg-primary',\n secondary:\n 'border-secondary/30 text-secondary ring-secondary/20 checked:border-secondary checked:bg-secondary',\n neutral:\n 'border-neutral/30 text-muted-foreground ring-neutral/20 checked:border-neutral checked:bg-neutral',\n light:\n 'border-white/30 text-white ring-white/20 checked:border-white checked:bg-white',\n text: 'border-text/30 text-foreground ring-text/20 checked:border-text checked:bg-text',\n 'text-inverse':\n 'border-text-inverse/30 text-foreground-inverse ring-text-inverse/20 checked:border-text-inverse checked:bg-text-inverse',\n dark: 'border-neutral-800/30 text-neutral-800 ring-neutral-800/20 checked:border-neutral-800 checked:bg-neutral-800',\n error:\n 'border-error/30 text-error ring-error/20 checked:border-error checked:bg-error',\n success:\n 'border-success/30 text-success ring-success/20 checked:border-success checked:bg-success',\n custom:\n 'border-custom/30 text-custom ring-custom/20 checked:border-custom checked:bg-custom',\n },\n validationStyleEnabled: {\n disabled: '',\n enabled: 'valid:border-success invalid:border-error',\n },\n },\n defaultVariants: {\n variant: 'default',\n color: 'text',\n validationStyleEnabled: 'disabled',\n size: 'md',\n },\n }\n);\n\nexport type CheckboxSize = 'xs' | 'sm' | 'md' | 'lg';\n\nexport type CheckboxColor =\n | 'primary'\n | 'secondary'\n | 'neutral'\n | 'light'\n | 'text'\n | 'text-inverse'\n | 'dark'\n | 'error'\n | 'success'\n | 'custom';\n\nexport type CheckboxProps = Omit<\n DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>,\n 'size'\n> & {\n name: string;\n validationStyleEnabled?: boolean;\n label?: ReactNode;\n} & Omit<\n VariantProps<typeof checkboxVariants>,\n 'validationStyleEnabled' | 'size' | 'color'\n > & {\n size?: CheckboxSize | `${CheckboxSize}`;\n color?: CheckboxColor | `${CheckboxColor}`;\n labelClassName?: string;\n };\n\nconst Input: FC<CheckboxProps> = ({\n validationStyleEnabled = false,\n label,\n size,\n color,\n name,\n variant,\n className,\n labelClassName,\n ...props\n}) => (\n <input\n type=\"checkbox\"\n className={cn(\n checkboxVariants({\n variant,\n size,\n color,\n validationStyleEnabled: validationStyleEnabled ? 'enabled' : 'disabled',\n }),\n className\n )}\n {...props}\n />\n);\n\nexport const Checkbox: FC<CheckboxProps> = (props) => {\n const { label, name, id } = props;\n\n return label ? (\n <label\n htmlFor={id ?? name}\n className={cn(\n 'flex w-full cursor-pointer items-center gap-x-4 font-medium text-sm',\n props.size === 'xs' && 'text-xs',\n props.labelClassName\n )}\n >\n <Input id={id ?? name} {...props} />\n {label}\n </label>\n ) : (\n <Input id={id ?? name} {...props} />\n );\n};\n"],"mappings":";;;;;AASA,MAAa,mBAAmB,IAC9B;CACE;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CAGA;CACA;CACA;CAGA;CAEA;AACF,CAAC,CAAC,KAAK,GAAG,GACV;CACE,UAAU;EACR,SAAS,EACP,SAAS,GACX;EACA,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EACA,OAAO;GACL,SACE;GACF,WACE;GACF,SACE;GACF,OACE;GACF,MAAM;GACN,gBACE;GACF,MAAM;GACN,OACE;GACF,SACE;GACF,QACE;EACJ;EACA,wBAAwB;GACtB,UAAU;GACV,SAAS;EACX;CACF;CACA,iBAAiB;EACf,SAAS;EACT,OAAO;EACP,wBAAwB;EACxB,MAAM;CACR;AACF,CACF;AAgCA,MAAM,SAA4B,EAChC,yBAAyB,OACzB,OACA,MACA,OACA,MACA,SACA,WACA,gBACA,GAAG,YAEH,oBAAC,SAAD;CACE,MAAK;CACL,WAAW,GACT,iBAAiB;EACf;EACA;EACA;EACA,wBAAwB,yBAAyB,YAAY;CAC/D,CAAC,GACD,SACF;CACA,GAAI;AACL;AAGH,MAAa,YAA+B,UAAU;CACpD,MAAM,EAAE,OAAO,MAAM,OAAO;CAE5B,OAAO,QACL,qBAAC,SAAD;EACE,SAAS,MAAM;EACf,WAAW,GACT,uEACA,MAAM,SAAS,QAAQ,WACvB,MAAM,cACR;YANF,CAQE,oBAAC,OAAD;GAAO,IAAI,MAAM;GAAM,GAAI;EAAQ,IAClC,KACI;MAEP,oBAAC,OAAD;EAAO,IAAI,MAAM;EAAM,GAAI;CAAQ;AAEvC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.mjs","names":[],"sources":["../../../../src/components/Input/Input.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport type { DetailedHTMLProps, FC, InputHTMLAttributes } from 'react';\n\n// Optional: your own cn helper to merge class names\nconst cn = (...classes: (string | undefined | false | null)[]) =>\n classes.filter(Boolean).join(' ');\n\nexport const inputVariants = cva(\n [\n // base styles\n 'w-full select-text resize-none text-base shadow-none outline-none',\n 'transition-all duration-300 md:text-sm',\n 'ring-0',\n 'disabled:opacity-50',\n\n // Corner shape\n 'rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl',\n ].join(' '),\n {\n variants: {\n variant: {\n default: [\n 'text-
|
|
1
|
+
{"version":3,"file":"Input.mjs","names":[],"sources":["../../../../src/components/Input/Input.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport type { DetailedHTMLProps, FC, InputHTMLAttributes } from 'react';\n\n// Optional: your own cn helper to merge class names\nconst cn = (...classes: (string | undefined | false | null)[]) =>\n classes.filter(Boolean).join(' ');\n\nexport const inputVariants = cva(\n [\n // base styles\n 'w-full select-text resize-none text-base shadow-none outline-none',\n 'transition-all duration-300 md:text-sm',\n 'ring-0',\n 'disabled:opacity-50',\n\n // Corner shape\n 'rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl',\n ].join(' '),\n {\n variants: {\n variant: {\n default: [\n 'text-foreground',\n 'bg-accent',\n 'ring-text/20',\n\n // Focus ring\n 'disabled:ring-0',\n 'hover:ring-3',\n 'focus-within:ring-4',\n 'focus-visible:outline-none focus-visible:ring-4',\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 ].join(' '),\n invisible: 'border-none text-inherit outline-none ring-0',\n },\n size: {\n sm: 'px-2 py-2 text-sm md:py-1.5 md:text-xs',\n md: 'px-2 py-3 md:py-2',\n lg: 'p-4',\n },\n validationStyleEnabled: {\n disabled: '',\n enabled: 'valid:border-success invalid:border-error',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n validationStyleEnabled: 'disabled',\n },\n }\n);\n\nexport type InputVariant = 'default' | 'invisible';\n\nexport type InputSize = 'md' | 'lg';\n\nexport type InputProps = Omit<\n DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>,\n 'size'\n> & {\n validationStyleEnabled?: boolean;\n} & Omit<VariantProps<typeof inputVariants>, 'validationStyleEnabled'>;\n\nexport const Input: FC<InputProps> = ({\n validationStyleEnabled = false,\n variant,\n size,\n className,\n ...props\n}) => (\n <input\n className={cn(\n inputVariants({\n variant,\n size,\n validationStyleEnabled: validationStyleEnabled ? 'enabled' : 'disabled',\n }),\n className\n )}\n suppressHydrationWarning\n {...props}\n />\n);\n"],"mappings":";;;;AAIA,MAAM,MAAM,GAAG,YACb,QAAQ,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;AAElC,MAAa,gBAAgB,IAC3B;CAEE;CACA;CACA;CACA;CAGA;AACF,CAAC,CAAC,KAAK,GAAG,GACV;CACE,UAAU;EACR,SAAS;GACP,SAAS;IACP;IACA;IACA;IAGA;IACA;IACA;IACA;IAGA;IAGA;GACF,CAAC,CAAC,KAAK,GAAG;GACV,WAAW;EACb;EACA,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EACA,wBAAwB;GACtB,UAAU;GACV,SAAS;EACX;CACF;CACA,iBAAiB;EACf,SAAS;EACT,MAAM;EACN,wBAAwB;CAC1B;AACF,CACF;AAaA,MAAa,SAAyB,EACpC,yBAAyB,OACzB,SACA,MACA,WACA,GAAG,YAEH,oBAAC,SAAD;CACE,WAAW,GACT,cAAc;EACZ;EACA;EACA,wBAAwB,yBAAyB,YAAY;CAC/D,CAAC,GACD,SACF;CACA;CACA,GAAI;AACL"}
|
|
@@ -480,7 +480,7 @@ const InputOTPSlot = ({ index, className, onClick, onKeyDown, ...props }) => {
|
|
|
480
480
|
};
|
|
481
481
|
const InputOTPSeparator = (props) => /* @__PURE__ */ jsx("div", {
|
|
482
482
|
"aria-hidden": true,
|
|
483
|
-
className: "z-0 table h-0.5 w-3 rounded-full text-
|
|
483
|
+
className: "z-0 table h-0.5 w-3 rounded-full text-foreground/50",
|
|
484
484
|
...props,
|
|
485
485
|
children: /* @__PURE__ */ jsx(MinusIcon, {})
|
|
486
486
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OTPInput.mjs","names":[],"sources":["../../../../src/components/Input/OTPInput.tsx"],"sourcesContent":["'use client';\n\n/**\n * This component is a fork of https://github.com/guilhermerodz/input-otp\n */\n\nimport { cn } from '@utils/cn';\nimport { cva } from 'class-variance-authority';\nimport { MinusIcon } from 'lucide-react';\nimport {\n type ChangeEvent,\n type ClipboardEvent,\n type ComponentProps,\n type CSSProperties,\n createContext,\n type FC,\n type InputHTMLAttributes,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n type RefObject,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { Button, type ButtonProps } from '../Button';\n\n// ---------------- Utilities ----------------\n\nconst syncTimeouts = (cb: (...args: any[]) => unknown): number[] => {\n const t1 = setTimeout(cb, 0); // For faster machines\n const t2 = setTimeout(cb, 1_0);\n const t3 = setTimeout(cb, 5_0);\n return [t1, t2, t3];\n};\n\nconst safeInsertRule = (sheet: CSSStyleSheet, rule: string) => {\n try {\n sheet.insertRule(rule);\n } catch {\n console.error('input-otp could not insert CSS rule:', rule);\n }\n};\n\n// Decided to go with <noscript>\n// instead of `scripting` CSS media query\n// because it's a fallback for initial page load\n// and the <script> tag won't be loaded\n// unless the user has JS disabled.\nconst NOSCRIPT_CSS_FALLBACK = `\n[data-input-otp] {\n --nojs-bg: white !important;\n --nojs-fg: black !important;\n\n background-color: var(--nojs-bg) !important;\n color: var(--nojs-fg) !important;\n caret-color: var(--nojs-fg) !important;\n letter-spacing: .25em !important;\n text-align: center !important;\n border: 1px solid var(--nojs-fg) !important;\n border-radius: 4px !important;\n width: 100% !important;\n}\n@media (prefers-color-scheme: dark) {\n [data-input-otp] {\n --nojs-bg: black !important;\n --nojs-fg: white !important;\n }\n}`;\n\n// ---------------- Constants ----------------\n\nconst PWM_BADGE_MARGIN_RIGHT = 18;\nconst PWM_BADGE_SPACE_WIDTH_PX = 40;\nconst PWM_BADGE_SPACE_WIDTH = `${PWM_BADGE_SPACE_WIDTH_PX}px` as const;\n\nconst PASSWORD_MANAGERS_SELECTORS = [\n '[data-lastpass-icon-root]', // LastPass\n 'com-1password-button', // 1Password\n '[data-dashlanecreated]', // Dashlane\n '[style$=\"2147483647 !important;\"]', // Bitwarden\n].join(',');\n\n// ---------------- Types ----------------\n\nexport type SlotProps = {\n isActive: boolean;\n char: string | null;\n placeholderChar: string | null;\n hasFakeCaret: boolean;\n};\n\nexport type RenderProps = {\n slots: SlotProps[];\n isFocused: boolean;\n isHovering: boolean;\n setSelection: (index: number) => void;\n};\n\ntype OverrideProps<T, R> = Omit<T, keyof R> & R;\n\ntype OTPInputBaseProps = OverrideProps<\n InputHTMLAttributes<HTMLInputElement>,\n {\n value?: string;\n onChange?: (newValue: string) => unknown;\n\n maxLength: number;\n\n onComplete?: (...args: any[]) => unknown;\n onActiveSlotChange?: (activeSlotIndex: number | null) => unknown;\n pushPasswordManagerStrategy?: 'increase-width' | 'none';\n pasteTransformer?: (pasted: string) => string;\n\n containerClassName?: string;\n\n noScriptCSSFallback?: string | null;\n }\n>;\n\ntype InputOTPRenderFn = (props: RenderProps) => ReactNode;\n\nexport type OTPInputProps = OTPInputBaseProps &\n (\n | {\n render: InputOTPRenderFn;\n children?: never;\n }\n | {\n render?: never;\n children: ReactNode;\n }\n );\n\n// ---------------- Hooks ----------------\n\nexport const usePasswordManagerBadge = ({\n containerRef,\n inputRef,\n pushPasswordManagerStrategy,\n isFocused,\n}: {\n containerRef: RefObject<HTMLDivElement | null>;\n inputRef: RefObject<HTMLInputElement | null>;\n pushPasswordManagerStrategy: OTPInputProps['pushPasswordManagerStrategy'];\n isFocused: boolean;\n}) => {\n /** Password managers have a badge\n * and I'll use this state to push them\n * outside the input */\n const [hasPWMBadge, setHasPWMBadge] = useState(false);\n const [hasPWMBadgeSpace, setHasPWMBadgeSpace] = useState(false);\n const [done, setDone] = useState(false);\n\n const willPushPWMBadge =\n pushPasswordManagerStrategy === 'none'\n ? false\n : (pushPasswordManagerStrategy === 'increase-width' ||\n // TODO: remove 'experimental-no-flickering' support in 2.0.0\n pushPasswordManagerStrategy === 'experimental-no-flickering') &&\n hasPWMBadge &&\n hasPWMBadgeSpace;\n\n const trackPWMBadge = () => {\n const container = containerRef.current;\n const input = inputRef.current;\n if (\n !container ||\n !input ||\n done ||\n pushPasswordManagerStrategy === 'none'\n ) {\n return;\n }\n\n const elementToCompare = container;\n\n // Get the top right-center point of the container.\n // That is usually where most password managers place their badge.\n const rightCornerX =\n elementToCompare.getBoundingClientRect().left +\n elementToCompare.offsetWidth;\n const centereredY =\n elementToCompare.getBoundingClientRect().top +\n elementToCompare.offsetHeight / 2;\n const x = rightCornerX - PWM_BADGE_MARGIN_RIGHT;\n const y = centereredY;\n\n // Do an extra search to check for famous password managers\n const pmws = document.querySelectorAll(PASSWORD_MANAGERS_SELECTORS);\n\n // If no password manager is automatically detect,\n // we'll try to dispatch document.elementFromPoint\n // to identify badges\n if (pmws.length === 0) {\n const maybeBadgeEl = document.elementFromPoint(x, y);\n\n // If the found element is the input itself,\n // then we assume it's not a password manager badge.\n // We are not sure. Most times that means there isn't a badge.\n if (maybeBadgeEl === container) {\n return;\n }\n }\n\n setHasPWMBadge(true);\n setDone(true);\n };\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container || pushPasswordManagerStrategy === 'none') {\n return;\n }\n\n // Check if the PWM area is 100% visible\n const checkHasSpace = () => {\n const viewportWidth = window.innerWidth;\n const distanceToRightEdge =\n viewportWidth - container.getBoundingClientRect().right;\n setHasPWMBadgeSpace(distanceToRightEdge >= PWM_BADGE_SPACE_WIDTH_PX);\n };\n\n checkHasSpace();\n const interval = setInterval(checkHasSpace, 1000);\n\n return () => {\n clearInterval(interval);\n };\n }, [containerRef, pushPasswordManagerStrategy]);\n\n useEffect(() => {\n const _isFocused = isFocused || document.activeElement === inputRef.current;\n\n if (pushPasswordManagerStrategy === 'none' || !_isFocused) {\n return;\n }\n const t1 = setTimeout(trackPWMBadge, 0);\n const t2 = setTimeout(trackPWMBadge, 2000);\n const t3 = setTimeout(trackPWMBadge, 5000);\n const t4 = setTimeout(() => {\n setDone(true);\n }, 6000);\n return () => {\n clearTimeout(t1);\n clearTimeout(t2);\n clearTimeout(t3);\n clearTimeout(t4);\n };\n }, [inputRef, isFocused, pushPasswordManagerStrategy]);\n\n return { hasPWMBadge, willPushPWMBadge, PWM_BADGE_SPACE_WIDTH };\n};\n\nexport const usePrevious = <T,>(value: T): T | undefined => {\n const ref = useRef<T | undefined>(undefined);\n useEffect(() => {\n ref.current = value;\n });\n return ref.current;\n};\n\n// ---------------- Context ----------------\n\nexport const OTPInputContext = createContext<RenderProps>({} as RenderProps);\n\n// ---------------- Core Component ----------------\n\nexport const OTPInput: FC<OTPInputProps> = ({\n value: uncheckedValue,\n onChange: uncheckedOnChange,\n maxLength,\n pattern,\n placeholder,\n inputMode = 'numeric',\n onComplete,\n onActiveSlotChange,\n pushPasswordManagerStrategy = 'increase-width',\n pasteTransformer,\n containerClassName,\n noScriptCSSFallback = NOSCRIPT_CSS_FALLBACK,\n render,\n children,\n ...props\n}) => {\n // Only used when `value` state is not provided\n const [internalValue, setInternalValue] = useState(\n typeof props.defaultValue === 'string' ? props.defaultValue : ''\n );\n\n // Definitions\n const value = uncheckedValue ?? internalValue;\n const previousValue = usePrevious(value);\n const onChange = (newValue: string) => {\n uncheckedOnChange?.(newValue);\n setInternalValue(newValue);\n };\n const regexp =\n pattern !== undefined\n ? typeof pattern === 'string'\n ? new RegExp(pattern)\n : pattern\n : null;\n\n /** useRef */\n const inputRef = useRef<HTMLInputElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const initialLoadRef = useRef({\n value,\n onChange,\n isIOS:\n typeof window !== 'undefined' &&\n window?.CSS?.supports?.('-webkit-touch-callout', 'none'),\n });\n const inputMetadataRef = useRef<{\n prev: [number | null, number | null, 'none' | 'forward' | 'backward'];\n }>({\n prev: [\n inputRef.current?.selectionStart ?? null,\n inputRef.current?.selectionEnd ?? null,\n inputRef.current?.selectionDirection ?? 'none',\n ],\n });\n useEffect(() => {\n const input = inputRef.current;\n const container = containerRef.current;\n\n if (!input || !container) {\n return;\n }\n\n // Sync input value\n if (initialLoadRef.current.value !== input.value) {\n initialLoadRef.current.onChange(input.value);\n }\n\n // Previous selection\n inputMetadataRef.current.prev = [\n input.selectionStart,\n input.selectionEnd,\n input.selectionDirection ?? 'none',\n ];\n const onDocumentSelectionChange = () => {\n if (document.activeElement !== input) {\n setMirrorSelectionStart(null);\n setMirrorSelectionEnd(null);\n setActualCaretPosition(null);\n return;\n }\n\n const selectionStart = input.selectionStart;\n const selectionEnd = input.selectionEnd;\n const selectionDirection = input.selectionDirection;\n const maxLength = input.maxLength;\n const value = input.value;\n const previousSelection = inputMetadataRef.current.prev;\n\n let calculatedStart = -1;\n let calculatedEnd = -1;\n let calculatedDirection: 'forward' | 'backward' | 'none' =\n selectionDirection ?? 'none';\n\n if (\n value.length !== 0 &&\n selectionStart !== null &&\n selectionEnd !== null\n ) {\n const isSingleCaret = selectionStart === selectionEnd;\n const isInsertMode =\n selectionStart === value.length && value.length < maxLength;\n\n if (isSingleCaret && !isInsertMode) {\n const caretPosition = selectionStart;\n if (caretPosition === 0) {\n calculatedStart = 0;\n calculatedEnd = 1;\n calculatedDirection = 'forward';\n } else if (caretPosition === maxLength) {\n calculatedStart = caretPosition - 1;\n calculatedEnd = caretPosition;\n calculatedDirection = 'backward';\n } else if (maxLength > 1 && value.length > 1) {\n let offset = 0;\n if (\n previousSelection[0] !== null &&\n previousSelection[1] !== null\n ) {\n calculatedDirection =\n caretPosition < previousSelection[1] ? 'backward' : 'forward';\n const wasPreviouslyInserting =\n previousSelection[0] === previousSelection[1] &&\n previousSelection[0] < maxLength;\n if (\n calculatedDirection === 'backward' &&\n !wasPreviouslyInserting\n ) {\n offset = -1;\n }\n }\n\n calculatedStart = offset + caretPosition;\n calculatedEnd = offset + caretPosition + 1;\n }\n }\n\n if (\n calculatedStart !== -1 &&\n calculatedEnd !== -1 &&\n calculatedStart !== calculatedEnd\n ) {\n inputRef.current?.setSelectionRange(\n calculatedStart,\n calculatedEnd,\n calculatedDirection\n );\n }\n }\n\n const finalSelectionStart =\n calculatedStart !== -1 ? calculatedStart : selectionStart;\n const finalSelectionEnd =\n calculatedEnd !== -1 ? calculatedEnd : selectionEnd;\n const finalDirection = calculatedDirection;\n\n // Track actual caret position (before expansion) for active slot detection\n if (selectionStart !== null && selectionEnd !== null) {\n const isSingleCaret = selectionStart === selectionEnd;\n if (isSingleCaret) {\n setActualCaretPosition(selectionStart);\n } else {\n // When selection is expanded, use the start position as the caret\n setActualCaretPosition(finalSelectionStart);\n }\n } else {\n setActualCaretPosition(null);\n }\n\n setMirrorSelectionStart(finalSelectionStart);\n setMirrorSelectionEnd(finalSelectionEnd);\n inputMetadataRef.current.prev = [\n finalSelectionStart,\n finalSelectionEnd,\n finalDirection,\n ];\n };\n document.addEventListener('selectionchange', onDocumentSelectionChange, {\n capture: true,\n });\n\n // Set initial mirror state\n onDocumentSelectionChange();\n if (document.activeElement === input) {\n setIsFocused(true);\n }\n\n // Apply needed styles\n if (!document.getElementById('input-otp-style')) {\n const styleEl = document.createElement('style');\n styleEl.id = 'input-otp-style';\n document.head.appendChild(styleEl);\n\n if (styleEl.sheet) {\n const autofillStyles =\n 'background: transparent !important; color: transparent !important; border-color: transparent !important; opacity: 0 !important; box-shadow: none !important; -webkit-box-shadow: none !important; -webkit-text-fill-color: transparent !important;';\n\n safeInsertRule(\n styleEl.sheet,\n '[data-input-otp]::selection { background: transparent !important; color: transparent !important; }'\n );\n safeInsertRule(\n styleEl.sheet,\n `[data-input-otp]:autofill { ${autofillStyles} }`\n );\n safeInsertRule(\n styleEl.sheet,\n `[data-input-otp]:-webkit-autofill { ${autofillStyles} }`\n );\n // iOS\n safeInsertRule(\n styleEl.sheet,\n `@supports (-webkit-touch-callout: none) { [data-input-otp] { letter-spacing: -.6em !important; font-weight: 100 !important; font-stretch: ultra-condensed; font-optical-sizing: none !important; left: -1px !important; right: 1px !important; } }`\n );\n // PWM badges\n safeInsertRule(\n styleEl.sheet,\n `[data-input-otp] + * { pointer-events: all !important; }`\n );\n }\n }\n // Track root height\n const updateRootHeight = () => {\n if (container) {\n container.style.setProperty('--root-height', `${input.clientHeight}px`);\n }\n };\n updateRootHeight();\n const resizeObserver = new ResizeObserver(updateRootHeight);\n resizeObserver.observe(input);\n\n return () => {\n document.removeEventListener(\n 'selectionchange',\n onDocumentSelectionChange,\n { capture: true }\n );\n resizeObserver.disconnect();\n };\n }, []);\n\n /** Mirrors for UI rendering purpose only */\n const [isHoveringInput, setIsHoveringInput] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n const [mirrorSelectionStart, setMirrorSelectionStart] = useState<\n number | null\n >(null);\n const [mirrorSelectionEnd, setMirrorSelectionEnd] = useState<number | null>(\n null\n );\n const [actualCaretPosition, setActualCaretPosition] = useState<number | null>(\n null\n );\n\n /** Effects */\n useEffect(() => {\n syncTimeouts(() => {\n // Forcefully remove :autofill state\n inputRef.current?.dispatchEvent(new Event('input'));\n\n // Update the selection state\n const s = inputRef.current?.selectionStart ?? null;\n const e = inputRef.current?.selectionEnd ?? null;\n const dir = inputRef.current?.selectionDirection ?? 'none';\n if (s !== null && e !== null) {\n setMirrorSelectionStart(s);\n setMirrorSelectionEnd(e);\n // Track actual caret position (use start position as caret)\n setActualCaretPosition(s);\n inputMetadataRef.current.prev = [s, e, dir];\n }\n });\n }, [value, isFocused]);\n\n useEffect(() => {\n if (previousValue === undefined) {\n return;\n }\n\n if (\n value !== previousValue &&\n previousValue.length < maxLength &&\n value.length === maxLength\n ) {\n onComplete?.(value);\n }\n }, [maxLength, onComplete, previousValue, value]);\n\n // Track active slot changes\n const previousActiveSlot = useRef<number | null>(null);\n useEffect(() => {\n const activeSlotIndex =\n isFocused && actualCaretPosition !== null ? actualCaretPosition : null;\n\n if (activeSlotIndex !== previousActiveSlot.current) {\n previousActiveSlot.current = activeSlotIndex;\n onActiveSlotChange?.(activeSlotIndex);\n }\n }, [isFocused, actualCaretPosition, onActiveSlotChange]);\n\n const pwmb = usePasswordManagerBadge({\n containerRef,\n inputRef,\n pushPasswordManagerStrategy,\n isFocused,\n });\n\n /** Event handlers */\n const _changeListener = (e: ChangeEvent<HTMLInputElement>) => {\n const newValue = e.currentTarget.value.slice(0, maxLength);\n if (newValue.length > 0 && regexp && !regexp.test(newValue)) {\n e.preventDefault();\n return;\n }\n const maybeHasDeleted =\n typeof previousValue === 'string' &&\n newValue.length < previousValue.length;\n if (maybeHasDeleted) {\n // Since cutting/deleting text doesn't trigger\n // selectionchange event, we'll have to dispatch it manually.\n // NOTE: The following line also triggers when cmd+A then pasting\n // a value with smaller length, which is not ideal for performance.\n document.dispatchEvent(new Event('selectionchange'));\n }\n onChange(newValue);\n };\n const _focusListener = () => {\n if (inputRef.current) {\n const start = Math.min(inputRef.current.value.length, maxLength - 1);\n const end = inputRef.current.value.length;\n inputRef.current?.setSelectionRange(start, end);\n setMirrorSelectionStart(start);\n setMirrorSelectionEnd(end);\n }\n setIsFocused(true);\n };\n // Fix iOS pasting\n const _pasteListener = (e: ClipboardEvent<HTMLInputElement>) => {\n const input = inputRef.current;\n if (\n !pasteTransformer &&\n (!initialLoadRef.current.isIOS || !e.clipboardData || !input)\n ) {\n return;\n }\n\n const _content = e.clipboardData.getData('text/plain');\n const content = pasteTransformer ? pasteTransformer(_content) : _content;\n e.preventDefault();\n\n const start = inputRef.current?.selectionStart;\n const end = inputRef.current?.selectionEnd;\n\n const isReplacing = start !== end;\n\n const newValueUncapped = isReplacing\n ? value.slice(0, start ?? 0) + content + value.slice(end ?? 0) // Replacing\n : value.slice(0, start ?? 0) + content + value.slice(start ?? 0); // Inserting\n const newValue = newValueUncapped.slice(0, maxLength);\n\n if (newValue.length > 0 && regexp && !regexp.test(newValue)) {\n return;\n }\n\n if (input) {\n input.value = newValue;\n onChange(newValue);\n\n const _start = Math.min(newValue.length, maxLength - 1);\n const _end = newValue.length;\n\n input.setSelectionRange(_start, _end);\n setMirrorSelectionStart(_start);\n setMirrorSelectionEnd(_end);\n }\n };\n\n /** Styles - dynamic styles that can't be converted to Tailwind */\n const dynamicInputStyle: CSSProperties = {\n width: pwmb.willPushPWMBadge\n ? `calc(100% + ${pwmb.PWM_BADGE_SPACE_WIDTH})`\n : '100%',\n clipPath: pwmb.willPushPWMBadge\n ? `inset(0 ${pwmb.PWM_BADGE_SPACE_WIDTH} 0 0)`\n : undefined,\n fontSize: 'var(--root-height)',\n };\n\n /** Rendering */\n const renderedInput = (\n <input\n autoComplete={props.autoComplete || 'one-time-code'}\n {...props}\n data-input-otp\n data-input-otp-placeholder-shown={value.length === 0 || undefined}\n data-input-otp-mss={mirrorSelectionStart}\n data-input-otp-mse={mirrorSelectionEnd}\n inputMode={inputMode}\n pattern={regexp?.source}\n aria-placeholder={placeholder}\n className=\"pointer-events-auto absolute inset-0 -z-10 flex h-full border-0 border-transparent bg-transparent text-center font-mono text-transparent tabular-nums leading-none tracking-[-.5em] caret-transparent opacity-100 shadow-none outline-none\"\n style={dynamicInputStyle}\n maxLength={maxLength}\n value={value}\n ref={inputRef}\n onPaste={(e) => {\n _pasteListener(e);\n props.onPaste?.(e);\n }}\n onChange={_changeListener}\n onMouseOver={(e) => {\n setIsHoveringInput(true);\n props.onMouseOver?.(e);\n }}\n onMouseLeave={(e) => {\n setIsHoveringInput(false);\n props.onMouseLeave?.(e);\n }}\n onKeyDown={(e) => {\n // Track arrow key navigation to ensure active slot updates correctly\n if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n // Use requestAnimationFrame to check selection after browser has processed the key\n requestAnimationFrame(() => {\n const input = inputRef.current;\n if (input && document.activeElement === input) {\n const s = input.selectionStart;\n const end = input.selectionEnd;\n if (s !== null && end !== null) {\n // Update actual caret position - use start position as caret\n setActualCaretPosition(s);\n }\n }\n });\n }\n props.onKeyDown?.(e);\n }}\n onFocus={(e) => {\n _focusListener();\n props.onFocus?.(e);\n }}\n onBlur={(e) => {\n setIsFocused(false);\n props.onBlur?.(e);\n }}\n />\n );\n\n const setSelection = (index: number) => {\n const input = inputRef.current;\n if (!input || props.disabled) {\n return;\n }\n\n // Clamp index to valid range\n const clampedIndex = Math.max(0, Math.min(index, maxLength - 1));\n\n // Focus the input if not already focused\n if (document.activeElement !== input) {\n input.focus();\n }\n\n // Set selection to the clicked slot\n // If there's a character at that position, select it; otherwise just position the caret\n const hasChar = value[clampedIndex] !== undefined;\n const start = clampedIndex;\n const end = hasChar ? clampedIndex + 1 : clampedIndex;\n\n input.setSelectionRange(start, end);\n setMirrorSelectionStart(start);\n setMirrorSelectionEnd(end);\n setIsFocused(true);\n };\n\n const contextValue: RenderProps = {\n slots: Array.from({ length: maxLength }).map((_, slotIdx) => {\n const isActive =\n isFocused &&\n mirrorSelectionStart !== null &&\n mirrorSelectionEnd !== null &&\n ((mirrorSelectionStart === mirrorSelectionEnd &&\n slotIdx === mirrorSelectionStart) ||\n (slotIdx >= mirrorSelectionStart && slotIdx < mirrorSelectionEnd));\n\n const char = value[slotIdx] !== undefined ? value[slotIdx] : null;\n const placeholderChar =\n value[0] !== undefined ? null : (placeholder?.[slotIdx] ?? null);\n\n return {\n char,\n placeholderChar,\n isActive,\n hasFakeCaret: isActive && char === null,\n };\n }),\n isFocused,\n isHovering: !props.disabled && isHoveringInput,\n setSelection,\n };\n\n const renderedChildren =\n render !== undefined ? (\n render(contextValue)\n ) : (\n <OTPInputContext.Provider value={contextValue}>\n {children}\n </OTPInputContext.Provider>\n );\n\n return (\n <>\n {noScriptCSSFallback !== null && (\n <noscript>\n <style>{noScriptCSSFallback}</style>\n </noscript>\n )}\n\n <div\n ref={containerRef}\n className={cn(\n 'relative',\n props.disabled ? 'cursor-default' : 'cursor-text',\n containerClassName\n )}\n >\n {renderedChildren}\n\n <div className=\"absolute inset-0\">{renderedInput}</div>\n </div>\n </>\n );\n};\n\n// ---------------- Root ----------------\n\ntype InputOTPProps = Omit<ComponentProps<typeof OTPInput>, 'children'>;\n\nexport const inputSlotVariants = cva('block text-center', {\n variants: {\n size: {\n sm: 'h-4 w-3 text-sm',\n md: 'h-5 w-4 text-base',\n lg: 'h-6 w-5 text-lg',\n xl: 'h-7 w-6 text-xl',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\nexport const InputOTP: FC<InputOTPProps> = ({\n className,\n render,\n ...props\n}) => (\n <OTPInput\n containerClassName=\"relative flex items-center gap-2 has-disabled:opacity-50\"\n className={cn('disabled:cursor-not-allowed', className)}\n render={render!}\n {...props}\n />\n);\n\n// ---------------- Group ----------------\n\nexport const InputOTPGroup = ({\n className,\n ...props\n}: ComponentProps<'div'>) => (\n <div className={cn('z-10 flex items-center gap-3', className)} {...props} />\n);\n\n// ---------------- Slot ----------------\n\ntype InputOTPSlotProps = Omit<ButtonProps, 'variant' | 'label'> & {\n index: number;\n};\n\nexport const InputOTPSlot: FC<InputOTPSlotProps> = ({\n index,\n className,\n onClick,\n onKeyDown,\n ...props\n}) => {\n const inputOTPContext = useContext(OTPInputContext);\n const { char, isActive } = inputOTPContext?.slots[index] ?? {};\n const { setSelection } = inputOTPContext ?? {};\n\n const handleClick = (e: MouseEvent<HTMLButtonElement>) => {\n setSelection?.(index);\n onClick?.(e);\n };\n\n const handleKeyDown = (e: KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n setSelection?.(index);\n }\n onKeyDown?.(e);\n };\n\n return (\n <Button\n isSelected={isActive}\n variant=\"input\"\n color=\"custom\"\n tabIndex={-1}\n className={cn('relative z-10 px-2!', isActive && 'ring-4!', className)}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n label={null}\n {...props}\n >\n {/* value */}\n <span className=\"relative z-10 flex h-6 w-4 items-center justify-center\">\n {char}\n </span>\n </Button>\n );\n};\n\n// ---------------- Separator ----------------\n\nexport const InputOTPSeparator: FC<ComponentProps<'div'>> = (props) => (\n <div\n aria-hidden\n className=\"z-0 table h-0.5 w-3 rounded-full text-text/50\"\n {...props}\n >\n <MinusIcon />\n </div>\n);\n\nexport const InputIndicator: FC<ComponentProps<'div'>> = (props) => (\n <div\n data-indicator\n className=\"absolute top-0 z-0 h-full w-auto rounded-xl bg-text/20 ring-4 ring-text/20 transition-[left,width] duration-300 ease-in-out [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl motion-reduce:transition-none\"\n {...props}\n />\n);\n"],"mappings":";;;;;;;;;;;;;AA8BA,MAAM,gBAAgB,OAA8C;CAIlE,OAAO;EAHI,WAAW,IAAI,CAGjB;EAFE,WAAW,IAAI,EAEb;EADF,WAAW,IAAI,EACT;CAAC;AACpB;AAEA,MAAM,kBAAkB,OAAsB,SAAiB;CAC7D,IAAI;EACF,MAAM,WAAW,IAAI;CACvB,QAAQ;EACN,QAAQ,MAAM,wCAAwC,IAAI;CAC5D;AACF;AAOA,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;AAuB9B,MAAM,yBAAyB;AAC/B,MAAM,2BAA2B;AACjC,MAAM,wBAAwB,GAAG,yBAAyB;AAE1D,MAAM,8BAA8B;CAClC;CACA;CACA;CACA;AACF,CAAC,CAAC,KAAK,GAAG;AAuDV,MAAa,2BAA2B,EACtC,cACA,UACA,6BACA,gBAMI;;;;CAIJ,MAAM,CAAC,aAAa,kBAAkB,SAAS,KAAK;CACpD,MAAM,CAAC,kBAAkB,uBAAuB,SAAS,KAAK;CAC9D,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CAEtC,MAAM,mBACJ,gCAAgC,SAC5B,SACC,gCAAgC,oBAE/B,gCAAgC,iCAClC,eACA;CAEN,MAAM,sBAAsB;EAC1B,MAAM,YAAY,aAAa;EAC/B,MAAM,QAAQ,SAAS;EACvB,IACE,CAAC,aACD,CAAC,SACD,QACA,gCAAgC,QAEhC;EAGF,MAAM,mBAAmB;EAIzB,MAAM,eACJ,iBAAiB,sBAAsB,CAAC,CAAC,OACzC,iBAAiB;EACnB,MAAM,cACJ,iBAAiB,sBAAsB,CAAC,CAAC,MACzC,iBAAiB,eAAe;EAClC,MAAM,IAAI,eAAe;EACzB,MAAM,IAAI;EAQV,IALa,SAAS,iBAAiB,2BAKhC,CAAC,CAAC,WAAW,GAMlB;OALqB,SAAS,iBAAiB,GAAG,CAKnC,MAAM,WACnB;EACF;EAGF,eAAe,IAAI;EACnB,QAAQ,IAAI;CACd;CAEA,gBAAgB;EACd,MAAM,YAAY,aAAa;EAC/B,IAAI,CAAC,aAAa,gCAAgC,QAChD;EAIF,MAAM,sBAAsB;GAE1B,MAAM,sBADgB,OAAO,aAEX,UAAU,sBAAsB,CAAC,CAAC;GACpD,oBAAoB,uBAAuB,wBAAwB;EACrE;EAEA,cAAc;EACd,MAAM,WAAW,YAAY,eAAe,GAAI;EAEhD,aAAa;GACX,cAAc,QAAQ;EACxB;CACF,GAAG,CAAC,cAAc,2BAA2B,CAAC;CAE9C,gBAAgB;EACd,MAAM,aAAa,aAAa,SAAS,kBAAkB,SAAS;EAEpE,IAAI,gCAAgC,UAAU,CAAC,YAC7C;EAEF,MAAM,KAAK,WAAW,eAAe,CAAC;EACtC,MAAM,KAAK,WAAW,eAAe,GAAI;EACzC,MAAM,KAAK,WAAW,eAAe,GAAI;EACzC,MAAM,KAAK,iBAAiB;GAC1B,QAAQ,IAAI;EACd,GAAG,GAAI;EACP,aAAa;GACX,aAAa,EAAE;GACf,aAAa,EAAE;GACf,aAAa,EAAE;GACf,aAAa,EAAE;EACjB;CACF,GAAG;EAAC;EAAU;EAAW;CAA2B,CAAC;CAErD,OAAO;EAAE;EAAa;EAAkB;CAAsB;AAChE;AAEA,MAAa,eAAmB,UAA4B;CAC1D,MAAM,MAAM,OAAsB,MAAS;CAC3C,gBAAgB;EACd,IAAI,UAAU;CAChB,CAAC;CACD,OAAO,IAAI;AACb;AAIA,MAAa,kBAAkB,cAA2B,CAAC,CAAgB;AAI3E,MAAa,YAA+B,EAC1C,OAAO,gBACP,UAAU,mBACV,WACA,SACA,aACA,YAAY,WACZ,YACA,oBACA,8BAA8B,kBAC9B,kBACA,oBACA,sBAAsB,uBACtB,QACA,UACA,GAAG,YACC;CAEJ,MAAM,CAAC,eAAe,oBAAoB,SACxC,OAAO,MAAM,iBAAiB,WAAW,MAAM,eAAe,EAChE;CAGA,MAAM,QAAQ,kBAAkB;CAChC,MAAM,gBAAgB,YAAY,KAAK;CACvC,MAAM,YAAY,aAAqB;EACrC,oBAAoB,QAAQ;EAC5B,iBAAiB,QAAQ;CAC3B;CACA,MAAM,SACJ,YAAY,SACR,OAAO,YAAY,WACjB,IAAI,OAAO,OAAO,IAClB,UACF;;CAGN,MAAM,WAAW,OAAyB,IAAI;CAC9C,MAAM,eAAe,OAAuB,IAAI;CAChD,MAAM,iBAAiB,OAAO;EAC5B;EACA;EACA,OACE,OAAO,WAAW,eAClB,QAAQ,KAAK,WAAW,yBAAyB,MAAM;CAC3D,CAAC;CACD,MAAM,mBAAmB,OAEtB,EACD,MAAM;EACJ,SAAS,SAAS,kBAAkB;EACpC,SAAS,SAAS,gBAAgB;EAClC,SAAS,SAAS,sBAAsB;CAC1C,EACF,CAAC;CACD,gBAAgB;EACd,MAAM,QAAQ,SAAS;EACvB,MAAM,YAAY,aAAa;EAE/B,IAAI,CAAC,SAAS,CAAC,WACb;EAIF,IAAI,eAAe,QAAQ,UAAU,MAAM,OACzC,eAAe,QAAQ,SAAS,MAAM,KAAK;EAI7C,iBAAiB,QAAQ,OAAO;GAC9B,MAAM;GACN,MAAM;GACN,MAAM,sBAAsB;EAC9B;EACA,MAAM,kCAAkC;GACtC,IAAI,SAAS,kBAAkB,OAAO;IACpC,wBAAwB,IAAI;IAC5B,sBAAsB,IAAI;IAC1B,uBAAuB,IAAI;IAC3B;GACF;GAEA,MAAM,iBAAiB,MAAM;GAC7B,MAAM,eAAe,MAAM;GAC3B,MAAM,qBAAqB,MAAM;GACjC,MAAM,YAAY,MAAM;GACxB,MAAM,QAAQ,MAAM;GACpB,MAAM,oBAAoB,iBAAiB,QAAQ;GAEnD,IAAI,kBAAkB;GACtB,IAAI,gBAAgB;GACpB,IAAI,sBACF,sBAAsB;GAExB,IACE,MAAM,WAAW,KACjB,mBAAmB,QACnB,iBAAiB,MACjB;IACA,MAAM,gBAAgB,mBAAmB;IACzC,MAAM,eACJ,mBAAmB,MAAM,UAAU,MAAM,SAAS;IAEpD,IAAI,iBAAiB,CAAC,cAAc;KAClC,MAAM,gBAAgB;KACtB,IAAI,kBAAkB,GAAG;MACvB,kBAAkB;MAClB,gBAAgB;MAChB,sBAAsB;KACxB,OAAO,IAAI,kBAAkB,WAAW;MACtC,kBAAkB,gBAAgB;MAClC,gBAAgB;MAChB,sBAAsB;KACxB,OAAO,IAAI,YAAY,KAAK,MAAM,SAAS,GAAG;MAC5C,IAAI,SAAS;MACb,IACE,kBAAkB,OAAO,QACzB,kBAAkB,OAAO,MACzB;OACA,sBACE,gBAAgB,kBAAkB,KAAK,aAAa;OACtD,MAAM,yBACJ,kBAAkB,OAAO,kBAAkB,MAC3C,kBAAkB,KAAK;OACzB,IACE,wBAAwB,cACxB,CAAC,wBAED,SAAS;MAEb;MAEA,kBAAkB,SAAS;MAC3B,gBAAgB,SAAS,gBAAgB;KAC3C;IACF;IAEA,IACE,oBAAoB,MACpB,kBAAkB,MAClB,oBAAoB,eAEpB,SAAS,SAAS,kBAChB,iBACA,eACA,mBACF;GAEJ;GAEA,MAAM,sBACJ,oBAAoB,KAAK,kBAAkB;GAC7C,MAAM,oBACJ,kBAAkB,KAAK,gBAAgB;GACzC,MAAM,iBAAiB;GAGvB,IAAI,mBAAmB,QAAQ,iBAAiB,MAAM;IAEpD,IADsB,mBAAmB,cAEvC,uBAAuB,cAAc;SAGrC,uBAAuB,mBAAmB;GAE9C,OACE,uBAAuB,IAAI;GAG7B,wBAAwB,mBAAmB;GAC3C,sBAAsB,iBAAiB;GACvC,iBAAiB,QAAQ,OAAO;IAC9B;IACA;IACA;GACF;EACF;EACA,SAAS,iBAAiB,mBAAmB,2BAA2B,EACtE,SAAS,KACX,CAAC;EAGD,0BAA0B;EAC1B,IAAI,SAAS,kBAAkB,OAC7B,aAAa,IAAI;EAInB,IAAI,CAAC,SAAS,eAAe,iBAAiB,GAAG;GAC/C,MAAM,UAAU,SAAS,cAAc,OAAO;GAC9C,QAAQ,KAAK;GACb,SAAS,KAAK,YAAY,OAAO;GAEjC,IAAI,QAAQ,OAAO;IACjB,MAAM,iBACJ;IAEF,eACE,QAAQ,OACR,oGACF;IACA,eACE,QAAQ,OACR,+BAA+B,eAAe,GAChD;IACA,eACE,QAAQ,OACR,uCAAuC,eAAe,GACxD;IAEA,eACE,QAAQ,OACR,oPACF;IAEA,eACE,QAAQ,OACR,0DACF;GACF;EACF;EAEA,MAAM,yBAAyB;GAC7B,IAAI,WACF,UAAU,MAAM,YAAY,iBAAiB,GAAG,MAAM,aAAa,GAAG;EAE1E;EACA,iBAAiB;EACjB,MAAM,iBAAiB,IAAI,eAAe,gBAAgB;EAC1D,eAAe,QAAQ,KAAK;EAE5B,aAAa;GACX,SAAS,oBACP,mBACA,2BACA,EAAE,SAAS,KAAK,CAClB;GACA,eAAe,WAAW;EAC5B;CACF,GAAG,CAAC,CAAC;;CAGL,MAAM,CAAC,iBAAiB,sBAAsB,SAAS,KAAK;CAC5D,MAAM,CAAC,WAAW,gBAAgB,SAAS,KAAK;CAChD,MAAM,CAAC,sBAAsB,2BAA2B,SAEtD,IAAI;CACN,MAAM,CAAC,oBAAoB,yBAAyB,SAClD,IACF;CACA,MAAM,CAAC,qBAAqB,0BAA0B,SACpD,IACF;;CAGA,gBAAgB;EACd,mBAAmB;GAEjB,SAAS,SAAS,cAAc,IAAI,MAAM,OAAO,CAAC;GAGlD,MAAM,IAAI,SAAS,SAAS,kBAAkB;GAC9C,MAAM,IAAI,SAAS,SAAS,gBAAgB;GAC5C,MAAM,MAAM,SAAS,SAAS,sBAAsB;GACpD,IAAI,MAAM,QAAQ,MAAM,MAAM;IAC5B,wBAAwB,CAAC;IACzB,sBAAsB,CAAC;IAEvB,uBAAuB,CAAC;IACxB,iBAAiB,QAAQ,OAAO;KAAC;KAAG;KAAG;IAAG;GAC5C;EACF,CAAC;CACH,GAAG,CAAC,OAAO,SAAS,CAAC;CAErB,gBAAgB;EACd,IAAI,kBAAkB,QACpB;EAGF,IACE,UAAU,iBACV,cAAc,SAAS,aACvB,MAAM,WAAW,WAEjB,aAAa,KAAK;CAEtB,GAAG;EAAC;EAAW;EAAY;EAAe;CAAK,CAAC;CAGhD,MAAM,qBAAqB,OAAsB,IAAI;CACrD,gBAAgB;EACd,MAAM,kBACJ,aAAa,wBAAwB,OAAO,sBAAsB;EAEpE,IAAI,oBAAoB,mBAAmB,SAAS;GAClD,mBAAmB,UAAU;GAC7B,qBAAqB,eAAe;EACtC;CACF,GAAG;EAAC;EAAW;EAAqB;CAAkB,CAAC;CAEvD,MAAM,OAAO,wBAAwB;EACnC;EACA;EACA;EACA;CACF,CAAC;;CAGD,MAAM,mBAAmB,MAAqC;EAC5D,MAAM,WAAW,EAAE,cAAc,MAAM,MAAM,GAAG,SAAS;EACzD,IAAI,SAAS,SAAS,KAAK,UAAU,CAAC,OAAO,KAAK,QAAQ,GAAG;GAC3D,EAAE,eAAe;GACjB;EACF;EAIA,IAFE,OAAO,kBAAkB,YACzB,SAAS,SAAS,cAAc,QAMhC,SAAS,cAAc,IAAI,MAAM,iBAAiB,CAAC;EAErD,SAAS,QAAQ;CACnB;CACA,MAAM,uBAAuB;EAC3B,IAAI,SAAS,SAAS;GACpB,MAAM,QAAQ,KAAK,IAAI,SAAS,QAAQ,MAAM,QAAQ,YAAY,CAAC;GACnE,MAAM,MAAM,SAAS,QAAQ,MAAM;GACnC,SAAS,SAAS,kBAAkB,OAAO,GAAG;GAC9C,wBAAwB,KAAK;GAC7B,sBAAsB,GAAG;EAC3B;EACA,aAAa,IAAI;CACnB;CAEA,MAAM,kBAAkB,MAAwC;EAC9D,MAAM,QAAQ,SAAS;EACvB,IACE,CAAC,qBACA,CAAC,eAAe,QAAQ,SAAS,CAAC,EAAE,iBAAiB,CAAC,QAEvD;EAGF,MAAM,WAAW,EAAE,cAAc,QAAQ,YAAY;EACrD,MAAM,UAAU,mBAAmB,iBAAiB,QAAQ,IAAI;EAChE,EAAE,eAAe;EAEjB,MAAM,QAAQ,SAAS,SAAS;EAChC,MAAM,MAAM,SAAS,SAAS;EAO9B,MAAM,YALc,UAAU,MAG1B,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,UAAU,MAAM,MAAM,OAAO,CAAC,IAC3D,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,UAAU,MAAM,MAAM,SAAS,CAAC,EAChC,CAAC,MAAM,GAAG,SAAS;EAEpD,IAAI,SAAS,SAAS,KAAK,UAAU,CAAC,OAAO,KAAK,QAAQ,GACxD;EAGF,IAAI,OAAO;GACT,MAAM,QAAQ;GACd,SAAS,QAAQ;GAEjB,MAAM,SAAS,KAAK,IAAI,SAAS,QAAQ,YAAY,CAAC;GACtD,MAAM,OAAO,SAAS;GAEtB,MAAM,kBAAkB,QAAQ,IAAI;GACpC,wBAAwB,MAAM;GAC9B,sBAAsB,IAAI;EAC5B;CACF;;CAGA,MAAM,oBAAmC;EACvC,OAAO,KAAK,mBACR,eAAe,KAAK,sBAAsB,KAC1C;EACJ,UAAU,KAAK,mBACX,WAAW,KAAK,sBAAsB,SACtC;EACJ,UAAU;CACZ;;CAGA,MAAM,gBACJ,oBAAC,SAAD;EACE,cAAc,MAAM,gBAAgB;EACpC,GAAI;EACJ;EACA,oCAAkC,MAAM,WAAW,KAAK;EACxD,sBAAoB;EACpB,sBAAoB;EACT;EACX,SAAS,QAAQ;EACjB,oBAAkB;EAClB,WAAU;EACV,OAAO;EACI;EACJ;EACP,KAAK;EACL,UAAU,MAAM;GACd,eAAe,CAAC;GAChB,MAAM,UAAU,CAAC;EACnB;EACA,UAAU;EACV,cAAc,MAAM;GAClB,mBAAmB,IAAI;GACvB,MAAM,cAAc,CAAC;EACvB;EACA,eAAe,MAAM;GACnB,mBAAmB,KAAK;GACxB,MAAM,eAAe,CAAC;EACxB;EACA,YAAY,MAAM;GAEhB,IAAI,EAAE,QAAQ,eAAe,EAAE,QAAQ,cAErC,4BAA4B;IAC1B,MAAM,QAAQ,SAAS;IACvB,IAAI,SAAS,SAAS,kBAAkB,OAAO;KAC7C,MAAM,IAAI,MAAM;KAChB,MAAM,MAAM,MAAM;KAClB,IAAI,MAAM,QAAQ,QAAQ,MAExB,uBAAuB,CAAC;IAE5B;GACF,CAAC;GAEH,MAAM,YAAY,CAAC;EACrB;EACA,UAAU,MAAM;GACd,eAAe;GACf,MAAM,UAAU,CAAC;EACnB;EACA,SAAS,MAAM;GACb,aAAa,KAAK;GAClB,MAAM,SAAS,CAAC;EAClB;CACD;CAGH,MAAM,gBAAgB,UAAkB;EACtC,MAAM,QAAQ,SAAS;EACvB,IAAI,CAAC,SAAS,MAAM,UAClB;EAIF,MAAM,eAAe,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,YAAY,CAAC,CAAC;EAG/D,IAAI,SAAS,kBAAkB,OAC7B,MAAM,MAAM;EAKd,MAAM,UAAU,MAAM,kBAAkB;EACxC,MAAM,QAAQ;EACd,MAAM,MAAM,UAAU,eAAe,IAAI;EAEzC,MAAM,kBAAkB,OAAO,GAAG;EAClC,wBAAwB,KAAK;EAC7B,sBAAsB,GAAG;EACzB,aAAa,IAAI;CACnB;CAEA,MAAM,eAA4B;EAChC,OAAO,MAAM,KAAK,EAAE,QAAQ,UAAU,CAAC,CAAC,CAAC,KAAK,GAAG,YAAY;GAC3D,MAAM,WACJ,aACA,yBAAyB,QACzB,uBAAuB,SACrB,yBAAyB,sBACzB,YAAY,wBACX,WAAW,wBAAwB,UAAU;GAElD,MAAM,OAAO,MAAM,aAAa,SAAY,MAAM,WAAW;GAI7D,OAAO;IACL;IACA,iBAJA,MAAM,OAAO,SAAY,OAAQ,cAAc,YAAY;IAK3D;IACA,cAAc,YAAY,SAAS;GACrC;EACF,CAAC;EACD;EACA,YAAY,CAAC,MAAM,YAAY;EAC/B;CACF;CAEA,MAAM,mBACJ,WAAW,SACT,OAAO,YAAY,IAEnB,oBAAC,gBAAgB,UAAjB;EAA0B,OAAO;EAC9B;CACuB;CAG9B,OACE,8CACG,wBAAwB,QACvB,oBAAC,YAAD,YACE,oBAAC,SAAD,YAAQ,oBAA2B,GAC3B,IAGZ,qBAAC,OAAD;EACE,KAAK;EACL,WAAW,GACT,YACA,MAAM,WAAW,mBAAmB,eACpC,kBACF;YANF,CAQG,kBAED,oBAAC,OAAD;GAAK,WAAU;aAAoB;EAAmB,EACnD;GACL;AAEN;AAMA,MAAa,oBAAoB,IAAI,qBAAqB;CACxD,UAAU,EACR,MAAM;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;CACN,EACF;CACA,iBAAiB,EACf,MAAM,KACR;AACF,CAAC;AAED,MAAa,YAA+B,EAC1C,WACA,QACA,GAAG,YAEH,oBAAC,UAAD;CACE,oBAAmB;CACnB,WAAW,GAAG,+BAA+B,SAAS;CAC9C;CACR,GAAI;AACL;AAKH,MAAa,iBAAiB,EAC5B,WACA,GAAG,YAEH,oBAAC,OAAD;CAAK,WAAW,GAAG,gCAAgC,SAAS;CAAG,GAAI;AAAQ;AAS7E,MAAa,gBAAuC,EAClD,OACA,WACA,SACA,WACA,GAAG,YACC;CACJ,MAAM,kBAAkB,WAAW,eAAe;CAClD,MAAM,EAAE,MAAM,aAAa,iBAAiB,MAAM,UAAU,CAAC;CAC7D,MAAM,EAAE,iBAAiB,mBAAmB,CAAC;CAE7C,MAAM,eAAe,MAAqC;EACxD,eAAe,KAAK;EACpB,UAAU,CAAC;CACb;CAEA,MAAM,iBAAiB,MAAwC;EAC7D,IAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;GACtC,EAAE,eAAe;GACjB,eAAe,KAAK;EACtB;EACA,YAAY,CAAC;CACf;CAEA,OACE,oBAAC,QAAD;EACE,YAAY;EACZ,SAAQ;EACR,OAAM;EACN,UAAU;EACV,WAAW,GAAG,uBAAuB,YAAY,WAAW,SAAS;EACrE,SAAS;EACT,WAAW;EACX,OAAO;EACP,GAAI;YAGJ,oBAAC,QAAD;GAAM,WAAU;aACb;EACG;CACA;AAEZ;AAIA,MAAa,qBAAgD,UAC3D,oBAAC,OAAD;CACE;CACA,WAAU;CACV,GAAI;WAEJ,oBAAC,WAAD,CAAY;AACT;AAGP,MAAa,kBAA6C,UACxD,oBAAC,OAAD;CACE;CACA,WAAU;CACV,GAAI;AACL"}
|
|
1
|
+
{"version":3,"file":"OTPInput.mjs","names":[],"sources":["../../../../src/components/Input/OTPInput.tsx"],"sourcesContent":["'use client';\n\n/**\n * This component is a fork of https://github.com/guilhermerodz/input-otp\n */\n\nimport { cn } from '@utils/cn';\nimport { cva } from 'class-variance-authority';\nimport { MinusIcon } from 'lucide-react';\nimport {\n type ChangeEvent,\n type ClipboardEvent,\n type ComponentProps,\n type CSSProperties,\n createContext,\n type FC,\n type InputHTMLAttributes,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n type RefObject,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { Button, type ButtonProps } from '../Button';\n\n// ---------------- Utilities ----------------\n\nconst syncTimeouts = (cb: (...args: any[]) => unknown): number[] => {\n const t1 = setTimeout(cb, 0); // For faster machines\n const t2 = setTimeout(cb, 1_0);\n const t3 = setTimeout(cb, 5_0);\n return [t1, t2, t3];\n};\n\nconst safeInsertRule = (sheet: CSSStyleSheet, rule: string) => {\n try {\n sheet.insertRule(rule);\n } catch {\n console.error('input-otp could not insert CSS rule:', rule);\n }\n};\n\n// Decided to go with <noscript>\n// instead of `scripting` CSS media query\n// because it's a fallback for initial page load\n// and the <script> tag won't be loaded\n// unless the user has JS disabled.\nconst NOSCRIPT_CSS_FALLBACK = `\n[data-input-otp] {\n --nojs-bg: white !important;\n --nojs-fg: black !important;\n\n background-color: var(--nojs-bg) !important;\n color: var(--nojs-fg) !important;\n caret-color: var(--nojs-fg) !important;\n letter-spacing: .25em !important;\n text-align: center !important;\n border: 1px solid var(--nojs-fg) !important;\n border-radius: 4px !important;\n width: 100% !important;\n}\n@media (prefers-color-scheme: dark) {\n [data-input-otp] {\n --nojs-bg: black !important;\n --nojs-fg: white !important;\n }\n}`;\n\n// ---------------- Constants ----------------\n\nconst PWM_BADGE_MARGIN_RIGHT = 18;\nconst PWM_BADGE_SPACE_WIDTH_PX = 40;\nconst PWM_BADGE_SPACE_WIDTH = `${PWM_BADGE_SPACE_WIDTH_PX}px` as const;\n\nconst PASSWORD_MANAGERS_SELECTORS = [\n '[data-lastpass-icon-root]', // LastPass\n 'com-1password-button', // 1Password\n '[data-dashlanecreated]', // Dashlane\n '[style$=\"2147483647 !important;\"]', // Bitwarden\n].join(',');\n\n// ---------------- Types ----------------\n\nexport type SlotProps = {\n isActive: boolean;\n char: string | null;\n placeholderChar: string | null;\n hasFakeCaret: boolean;\n};\n\nexport type RenderProps = {\n slots: SlotProps[];\n isFocused: boolean;\n isHovering: boolean;\n setSelection: (index: number) => void;\n};\n\ntype OverrideProps<T, R> = Omit<T, keyof R> & R;\n\ntype OTPInputBaseProps = OverrideProps<\n InputHTMLAttributes<HTMLInputElement>,\n {\n value?: string;\n onChange?: (newValue: string) => unknown;\n\n maxLength: number;\n\n onComplete?: (...args: any[]) => unknown;\n onActiveSlotChange?: (activeSlotIndex: number | null) => unknown;\n pushPasswordManagerStrategy?: 'increase-width' | 'none';\n pasteTransformer?: (pasted: string) => string;\n\n containerClassName?: string;\n\n noScriptCSSFallback?: string | null;\n }\n>;\n\ntype InputOTPRenderFn = (props: RenderProps) => ReactNode;\n\nexport type OTPInputProps = OTPInputBaseProps &\n (\n | {\n render: InputOTPRenderFn;\n children?: never;\n }\n | {\n render?: never;\n children: ReactNode;\n }\n );\n\n// ---------------- Hooks ----------------\n\nexport const usePasswordManagerBadge = ({\n containerRef,\n inputRef,\n pushPasswordManagerStrategy,\n isFocused,\n}: {\n containerRef: RefObject<HTMLDivElement | null>;\n inputRef: RefObject<HTMLInputElement | null>;\n pushPasswordManagerStrategy: OTPInputProps['pushPasswordManagerStrategy'];\n isFocused: boolean;\n}) => {\n /** Password managers have a badge\n * and I'll use this state to push them\n * outside the input */\n const [hasPWMBadge, setHasPWMBadge] = useState(false);\n const [hasPWMBadgeSpace, setHasPWMBadgeSpace] = useState(false);\n const [done, setDone] = useState(false);\n\n const willPushPWMBadge =\n pushPasswordManagerStrategy === 'none'\n ? false\n : (pushPasswordManagerStrategy === 'increase-width' ||\n // TODO: remove 'experimental-no-flickering' support in 2.0.0\n pushPasswordManagerStrategy === 'experimental-no-flickering') &&\n hasPWMBadge &&\n hasPWMBadgeSpace;\n\n const trackPWMBadge = () => {\n const container = containerRef.current;\n const input = inputRef.current;\n if (\n !container ||\n !input ||\n done ||\n pushPasswordManagerStrategy === 'none'\n ) {\n return;\n }\n\n const elementToCompare = container;\n\n // Get the top right-center point of the container.\n // That is usually where most password managers place their badge.\n const rightCornerX =\n elementToCompare.getBoundingClientRect().left +\n elementToCompare.offsetWidth;\n const centereredY =\n elementToCompare.getBoundingClientRect().top +\n elementToCompare.offsetHeight / 2;\n const x = rightCornerX - PWM_BADGE_MARGIN_RIGHT;\n const y = centereredY;\n\n // Do an extra search to check for famous password managers\n const pmws = document.querySelectorAll(PASSWORD_MANAGERS_SELECTORS);\n\n // If no password manager is automatically detect,\n // we'll try to dispatch document.elementFromPoint\n // to identify badges\n if (pmws.length === 0) {\n const maybeBadgeEl = document.elementFromPoint(x, y);\n\n // If the found element is the input itself,\n // then we assume it's not a password manager badge.\n // We are not sure. Most times that means there isn't a badge.\n if (maybeBadgeEl === container) {\n return;\n }\n }\n\n setHasPWMBadge(true);\n setDone(true);\n };\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container || pushPasswordManagerStrategy === 'none') {\n return;\n }\n\n // Check if the PWM area is 100% visible\n const checkHasSpace = () => {\n const viewportWidth = window.innerWidth;\n const distanceToRightEdge =\n viewportWidth - container.getBoundingClientRect().right;\n setHasPWMBadgeSpace(distanceToRightEdge >= PWM_BADGE_SPACE_WIDTH_PX);\n };\n\n checkHasSpace();\n const interval = setInterval(checkHasSpace, 1000);\n\n return () => {\n clearInterval(interval);\n };\n }, [containerRef, pushPasswordManagerStrategy]);\n\n useEffect(() => {\n const _isFocused = isFocused || document.activeElement === inputRef.current;\n\n if (pushPasswordManagerStrategy === 'none' || !_isFocused) {\n return;\n }\n const t1 = setTimeout(trackPWMBadge, 0);\n const t2 = setTimeout(trackPWMBadge, 2000);\n const t3 = setTimeout(trackPWMBadge, 5000);\n const t4 = setTimeout(() => {\n setDone(true);\n }, 6000);\n return () => {\n clearTimeout(t1);\n clearTimeout(t2);\n clearTimeout(t3);\n clearTimeout(t4);\n };\n }, [inputRef, isFocused, pushPasswordManagerStrategy]);\n\n return { hasPWMBadge, willPushPWMBadge, PWM_BADGE_SPACE_WIDTH };\n};\n\nexport const usePrevious = <T,>(value: T): T | undefined => {\n const ref = useRef<T | undefined>(undefined);\n useEffect(() => {\n ref.current = value;\n });\n return ref.current;\n};\n\n// ---------------- Context ----------------\n\nexport const OTPInputContext = createContext<RenderProps>({} as RenderProps);\n\n// ---------------- Core Component ----------------\n\nexport const OTPInput: FC<OTPInputProps> = ({\n value: uncheckedValue,\n onChange: uncheckedOnChange,\n maxLength,\n pattern,\n placeholder,\n inputMode = 'numeric',\n onComplete,\n onActiveSlotChange,\n pushPasswordManagerStrategy = 'increase-width',\n pasteTransformer,\n containerClassName,\n noScriptCSSFallback = NOSCRIPT_CSS_FALLBACK,\n render,\n children,\n ...props\n}) => {\n // Only used when `value` state is not provided\n const [internalValue, setInternalValue] = useState(\n typeof props.defaultValue === 'string' ? props.defaultValue : ''\n );\n\n // Definitions\n const value = uncheckedValue ?? internalValue;\n const previousValue = usePrevious(value);\n const onChange = (newValue: string) => {\n uncheckedOnChange?.(newValue);\n setInternalValue(newValue);\n };\n const regexp =\n pattern !== undefined\n ? typeof pattern === 'string'\n ? new RegExp(pattern)\n : pattern\n : null;\n\n /** useRef */\n const inputRef = useRef<HTMLInputElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const initialLoadRef = useRef({\n value,\n onChange,\n isIOS:\n typeof window !== 'undefined' &&\n window?.CSS?.supports?.('-webkit-touch-callout', 'none'),\n });\n const inputMetadataRef = useRef<{\n prev: [number | null, number | null, 'none' | 'forward' | 'backward'];\n }>({\n prev: [\n inputRef.current?.selectionStart ?? null,\n inputRef.current?.selectionEnd ?? null,\n inputRef.current?.selectionDirection ?? 'none',\n ],\n });\n useEffect(() => {\n const input = inputRef.current;\n const container = containerRef.current;\n\n if (!input || !container) {\n return;\n }\n\n // Sync input value\n if (initialLoadRef.current.value !== input.value) {\n initialLoadRef.current.onChange(input.value);\n }\n\n // Previous selection\n inputMetadataRef.current.prev = [\n input.selectionStart,\n input.selectionEnd,\n input.selectionDirection ?? 'none',\n ];\n const onDocumentSelectionChange = () => {\n if (document.activeElement !== input) {\n setMirrorSelectionStart(null);\n setMirrorSelectionEnd(null);\n setActualCaretPosition(null);\n return;\n }\n\n const selectionStart = input.selectionStart;\n const selectionEnd = input.selectionEnd;\n const selectionDirection = input.selectionDirection;\n const maxLength = input.maxLength;\n const value = input.value;\n const previousSelection = inputMetadataRef.current.prev;\n\n let calculatedStart = -1;\n let calculatedEnd = -1;\n let calculatedDirection: 'forward' | 'backward' | 'none' =\n selectionDirection ?? 'none';\n\n if (\n value.length !== 0 &&\n selectionStart !== null &&\n selectionEnd !== null\n ) {\n const isSingleCaret = selectionStart === selectionEnd;\n const isInsertMode =\n selectionStart === value.length && value.length < maxLength;\n\n if (isSingleCaret && !isInsertMode) {\n const caretPosition = selectionStart;\n if (caretPosition === 0) {\n calculatedStart = 0;\n calculatedEnd = 1;\n calculatedDirection = 'forward';\n } else if (caretPosition === maxLength) {\n calculatedStart = caretPosition - 1;\n calculatedEnd = caretPosition;\n calculatedDirection = 'backward';\n } else if (maxLength > 1 && value.length > 1) {\n let offset = 0;\n if (\n previousSelection[0] !== null &&\n previousSelection[1] !== null\n ) {\n calculatedDirection =\n caretPosition < previousSelection[1] ? 'backward' : 'forward';\n const wasPreviouslyInserting =\n previousSelection[0] === previousSelection[1] &&\n previousSelection[0] < maxLength;\n if (\n calculatedDirection === 'backward' &&\n !wasPreviouslyInserting\n ) {\n offset = -1;\n }\n }\n\n calculatedStart = offset + caretPosition;\n calculatedEnd = offset + caretPosition + 1;\n }\n }\n\n if (\n calculatedStart !== -1 &&\n calculatedEnd !== -1 &&\n calculatedStart !== calculatedEnd\n ) {\n inputRef.current?.setSelectionRange(\n calculatedStart,\n calculatedEnd,\n calculatedDirection\n );\n }\n }\n\n const finalSelectionStart =\n calculatedStart !== -1 ? calculatedStart : selectionStart;\n const finalSelectionEnd =\n calculatedEnd !== -1 ? calculatedEnd : selectionEnd;\n const finalDirection = calculatedDirection;\n\n // Track actual caret position (before expansion) for active slot detection\n if (selectionStart !== null && selectionEnd !== null) {\n const isSingleCaret = selectionStart === selectionEnd;\n if (isSingleCaret) {\n setActualCaretPosition(selectionStart);\n } else {\n // When selection is expanded, use the start position as the caret\n setActualCaretPosition(finalSelectionStart);\n }\n } else {\n setActualCaretPosition(null);\n }\n\n setMirrorSelectionStart(finalSelectionStart);\n setMirrorSelectionEnd(finalSelectionEnd);\n inputMetadataRef.current.prev = [\n finalSelectionStart,\n finalSelectionEnd,\n finalDirection,\n ];\n };\n document.addEventListener('selectionchange', onDocumentSelectionChange, {\n capture: true,\n });\n\n // Set initial mirror state\n onDocumentSelectionChange();\n if (document.activeElement === input) {\n setIsFocused(true);\n }\n\n // Apply needed styles\n if (!document.getElementById('input-otp-style')) {\n const styleEl = document.createElement('style');\n styleEl.id = 'input-otp-style';\n document.head.appendChild(styleEl);\n\n if (styleEl.sheet) {\n const autofillStyles =\n 'background: transparent !important; color: transparent !important; border-color: transparent !important; opacity: 0 !important; box-shadow: none !important; -webkit-box-shadow: none !important; -webkit-text-fill-color: transparent !important;';\n\n safeInsertRule(\n styleEl.sheet,\n '[data-input-otp]::selection { background: transparent !important; color: transparent !important; }'\n );\n safeInsertRule(\n styleEl.sheet,\n `[data-input-otp]:autofill { ${autofillStyles} }`\n );\n safeInsertRule(\n styleEl.sheet,\n `[data-input-otp]:-webkit-autofill { ${autofillStyles} }`\n );\n // iOS\n safeInsertRule(\n styleEl.sheet,\n `@supports (-webkit-touch-callout: none) { [data-input-otp] { letter-spacing: -.6em !important; font-weight: 100 !important; font-stretch: ultra-condensed; font-optical-sizing: none !important; left: -1px !important; right: 1px !important; } }`\n );\n // PWM badges\n safeInsertRule(\n styleEl.sheet,\n `[data-input-otp] + * { pointer-events: all !important; }`\n );\n }\n }\n // Track root height\n const updateRootHeight = () => {\n if (container) {\n container.style.setProperty('--root-height', `${input.clientHeight}px`);\n }\n };\n updateRootHeight();\n const resizeObserver = new ResizeObserver(updateRootHeight);\n resizeObserver.observe(input);\n\n return () => {\n document.removeEventListener(\n 'selectionchange',\n onDocumentSelectionChange,\n { capture: true }\n );\n resizeObserver.disconnect();\n };\n }, []);\n\n /** Mirrors for UI rendering purpose only */\n const [isHoveringInput, setIsHoveringInput] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n const [mirrorSelectionStart, setMirrorSelectionStart] = useState<\n number | null\n >(null);\n const [mirrorSelectionEnd, setMirrorSelectionEnd] = useState<number | null>(\n null\n );\n const [actualCaretPosition, setActualCaretPosition] = useState<number | null>(\n null\n );\n\n /** Effects */\n useEffect(() => {\n syncTimeouts(() => {\n // Forcefully remove :autofill state\n inputRef.current?.dispatchEvent(new Event('input'));\n\n // Update the selection state\n const s = inputRef.current?.selectionStart ?? null;\n const e = inputRef.current?.selectionEnd ?? null;\n const dir = inputRef.current?.selectionDirection ?? 'none';\n if (s !== null && e !== null) {\n setMirrorSelectionStart(s);\n setMirrorSelectionEnd(e);\n // Track actual caret position (use start position as caret)\n setActualCaretPosition(s);\n inputMetadataRef.current.prev = [s, e, dir];\n }\n });\n }, [value, isFocused]);\n\n useEffect(() => {\n if (previousValue === undefined) {\n return;\n }\n\n if (\n value !== previousValue &&\n previousValue.length < maxLength &&\n value.length === maxLength\n ) {\n onComplete?.(value);\n }\n }, [maxLength, onComplete, previousValue, value]);\n\n // Track active slot changes\n const previousActiveSlot = useRef<number | null>(null);\n useEffect(() => {\n const activeSlotIndex =\n isFocused && actualCaretPosition !== null ? actualCaretPosition : null;\n\n if (activeSlotIndex !== previousActiveSlot.current) {\n previousActiveSlot.current = activeSlotIndex;\n onActiveSlotChange?.(activeSlotIndex);\n }\n }, [isFocused, actualCaretPosition, onActiveSlotChange]);\n\n const pwmb = usePasswordManagerBadge({\n containerRef,\n inputRef,\n pushPasswordManagerStrategy,\n isFocused,\n });\n\n /** Event handlers */\n const _changeListener = (e: ChangeEvent<HTMLInputElement>) => {\n const newValue = e.currentTarget.value.slice(0, maxLength);\n if (newValue.length > 0 && regexp && !regexp.test(newValue)) {\n e.preventDefault();\n return;\n }\n const maybeHasDeleted =\n typeof previousValue === 'string' &&\n newValue.length < previousValue.length;\n if (maybeHasDeleted) {\n // Since cutting/deleting text doesn't trigger\n // selectionchange event, we'll have to dispatch it manually.\n // NOTE: The following line also triggers when cmd+A then pasting\n // a value with smaller length, which is not ideal for performance.\n document.dispatchEvent(new Event('selectionchange'));\n }\n onChange(newValue);\n };\n const _focusListener = () => {\n if (inputRef.current) {\n const start = Math.min(inputRef.current.value.length, maxLength - 1);\n const end = inputRef.current.value.length;\n inputRef.current?.setSelectionRange(start, end);\n setMirrorSelectionStart(start);\n setMirrorSelectionEnd(end);\n }\n setIsFocused(true);\n };\n // Fix iOS pasting\n const _pasteListener = (e: ClipboardEvent<HTMLInputElement>) => {\n const input = inputRef.current;\n if (\n !pasteTransformer &&\n (!initialLoadRef.current.isIOS || !e.clipboardData || !input)\n ) {\n return;\n }\n\n const _content = e.clipboardData.getData('text/plain');\n const content = pasteTransformer ? pasteTransformer(_content) : _content;\n e.preventDefault();\n\n const start = inputRef.current?.selectionStart;\n const end = inputRef.current?.selectionEnd;\n\n const isReplacing = start !== end;\n\n const newValueUncapped = isReplacing\n ? value.slice(0, start ?? 0) + content + value.slice(end ?? 0) // Replacing\n : value.slice(0, start ?? 0) + content + value.slice(start ?? 0); // Inserting\n const newValue = newValueUncapped.slice(0, maxLength);\n\n if (newValue.length > 0 && regexp && !regexp.test(newValue)) {\n return;\n }\n\n if (input) {\n input.value = newValue;\n onChange(newValue);\n\n const _start = Math.min(newValue.length, maxLength - 1);\n const _end = newValue.length;\n\n input.setSelectionRange(_start, _end);\n setMirrorSelectionStart(_start);\n setMirrorSelectionEnd(_end);\n }\n };\n\n /** Styles - dynamic styles that can't be converted to Tailwind */\n const dynamicInputStyle: CSSProperties = {\n width: pwmb.willPushPWMBadge\n ? `calc(100% + ${pwmb.PWM_BADGE_SPACE_WIDTH})`\n : '100%',\n clipPath: pwmb.willPushPWMBadge\n ? `inset(0 ${pwmb.PWM_BADGE_SPACE_WIDTH} 0 0)`\n : undefined,\n fontSize: 'var(--root-height)',\n };\n\n /** Rendering */\n const renderedInput = (\n <input\n autoComplete={props.autoComplete || 'one-time-code'}\n {...props}\n data-input-otp\n data-input-otp-placeholder-shown={value.length === 0 || undefined}\n data-input-otp-mss={mirrorSelectionStart}\n data-input-otp-mse={mirrorSelectionEnd}\n inputMode={inputMode}\n pattern={regexp?.source}\n aria-placeholder={placeholder}\n className=\"pointer-events-auto absolute inset-0 -z-10 flex h-full border-0 border-transparent bg-transparent text-center font-mono text-transparent tabular-nums leading-none tracking-[-.5em] caret-transparent opacity-100 shadow-none outline-none\"\n style={dynamicInputStyle}\n maxLength={maxLength}\n value={value}\n ref={inputRef}\n onPaste={(e) => {\n _pasteListener(e);\n props.onPaste?.(e);\n }}\n onChange={_changeListener}\n onMouseOver={(e) => {\n setIsHoveringInput(true);\n props.onMouseOver?.(e);\n }}\n onMouseLeave={(e) => {\n setIsHoveringInput(false);\n props.onMouseLeave?.(e);\n }}\n onKeyDown={(e) => {\n // Track arrow key navigation to ensure active slot updates correctly\n if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n // Use requestAnimationFrame to check selection after browser has processed the key\n requestAnimationFrame(() => {\n const input = inputRef.current;\n if (input && document.activeElement === input) {\n const s = input.selectionStart;\n const end = input.selectionEnd;\n if (s !== null && end !== null) {\n // Update actual caret position - use start position as caret\n setActualCaretPosition(s);\n }\n }\n });\n }\n props.onKeyDown?.(e);\n }}\n onFocus={(e) => {\n _focusListener();\n props.onFocus?.(e);\n }}\n onBlur={(e) => {\n setIsFocused(false);\n props.onBlur?.(e);\n }}\n />\n );\n\n const setSelection = (index: number) => {\n const input = inputRef.current;\n if (!input || props.disabled) {\n return;\n }\n\n // Clamp index to valid range\n const clampedIndex = Math.max(0, Math.min(index, maxLength - 1));\n\n // Focus the input if not already focused\n if (document.activeElement !== input) {\n input.focus();\n }\n\n // Set selection to the clicked slot\n // If there's a character at that position, select it; otherwise just position the caret\n const hasChar = value[clampedIndex] !== undefined;\n const start = clampedIndex;\n const end = hasChar ? clampedIndex + 1 : clampedIndex;\n\n input.setSelectionRange(start, end);\n setMirrorSelectionStart(start);\n setMirrorSelectionEnd(end);\n setIsFocused(true);\n };\n\n const contextValue: RenderProps = {\n slots: Array.from({ length: maxLength }).map((_, slotIdx) => {\n const isActive =\n isFocused &&\n mirrorSelectionStart !== null &&\n mirrorSelectionEnd !== null &&\n ((mirrorSelectionStart === mirrorSelectionEnd &&\n slotIdx === mirrorSelectionStart) ||\n (slotIdx >= mirrorSelectionStart && slotIdx < mirrorSelectionEnd));\n\n const char = value[slotIdx] !== undefined ? value[slotIdx] : null;\n const placeholderChar =\n value[0] !== undefined ? null : (placeholder?.[slotIdx] ?? null);\n\n return {\n char,\n placeholderChar,\n isActive,\n hasFakeCaret: isActive && char === null,\n };\n }),\n isFocused,\n isHovering: !props.disabled && isHoveringInput,\n setSelection,\n };\n\n const renderedChildren =\n render !== undefined ? (\n render(contextValue)\n ) : (\n <OTPInputContext.Provider value={contextValue}>\n {children}\n </OTPInputContext.Provider>\n );\n\n return (\n <>\n {noScriptCSSFallback !== null && (\n <noscript>\n <style>{noScriptCSSFallback}</style>\n </noscript>\n )}\n\n <div\n ref={containerRef}\n className={cn(\n 'relative',\n props.disabled ? 'cursor-default' : 'cursor-text',\n containerClassName\n )}\n >\n {renderedChildren}\n\n <div className=\"absolute inset-0\">{renderedInput}</div>\n </div>\n </>\n );\n};\n\n// ---------------- Root ----------------\n\ntype InputOTPProps = Omit<ComponentProps<typeof OTPInput>, 'children'>;\n\nexport const inputSlotVariants = cva('block text-center', {\n variants: {\n size: {\n sm: 'h-4 w-3 text-sm',\n md: 'h-5 w-4 text-base',\n lg: 'h-6 w-5 text-lg',\n xl: 'h-7 w-6 text-xl',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\nexport const InputOTP: FC<InputOTPProps> = ({\n className,\n render,\n ...props\n}) => (\n <OTPInput\n containerClassName=\"relative flex items-center gap-2 has-disabled:opacity-50\"\n className={cn('disabled:cursor-not-allowed', className)}\n render={render!}\n {...props}\n />\n);\n\n// ---------------- Group ----------------\n\nexport const InputOTPGroup = ({\n className,\n ...props\n}: ComponentProps<'div'>) => (\n <div className={cn('z-10 flex items-center gap-3', className)} {...props} />\n);\n\n// ---------------- Slot ----------------\n\ntype InputOTPSlotProps = Omit<ButtonProps, 'variant' | 'label'> & {\n index: number;\n};\n\nexport const InputOTPSlot: FC<InputOTPSlotProps> = ({\n index,\n className,\n onClick,\n onKeyDown,\n ...props\n}) => {\n const inputOTPContext = useContext(OTPInputContext);\n const { char, isActive } = inputOTPContext?.slots[index] ?? {};\n const { setSelection } = inputOTPContext ?? {};\n\n const handleClick = (e: MouseEvent<HTMLButtonElement>) => {\n setSelection?.(index);\n onClick?.(e);\n };\n\n const handleKeyDown = (e: KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n setSelection?.(index);\n }\n onKeyDown?.(e);\n };\n\n return (\n <Button\n isSelected={isActive}\n variant=\"input\"\n color=\"custom\"\n tabIndex={-1}\n className={cn('relative z-10 px-2!', isActive && 'ring-4!', className)}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n label={null}\n {...props}\n >\n {/* value */}\n <span className=\"relative z-10 flex h-6 w-4 items-center justify-center\">\n {char}\n </span>\n </Button>\n );\n};\n\n// ---------------- Separator ----------------\n\nexport const InputOTPSeparator: FC<ComponentProps<'div'>> = (props) => (\n <div\n aria-hidden\n className=\"z-0 table h-0.5 w-3 rounded-full text-foreground/50\"\n {...props}\n >\n <MinusIcon />\n </div>\n);\n\nexport const InputIndicator: FC<ComponentProps<'div'>> = (props) => (\n <div\n data-indicator\n className=\"absolute top-0 z-0 h-full w-auto rounded-xl bg-text/20 ring-4 ring-text/20 transition-[left,width] duration-300 ease-in-out [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl motion-reduce:transition-none\"\n {...props}\n />\n);\n"],"mappings":"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"}
|
|
@@ -157,7 +157,7 @@ const KeyboardShortcut = ({ shortcut, onTriggered, display = true, disabled = fa
|
|
|
157
157
|
return pressedKeys.has(key) || pressedKeys.has(upperKey) || pressedKeys.has(normalizedKey) || key === "⌘" && pressedKeys.has("Meta") || key === "Ctrl" && pressedKeys.has("Control") || key === "⌥" && pressedKeys.has("Alt") || key === "Alt" && pressedKeys.has("Alt") || key === "←" && pressedKeys.has("ArrowLeft") || key === "→" && pressedKeys.has("ArrowRight") || key === "↑" && pressedKeys.has("ArrowUp") || key === "↓" && pressedKeys.has("ArrowDown");
|
|
158
158
|
};
|
|
159
159
|
return /* @__PURE__ */ jsx("kbd", {
|
|
160
|
-
className: cn("inline-flex items-center justify-center gap-0.5 p-0.5", "rounded-lg [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-xl", "font-medium font-sans", "border-1
|
|
160
|
+
className: cn("inline-flex items-center justify-center gap-0.5 p-0.5", "rounded-lg [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-xl", "font-medium font-sans", "border-1 text-neutral", size === "sm" && "text-xs", size === "md" && "text-sm", size === "lg" && "text-base", className),
|
|
161
161
|
children: keys.map((key, index) => {
|
|
162
162
|
const keyId = `${key}-${index}-${shortcut}`;
|
|
163
163
|
const displayKey = getDisplayKey(key);
|
|
@@ -167,7 +167,7 @@ const KeyboardShortcut = ({ shortcut, onTriggered, display = true, disabled = fa
|
|
|
167
167
|
className: "text-neutral/50",
|
|
168
168
|
children: "+"
|
|
169
169
|
}), /* @__PURE__ */ jsx("span", {
|
|
170
|
-
className: cn("min-w-4 px-0.5 text-center", isKeyPressed(key) && "scale-120 font-bold text-
|
|
170
|
+
className: cn("min-w-4 px-0.5 text-center", isKeyPressed(key) && "scale-120 font-bold text-foreground"),
|
|
171
171
|
suppressHydrationWarning: true,
|
|
172
172
|
children: displayKey
|
|
173
173
|
})]
|