@shipfox/react-ui 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +5 -5
- package/.turbo/turbo-check.log +2 -2
- package/.turbo/turbo-type.log +1 -1
- package/CHANGELOG.md +12 -0
- package/dist/components/badge/index.d.ts +4 -4
- package/dist/components/badge/index.d.ts.map +1 -1
- package/dist/components/badge/index.js +4 -4
- package/dist/components/badge/index.js.map +1 -1
- package/dist/components/code-block/code-block-footer.d.ts.map +1 -1
- package/dist/components/code-block/code-block-footer.js +11 -5
- package/dist/components/code-block/code-block-footer.js.map +1 -1
- package/dist/components/confetti/confetti.d.ts +21 -0
- package/dist/components/confetti/confetti.d.ts.map +1 -0
- package/dist/components/confetti/confetti.js +101 -0
- package/dist/components/confetti/confetti.js.map +1 -0
- package/dist/components/confetti/confetti.stories.js +41 -0
- package/dist/components/confetti/confetti.stories.js.map +1 -0
- package/dist/components/confetti/index.d.ts +2 -0
- package/dist/components/confetti/index.d.ts.map +1 -0
- package/dist/components/confetti/index.js +3 -0
- package/dist/components/confetti/index.js.map +1 -0
- package/dist/components/dropdown-menu/index.d.ts +1 -2
- package/dist/components/dropdown-menu/index.d.ts.map +1 -1
- package/dist/components/dropdown-menu/index.js +1 -1
- package/dist/components/dropdown-menu/index.js.map +1 -1
- package/dist/components/icon/icon.d.ts +3 -2
- package/dist/components/icon/icon.d.ts.map +1 -1
- package/dist/components/icon/icon.js +7 -2
- package/dist/components/icon/icon.js.map +1 -1
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +4 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/modal/index.d.ts +1 -2
- package/dist/components/modal/index.d.ts.map +1 -1
- package/dist/components/modal/index.js +1 -1
- package/dist/components/modal/index.js.map +1 -1
- package/dist/components/modal/modal.d.ts +2 -1
- package/dist/components/modal/modal.d.ts.map +1 -1
- package/dist/components/modal/modal.js +5 -3
- package/dist/components/modal/modal.js.map +1 -1
- package/dist/components/modal/modal.stories.js +228 -167
- package/dist/components/modal/modal.stories.js.map +1 -1
- package/dist/components/shiny-text/index.d.ts +2 -0
- package/dist/components/shiny-text/index.d.ts.map +1 -0
- package/dist/components/shiny-text/index.js +3 -0
- package/dist/components/shiny-text/index.js.map +1 -0
- package/dist/components/shiny-text/shiny-text.d.ts +10 -0
- package/dist/components/shiny-text/shiny-text.d.ts.map +1 -0
- package/dist/components/shiny-text/shiny-text.js +17 -0
- package/dist/components/shiny-text/shiny-text.js.map +1 -0
- package/dist/components/tabs/index.d.ts +2 -0
- package/dist/components/tabs/index.d.ts.map +1 -0
- package/dist/components/tabs/index.js +3 -0
- package/dist/components/tabs/index.js.map +1 -0
- package/dist/components/tabs/tabs.d.ts +50 -0
- package/dist/components/tabs/tabs.d.ts.map +1 -0
- package/dist/components/tabs/tabs.js +243 -0
- package/dist/components/tabs/tabs.js.map +1 -0
- package/dist/components/tabs/tabs.stories.js +179 -0
- package/dist/components/tabs/tabs.stories.js.map +1 -0
- package/dist/components/toast/index.d.ts +2 -2
- package/dist/components/toast/index.d.ts.map +1 -1
- package/dist/components/toast/index.js +2 -2
- package/dist/components/toast/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/utils/debounce.d.ts +2 -0
- package/dist/utils/debounce.d.ts.map +1 -0
- package/dist/utils/debounce.js +13 -0
- package/dist/utils/debounce.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/index.css +34 -0
- package/package.json +4 -1
- package/src/components/badge/index.ts +4 -4
- package/src/components/code-block/code-block-footer.tsx +12 -2
- package/src/components/confetti/confetti.stories.tsx +38 -0
- package/src/components/confetti/confetti.tsx +140 -0
- package/src/components/confetti/index.ts +1 -0
- package/src/components/dropdown-menu/index.ts +1 -29
- package/src/components/icon/icon.tsx +7 -3
- package/src/components/index.ts +4 -0
- package/src/components/modal/index.ts +1 -23
- package/src/components/modal/modal.stories.tsx +60 -6
- package/src/components/modal/modal.tsx +4 -2
- package/src/components/shiny-text/index.ts +1 -0
- package/src/components/shiny-text/shiny-text.tsx +21 -0
- package/src/components/tabs/index.ts +1 -0
- package/src/components/tabs/tabs.stories.tsx +100 -0
- package/src/components/tabs/tabs.tsx +380 -0
- package/src/components/toast/index.ts +2 -2
- package/src/index.ts +1 -0
- package/src/utils/debounce.ts +15 -0
- package/src/utils/index.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/modal/modal.stories.tsx"],"sourcesContent":["import {argosScreenshot} from '@argos-ci/storybook/vitest';\nimport type {Meta, StoryObj} from '@storybook/react';\nimport {screen, within} from '@testing-library/react';\nimport userEvent from '@testing-library/user-event';\nimport {Button, ButtonLink} from 'components/button';\nimport {\n CodeBlock,\n CodeBlockBody,\n CodeBlockContent,\n CodeBlockCopyButton,\n CodeBlockFilename,\n CodeBlockFiles,\n CodeBlockFooter,\n CodeBlockHeader,\n CodeBlockItem,\n} from 'components/code-block';\nimport {DatePicker} from 'components/date-picker';\nimport {DynamicItem} from 'components/dynamic-item';\nimport {Icon} from 'components/icon';\nimport {Input} from 'components/input';\nimport {ItemTitle} from 'components/item';\nimport {Label} from 'components/label';\nimport {MovingBorder} from 'components/moving-border';\nimport {Text} from 'components/typography';\nimport {useState} from 'react';\nimport {cn} from 'utils/cn';\nimport illustration2 from '../../assets/illustration-2.svg';\nimport illustrationBg from '../../assets/illustration-gradient.svg';\nimport {\n Modal,\n ModalBody,\n ModalContent,\n ModalFooter,\n ModalHeader,\n ModalTitle,\n ModalTrigger,\n} from './modal';\n\nconst OPEN_MODAL_REGEX = /open modal/i;\nconst IMPORT_JOBS_REGEX = /import past jobs from github/i;\nconst GITHUB_ACTIONS_REGEX = /run github actions on shipfox/i;\n\nconst DEFAULT_START_DATE = new Date('2025-12-06T00:00:00.000Z');\n\nconst meta = {\n title: 'Components/Modal',\n component: Modal,\n tags: ['autodocs'],\n parameters: {\n layout: 'centered',\n },\n} satisfies Meta<typeof Modal>;\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Default: Story = {\n play: async (ctx) => {\n const {canvasElement, step} = ctx;\n const canvas = within(canvasElement);\n const user = userEvent.setup();\n\n await step('Open the modal', async () => {\n const triggerButton = canvas.getByRole('button', {name: OPEN_MODAL_REGEX});\n await user.click(triggerButton);\n });\n\n await step('Wait for dialog to appear and render', async () => {\n await screen.findByRole('dialog');\n await new Promise((resolve) => setTimeout(resolve, 100));\n });\n\n await argosScreenshot(ctx, 'Default Modal Open');\n },\n render: () => {\n const [open, setOpen] = useState(false);\n\n return (\n <div className=\"flex h-[calc(100vh/2)] w-[calc(100vw/2)] items-center justify-center rounded-16 bg-background-subtle-base shadow-tooltip\">\n <Modal open={open} onOpenChange={setOpen}>\n <ModalTrigger asChild>\n <Button>Open Modal</Button>\n </ModalTrigger>\n <ModalContent aria-describedby={undefined}>\n <ModalTitle className=\"sr-only\">Modal Title</ModalTitle>\n <ModalHeader>\n <Text\n size=\"lg\"\n className=\"flex-1 overflow-ellipsis overflow-hidden whitespace-nowrap\"\n >\n Modal Title\n </Text>\n </ModalHeader>\n <ModalBody>\n <Text size=\"sm\" className=\"text-foreground-neutral-subtle w-full\">\n This modal automatically adapts between dialog (desktop) and drawer (mobile) based\n on screen size. Try resizing your browser window!\n </Text>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"transparent\" onClick={() => setOpen(false)}>\n Cancel\n </Button>\n <Button variant=\"primary\" onClick={() => setOpen(false)}>\n Confirm\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n </div>\n );\n },\n};\n\nexport const ImportForm: Story = {\n play: async (ctx) => {\n const {canvasElement, step} = ctx;\n const canvas = within(canvasElement);\n const user = userEvent.setup();\n\n await step('Open the modal', async () => {\n const triggerButton = canvas.getByRole('button', {name: IMPORT_JOBS_REGEX});\n await user.click(triggerButton);\n });\n\n await step('Wait for dialog to appear and render', async () => {\n await screen.findByRole('dialog');\n await new Promise((resolve) => setTimeout(resolve, 100));\n });\n\n await argosScreenshot(ctx, 'Import Form Modal Open');\n },\n render: () => {\n const [open, setOpen] = useState(false);\n const [date, setDate] = useState<Date | undefined>(DEFAULT_START_DATE);\n\n return (\n <div className=\"flex h-[calc(100vh/2)] w-[calc(100vw/2)] items-center justify-center rounded-16 bg-background-subtle-base shadow-tooltip\">\n <Modal open={open} onOpenChange={setOpen}>\n <ModalTrigger asChild>\n <Button>Import past jobs from GitHub</Button>\n </ModalTrigger>\n <ModalContent aria-describedby={undefined}>\n <ModalTitle className=\"sr-only\">Import past jobs from GitHub</ModalTitle>\n <ModalHeader title=\"Import past jobs from GitHub\" />\n <ModalBody className=\"gap-20\">\n <Text size=\"sm\" className=\"text-foreground-neutral-subtle w-full\">\n Backfill your CI history by importing past runs from your GitHub repo. We'll\n handle the rest by creating a background task to import the data for you.\n </Text>\n <div className=\"flex flex-col gap-20 w-full\">\n <div className=\"flex flex-col gap-8 w-full\">\n <Label>Repository owner</Label>\n <Input placeholder=\"apache\" />\n </div>\n <div className=\"flex flex-col gap-8 w-full\">\n <Label>Repository name</Label>\n <Input placeholder=\"kafka\" />\n </div>\n <div className=\"flex flex-col gap-8 w-full\">\n <Label htmlFor=\"start-date\">Start date</Label>\n <DatePicker\n id=\"start-date\"\n date={date}\n onDateSelect={setDate}\n onClear={() => setDate(undefined)}\n placeholder=\"DD/MM/YYYY\"\n />\n </div>\n </div>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"transparent\" onClick={() => setOpen(false)}>\n Cancel\n </Button>\n <Button variant=\"primary\" onClick={() => setOpen(false)}>\n Import\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n </div>\n );\n },\n};\n\nconst diffCode = `jobs:\n build:\n- runs-on: ubuntu-latest\n+ runs-on: shipfox-2vcpu-ubuntu-2404`;\n\nexport const GithubActions: Story = {\n parameters: {\n viewport: {\n defaultViewport: 'large',\n },\n },\n play: async (ctx) => {\n const {canvasElement, step} = ctx;\n const canvas = within(canvasElement);\n const user = userEvent.setup();\n\n await step('Open the modal', async () => {\n const triggerButton = canvas.getByRole('button', {name: GITHUB_ACTIONS_REGEX});\n await user.click(triggerButton);\n });\n\n await step('Wait for dialog to appear and render', async () => {\n await screen.findByRole('dialog');\n await new Promise((resolve) => setTimeout(resolve, 100));\n });\n\n await argosScreenshot(ctx, 'Github Actions Modal Open');\n },\n render: () => {\n const [open, setOpen] = useState(false);\n\n return (\n <div className=\"flex h-[50vh] w-[calc(100vw/2)] items-center justify-center rounded-16 bg-background-subtle-base shadow-tooltip\">\n <Modal open={open} onOpenChange={setOpen}>\n <ModalTrigger asChild>\n <Button>Run GitHub Actions on Shipfox</Button>\n </ModalTrigger>\n <ModalContent aria-describedby={undefined}>\n <ModalTitle className=\"sr-only\">Run GitHub Actions on Shipfox</ModalTitle>\n <ModalHeader title=\"Run GitHub Actions on Shipfox\" />\n <ModalBody className=\"gap-32\">\n <div className=\"flex flex-col gap-20 w-full\">\n <Text size=\"sm\" className=\"text-foreground-neutral-subtle w-full\">\n This will run your jobs on Shipfox's optimized infrastructure. Giving you\n faster builds, and dedicated resources.\n </Text>\n <div className=\"relative\">\n <img\n src={illustration2}\n alt=\"illustration-2\"\n className=\"hidden sm:block absolute overflow-clip right-2 top-1/2 -translate-y-1/2 translate-x-8 w-fit object-contain z-50\"\n />\n <div className={cn('relative overflow-hidden bg-transparent p-1 rounded-8')}>\n <div className=\"absolute inset-0\" style={{borderRadius: 'calc(0.5rem * 0.96)'}}>\n <MovingBorder duration={6000} rx=\"30%\" ry=\"30%\">\n <div className=\"h-100 w-200 bg-[radial-gradient(#ff9e7a_40%,transparent_60%)]\" />\n </MovingBorder>\n </div>\n <div\n className=\"relative\"\n style={{\n borderRadius: 'calc(0.5rem * 0.96)',\n }}\n >\n <DynamicItem\n variant=\"default\"\n title={\n <div className=\"flex items-center gap-6\">\n <span className=\"flex shrink-0 items-center justify-center text-tag-success-icon w-16 h-16\">\n <Icon\n name=\"money\"\n size=\"sm\"\n color=\"var(--foreground-neutral-subtle, #a1a1aa)\"\n />\n </span>\n <ItemTitle>6000 free credits/month to run your jobs</ItemTitle>\n </div>\n }\n description=\"~500 builds/month. No payment required.\"\n rightElement={\n <img\n src={illustrationBg}\n alt=\"illustration-bg\"\n className=\"hidden sm:block absolute overflow-clip right-4 w-fit object-contain scale-105\"\n />\n }\n />\n </div>\n </div>\n </div>\n </div>\n <div className=\"flex flex-col gap-20 w-full\">\n <div className=\"flex flex-col gap-6\">\n <div className=\"flex items-center justify-center w-full\">\n <Text className=\"flex-1 font-semibold text-foreground-neutral-base overflow-ellipsis overflow-hidden whitespace-nowrap\">\n Update your GitHub Actions workflow\n </Text>\n <ButtonLink variant=\"base\" size=\"sm\" href=\"#\" iconRight=\"bookOpen\">\n See docs\n </ButtonLink>\n </div>\n <Text size=\"sm\" className=\"text-foreground-neutral-subtle w-full\">\n Replace the runs-on line in your workflow file to use Shipfox runners.\n </Text>\n </div>\n\n <CodeBlock\n data={[\n {\n language: 'yaml',\n filename: '.github/workflows/<workflow-name>.yml',\n code: diffCode,\n },\n ]}\n defaultValue=\"yaml\"\n >\n <CodeBlockHeader>\n <CodeBlockFiles>\n {(item) => (\n <CodeBlockFilename value={item.language}>{item.filename}</CodeBlockFilename>\n )}\n </CodeBlockFiles>\n <CodeBlockCopyButton />\n </CodeBlockHeader>\n <CodeBlockBody>\n {(item) => (\n <CodeBlockItem value={item.language}>\n <CodeBlockContent language={item.language}>{item.code}</CodeBlockContent>\n </CodeBlockItem>\n )}\n </CodeBlockBody>\n <CodeBlockFooter\n state=\"running\"\n message=\"Waiting for Shipfox runner event…\"\n description=\"This usually takes 30-60 seconds after you commit the workflow file.\"\n />\n </CodeBlock>\n </div>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"primary\" onClick={() => setOpen(false)}>\n Got it\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n </div>\n );\n },\n};\n\nexport const OpenedModal: Story = {\n play: async (ctx) => {\n const {canvasElement, step} = ctx;\n const canvas = within(canvasElement);\n const user = userEvent.setup();\n\n await step('Open the modal', async () => {\n const triggerButton = canvas.getByRole('button', {name: OPEN_MODAL_REGEX});\n await user.click(triggerButton);\n });\n\n await step('Wait for dialog to appear and render', async () => {\n await screen.findByRole('dialog');\n await new Promise((resolve) => setTimeout(resolve, 100));\n });\n\n await argosScreenshot(ctx, 'Opened Modal State');\n },\n render: () => {\n const [open, setOpen] = useState(false);\n\n return (\n <div className=\"flex h-[calc(100vh/2)] w-[calc(100vw/2)] items-center justify-center rounded-16 bg-background-subtle-base shadow-tooltip\">\n <Modal open={open} onOpenChange={setOpen}>\n <ModalTrigger asChild>\n <Button>Open Modal</Button>\n </ModalTrigger>\n <ModalContent aria-describedby={undefined}>\n <ModalTitle className=\"sr-only\">Modal Title</ModalTitle>\n <ModalHeader>\n <Text\n size=\"lg\"\n className=\"flex-1 overflow-ellipsis overflow-hidden whitespace-nowrap\"\n >\n Modal Title\n </Text>\n </ModalHeader>\n <ModalBody>\n <Text size=\"sm\" className=\"text-foreground-neutral-subtle w-full\">\n This modal automatically adapts between dialog (desktop) and drawer (mobile) based\n on screen size. Try resizing your browser window!\n </Text>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"transparent\" onClick={() => setOpen(false)}>\n Cancel\n </Button>\n <Button variant=\"primary\" onClick={() => setOpen(false)}>\n Confirm\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n </div>\n );\n },\n};\n"],"names":["argosScreenshot","screen","within","userEvent","Button","ButtonLink","CodeBlock","CodeBlockBody","CodeBlockContent","CodeBlockCopyButton","CodeBlockFilename","CodeBlockFiles","CodeBlockFooter","CodeBlockHeader","CodeBlockItem","DatePicker","DynamicItem","Icon","Input","ItemTitle","Label","MovingBorder","Text","useState","cn","illustration2","illustrationBg","Modal","ModalBody","ModalContent","ModalFooter","ModalHeader","ModalTitle","ModalTrigger","OPEN_MODAL_REGEX","IMPORT_JOBS_REGEX","GITHUB_ACTIONS_REGEX","DEFAULT_START_DATE","Date","meta","title","component","tags","parameters","layout","Default","play","ctx","canvasElement","step","canvas","user","setup","triggerButton","getByRole","name","click","findByRole","Promise","resolve","setTimeout","render","open","setOpen","div","className","onOpenChange","asChild","aria-describedby","undefined","size","variant","onClick","ImportForm","date","setDate","placeholder","htmlFor","id","onDateSelect","onClear","diffCode","GithubActions","viewport","defaultViewport","img","src","alt","style","borderRadius","duration","rx","ry","span","color","description","rightElement","href","iconRight","data","language","filename","code","defaultValue","item","value","state","message","OpenedModal"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/modal/modal.stories.tsx"],"sourcesContent":["import {argosScreenshot} from '@argos-ci/storybook/vitest';\nimport type {Meta, StoryObj} from '@storybook/react';\nimport {screen, within} from '@testing-library/react';\nimport userEvent from '@testing-library/user-event';\nimport {Button, ButtonLink} from 'components/button';\nimport {\n CodeBlock,\n CodeBlockBody,\n CodeBlockContent,\n CodeBlockCopyButton,\n CodeBlockFilename,\n CodeBlockFiles,\n CodeBlockFooter,\n CodeBlockHeader,\n CodeBlockItem,\n} from 'components/code-block';\nimport {Confetti, type ConfettiRef} from 'components/confetti';\nimport {DatePicker} from 'components/date-picker';\nimport {DynamicItem} from 'components/dynamic-item';\nimport {Icon} from 'components/icon';\nimport {Input} from 'components/input';\nimport {ItemTitle} from 'components/item';\nimport {Label} from 'components/label';\nimport {MovingBorder} from 'components/moving-border';\nimport {Text} from 'components/typography';\nimport {useEffect, useRef, useState} from 'react';\nimport {cn} from 'utils/cn';\nimport illustration2 from '../../assets/illustration-2.svg';\nimport illustrationBg from '../../assets/illustration-gradient.svg';\nimport {\n Modal,\n ModalBody,\n ModalContent,\n ModalFooter,\n ModalHeader,\n ModalTitle,\n ModalTrigger,\n} from './modal';\n\nconst OPEN_MODAL_REGEX = /open modal/i;\nconst IMPORT_JOBS_REGEX = /import past jobs from github/i;\nconst GITHUB_ACTIONS_REGEX = /run github actions on shipfox/i;\n\nconst DEFAULT_START_DATE = new Date('2025-12-06T00:00:00.000Z');\n\nconst meta = {\n title: 'Components/Modal',\n component: Modal,\n tags: ['autodocs'],\n parameters: {\n layout: 'centered',\n },\n} satisfies Meta<typeof Modal>;\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Default: Story = {\n play: async (ctx) => {\n const {canvasElement, step} = ctx;\n const canvas = within(canvasElement);\n const user = userEvent.setup();\n\n await step('Open the modal', async () => {\n const triggerButton = canvas.getByRole('button', {name: OPEN_MODAL_REGEX});\n await user.click(triggerButton);\n });\n\n await step('Wait for dialog to appear and render', async () => {\n await screen.findByRole('dialog');\n await new Promise((resolve) => setTimeout(resolve, 100));\n });\n\n await argosScreenshot(ctx, 'Default Modal Open');\n },\n render: () => {\n const [open, setOpen] = useState(false);\n\n return (\n <div className=\"flex h-[calc(100vh/2)] w-[calc(100vw/2)] items-center justify-center rounded-16 bg-background-subtle-base shadow-tooltip\">\n <Modal open={open} onOpenChange={setOpen}>\n <ModalTrigger asChild>\n <Button>Open Modal</Button>\n </ModalTrigger>\n <ModalContent aria-describedby={undefined}>\n <ModalTitle className=\"sr-only\">Modal Title</ModalTitle>\n <ModalHeader>\n <Text\n size=\"lg\"\n className=\"flex-1 overflow-ellipsis overflow-hidden whitespace-nowrap\"\n >\n Modal Title\n </Text>\n </ModalHeader>\n <ModalBody>\n <Text size=\"sm\" className=\"text-foreground-neutral-subtle w-full\">\n This modal automatically adapts between dialog (desktop) and drawer (mobile) based\n on screen size. Try resizing your browser window!\n </Text>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"transparent\" onClick={() => setOpen(false)}>\n Cancel\n </Button>\n <Button variant=\"primary\" onClick={() => setOpen(false)}>\n Confirm\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n </div>\n );\n },\n};\n\nexport const ImportForm: Story = {\n play: async (ctx) => {\n const {canvasElement, step} = ctx;\n const canvas = within(canvasElement);\n const user = userEvent.setup();\n\n await step('Open the modal', async () => {\n const triggerButton = canvas.getByRole('button', {name: IMPORT_JOBS_REGEX});\n await user.click(triggerButton);\n });\n\n await step('Wait for dialog to appear and render', async () => {\n await screen.findByRole('dialog');\n await new Promise((resolve) => setTimeout(resolve, 100));\n });\n\n await argosScreenshot(ctx, 'Import Form Modal Open');\n },\n render: () => {\n const [open, setOpen] = useState(false);\n const [date, setDate] = useState<Date | undefined>(DEFAULT_START_DATE);\n\n return (\n <div className=\"flex h-[calc(100vh/2)] w-[calc(100vw/2)] items-center justify-center rounded-16 bg-background-subtle-base shadow-tooltip\">\n <Modal open={open} onOpenChange={setOpen}>\n <ModalTrigger asChild>\n <Button>Import past jobs from GitHub</Button>\n </ModalTrigger>\n <ModalContent aria-describedby={undefined} overlayClassName=\"bg-background-modal-overlay\">\n <ModalTitle className=\"sr-only\">Import past jobs from GitHub</ModalTitle>\n <ModalHeader title=\"Import past jobs from GitHub\" />\n <ModalBody className=\"gap-20\">\n <Text size=\"sm\" className=\"text-foreground-neutral-subtle w-full\">\n Backfill your CI history by importing past runs from your GitHub repo. We'll\n handle the rest by creating a background task to import the data for you.\n </Text>\n <div className=\"flex flex-col gap-20 w-full\">\n <div className=\"flex flex-col gap-8 w-full\">\n <Label>Repository owner</Label>\n <Input placeholder=\"apache\" />\n </div>\n <div className=\"flex flex-col gap-8 w-full\">\n <Label>Repository name</Label>\n <Input placeholder=\"kafka\" />\n </div>\n <div className=\"flex flex-col gap-8 w-full\">\n <Label htmlFor=\"start-date\">Start date</Label>\n <DatePicker\n id=\"start-date\"\n date={date}\n onDateSelect={setDate}\n onClear={() => setDate(undefined)}\n placeholder=\"DD/MM/YYYY\"\n />\n </div>\n </div>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"transparent\" onClick={() => setOpen(false)}>\n Cancel\n </Button>\n <Button variant=\"primary\" onClick={() => setOpen(false)}>\n Import\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n </div>\n );\n },\n};\n\nconst diffCode = `jobs:\n build:\n- runs-on: ubuntu-latest\n+ runs-on: shipfox-2vcpu-ubuntu-2404`;\n\nexport const GithubActions: Story = {\n parameters: {\n viewport: {\n defaultViewport: 'large',\n },\n },\n play: async (ctx) => {\n const {canvasElement, step} = ctx;\n const canvas = within(canvasElement);\n const user = userEvent.setup();\n\n await step('Open the modal', async () => {\n const triggerButton = canvas.getByRole('button', {name: GITHUB_ACTIONS_REGEX});\n await user.click(triggerButton);\n });\n\n await step('Wait for dialog to appear and render', async () => {\n await screen.findByRole('dialog');\n await new Promise((resolve) => setTimeout(resolve, 100));\n });\n\n await argosScreenshot(ctx, 'Github Actions Modal Open');\n },\n render: () => {\n const [open, setOpen] = useState(false);\n const [footerState, setFooterState] = useState<'running' | 'done'>('running');\n const confettiRef = useRef<ConfettiRef>(null);\n\n useEffect(() => {\n if (open && footerState === 'running') {\n const timer = setTimeout(() => {\n setFooterState('done');\n }, 3000);\n\n return () => {\n clearTimeout(timer);\n };\n }\n }, [open, footerState]);\n\n useEffect(() => {\n if (footerState === 'done' && open) {\n const timer = setTimeout(() => {\n if (confettiRef.current) {\n void confettiRef.current.fire();\n }\n }, 200);\n\n return () => {\n clearTimeout(timer);\n };\n }\n }, [footerState, open]);\n\n useEffect(() => {\n if (!open) {\n setFooterState('running');\n }\n }, [open]);\n\n return (\n <div className=\"flex h-[50vh] w-[calc(100vw/2)] items-center justify-center rounded-16 bg-background-subtle-base shadow-tooltip\">\n <Confetti\n ref={confettiRef}\n manualstart\n options={{\n particleCount: 200,\n spread: 100,\n colors: ['#ff6b6b', '#4ecdc4', '#ffe66d', '#95e1d3'],\n }}\n className=\"fixed inset-0 pointer-events-none z-100\"\n style={{width: '100%', height: '100%'}}\n />\n <Modal open={open} onOpenChange={setOpen}>\n <ModalTrigger asChild>\n <Button>Run GitHub Actions on Shipfox</Button>\n </ModalTrigger>\n <ModalContent aria-describedby={undefined} overlayClassName=\"bg-background-modal-overlay\">\n <ModalTitle className=\"sr-only\">Run GitHub Actions on Shipfox</ModalTitle>\n <ModalHeader title=\"Run GitHub Actions on Shipfox\" />\n <ModalBody className=\"gap-32\">\n <div className=\"flex flex-col gap-20 w-full\">\n <Text size=\"sm\" className=\"text-foreground-neutral-subtle w-full\">\n This will run your jobs on Shipfox's optimized infrastructure. Giving you\n faster builds, and dedicated resources.\n </Text>\n <div className=\"relative\">\n <img\n src={illustration2}\n alt=\"illustration-2\"\n className=\"hidden sm:block absolute overflow-clip right-2 top-1/2 -translate-y-1/2 translate-x-8 w-fit object-contain z-50\"\n />\n <div className={cn('relative overflow-hidden bg-transparent p-1 rounded-8')}>\n <div className=\"absolute inset-0\" style={{borderRadius: 'calc(0.5rem * 0.96)'}}>\n <MovingBorder duration={6000} rx=\"30%\" ry=\"30%\">\n <div className=\"h-100 w-200 bg-[radial-gradient(#ff9e7a_40%,transparent_60%)]\" />\n </MovingBorder>\n </div>\n <div\n className=\"relative\"\n style={{\n borderRadius: 'calc(0.5rem * 0.96)',\n }}\n >\n <DynamicItem\n variant=\"default\"\n title={\n <div className=\"flex items-center gap-6\">\n <span className=\"flex shrink-0 items-center justify-center text-tag-success-icon w-16 h-16\">\n <Icon\n name=\"money\"\n size=\"sm\"\n color=\"var(--foreground-neutral-subtle, #a1a1aa)\"\n />\n </span>\n <ItemTitle>6000 free credits/month to run your jobs</ItemTitle>\n </div>\n }\n description=\"~500 builds/month. No payment required.\"\n rightElement={\n <img\n src={illustrationBg}\n alt=\"illustration-bg\"\n className=\"hidden sm:block absolute overflow-clip right-4 w-fit object-contain scale-105\"\n />\n }\n />\n </div>\n </div>\n </div>\n </div>\n <div className=\"flex flex-col gap-20 w-full\">\n <div className=\"flex flex-col gap-6\">\n <div className=\"flex items-center justify-center w-full\">\n <Text className=\"flex-1 font-semibold text-foreground-neutral-base overflow-ellipsis overflow-hidden whitespace-nowrap\">\n Update your GitHub Actions workflow\n </Text>\n <ButtonLink variant=\"base\" size=\"sm\" href=\"#\" iconRight=\"bookOpen\">\n See docs\n </ButtonLink>\n </div>\n <Text size=\"sm\" className=\"text-foreground-neutral-subtle w-full\">\n Replace the runs-on line in your workflow file to use Shipfox runners.\n </Text>\n </div>\n\n <CodeBlock\n data={[\n {\n language: 'yaml',\n filename: '.github/workflows/<workflow-name>.yml',\n code: diffCode,\n },\n ]}\n defaultValue=\"yaml\"\n >\n <CodeBlockHeader>\n <CodeBlockFiles>\n {(item) => (\n <CodeBlockFilename value={item.language}>{item.filename}</CodeBlockFilename>\n )}\n </CodeBlockFiles>\n <CodeBlockCopyButton />\n </CodeBlockHeader>\n <CodeBlockBody>\n {(item) => (\n <CodeBlockItem value={item.language}>\n <CodeBlockContent language={item.language}>{item.code}</CodeBlockContent>\n </CodeBlockItem>\n )}\n </CodeBlockBody>\n <CodeBlockFooter\n state={footerState}\n message={\n footerState === 'running'\n ? 'Waiting for Shipfox runner event…'\n : 'Runners connected!'\n }\n description={\n footerState === 'running'\n ? 'This usually takes 30-60 seconds after you commit the workflow file.'\n : ''\n }\n />\n </CodeBlock>\n </div>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"primary\" onClick={() => setOpen(false)}>\n Got it\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n </div>\n );\n },\n};\n\nexport const OpenedModal: Story = {\n play: async (ctx) => {\n const {canvasElement, step} = ctx;\n const canvas = within(canvasElement);\n const user = userEvent.setup();\n\n await step('Open the modal', async () => {\n const triggerButton = canvas.getByRole('button', {name: OPEN_MODAL_REGEX});\n await user.click(triggerButton);\n });\n\n await step('Wait for dialog to appear and render', async () => {\n await screen.findByRole('dialog');\n await new Promise((resolve) => setTimeout(resolve, 100));\n });\n\n await argosScreenshot(ctx, 'Opened Modal State');\n },\n render: () => {\n const [open, setOpen] = useState(false);\n\n return (\n <div className=\"flex h-[calc(100vh/2)] w-[calc(100vw/2)] items-center justify-center rounded-16 bg-background-subtle-base shadow-tooltip\">\n <Modal open={open} onOpenChange={setOpen}>\n <ModalTrigger asChild>\n <Button>Open Modal</Button>\n </ModalTrigger>\n <ModalContent aria-describedby={undefined}>\n <ModalTitle className=\"sr-only\">Modal Title</ModalTitle>\n <ModalHeader>\n <Text\n size=\"lg\"\n className=\"flex-1 overflow-ellipsis overflow-hidden whitespace-nowrap\"\n >\n Modal Title\n </Text>\n </ModalHeader>\n <ModalBody>\n <Text size=\"sm\" className=\"text-foreground-neutral-subtle w-full\">\n This modal automatically adapts between dialog (desktop) and drawer (mobile) based\n on screen size. Try resizing your browser window!\n </Text>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"transparent\" onClick={() => setOpen(false)}>\n Cancel\n </Button>\n <Button variant=\"primary\" onClick={() => setOpen(false)}>\n Confirm\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n </div>\n );\n },\n};\n"],"names":["argosScreenshot","screen","within","userEvent","Button","ButtonLink","CodeBlock","CodeBlockBody","CodeBlockContent","CodeBlockCopyButton","CodeBlockFilename","CodeBlockFiles","CodeBlockFooter","CodeBlockHeader","CodeBlockItem","Confetti","DatePicker","DynamicItem","Icon","Input","ItemTitle","Label","MovingBorder","Text","useEffect","useRef","useState","cn","illustration2","illustrationBg","Modal","ModalBody","ModalContent","ModalFooter","ModalHeader","ModalTitle","ModalTrigger","OPEN_MODAL_REGEX","IMPORT_JOBS_REGEX","GITHUB_ACTIONS_REGEX","DEFAULT_START_DATE","Date","meta","title","component","tags","parameters","layout","Default","play","ctx","canvasElement","step","canvas","user","setup","triggerButton","getByRole","name","click","findByRole","Promise","resolve","setTimeout","render","open","setOpen","div","className","onOpenChange","asChild","aria-describedby","undefined","size","variant","onClick","ImportForm","date","setDate","overlayClassName","placeholder","htmlFor","id","onDateSelect","onClear","diffCode","GithubActions","viewport","defaultViewport","footerState","setFooterState","confettiRef","timer","clearTimeout","current","fire","ref","manualstart","options","particleCount","spread","colors","style","width","height","img","src","alt","borderRadius","duration","rx","ry","span","color","description","rightElement","href","iconRight","data","language","filename","code","defaultValue","item","value","state","message","OpenedModal"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/shiny-text/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/shiny-text/index.ts"],"sourcesContent":["export * from './shiny-text';\n"],"names":[],"mappings":"AAAA,cAAc,eAAe"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type ShinyTextProps = {
|
|
2
|
+
text: string;
|
|
3
|
+
disabled?: boolean;
|
|
4
|
+
speed?: number;
|
|
5
|
+
className?: string;
|
|
6
|
+
};
|
|
7
|
+
declare function ShinyText({ text, disabled, speed, className }: ShinyTextProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export { ShinyText };
|
|
9
|
+
export type { ShinyTextProps };
|
|
10
|
+
//# sourceMappingURL=shiny-text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shiny-text.d.ts","sourceRoot":"","sources":["../../../src/components/shiny-text/shiny-text.tsx"],"names":[],"mappings":"AAEA,KAAK,cAAc,GAAG;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,iBAAS,SAAS,CAAC,EAAC,IAAI,EAAE,QAAgB,EAAE,KAAS,EAAE,SAAc,EAAC,EAAE,cAAc,2CAQrF;AAED,OAAO,EAAC,SAAS,EAAC,CAAC;AACnB,YAAY,EAAC,cAAc,EAAC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from '../../utils/cn.js';
|
|
3
|
+
function ShinyText({ text, disabled = false, speed = 5, className = '' }) {
|
|
4
|
+
const animationDuration = `${speed}s`;
|
|
5
|
+
return /*#__PURE__*/ _jsx("span", {
|
|
6
|
+
className: cn('shiny-text', {
|
|
7
|
+
disabled: disabled
|
|
8
|
+
}, className),
|
|
9
|
+
style: {
|
|
10
|
+
animationDuration
|
|
11
|
+
},
|
|
12
|
+
children: text
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export { ShinyText };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=shiny-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/shiny-text/shiny-text.tsx"],"sourcesContent":["import {cn} from 'utils/cn';\n\ntype ShinyTextProps = {\n text: string;\n disabled?: boolean;\n speed?: number;\n className?: string;\n};\n\nfunction ShinyText({text, disabled = false, speed = 5, className = ''}: ShinyTextProps) {\n const animationDuration = `${speed}s`;\n\n return (\n <span className={cn('shiny-text', {disabled: disabled}, className)} style={{animationDuration}}>\n {text}\n </span>\n );\n}\n\nexport {ShinyText};\nexport type {ShinyTextProps};\n"],"names":["cn","ShinyText","text","disabled","speed","className","animationDuration","span","style"],"mappings":";AAAA,SAAQA,EAAE,QAAO,WAAW;AAS5B,SAASC,UAAU,EAACC,IAAI,EAAEC,WAAW,KAAK,EAAEC,QAAQ,CAAC,EAAEC,YAAY,EAAE,EAAiB;IACpF,MAAMC,oBAAoB,GAAGF,MAAM,CAAC,CAAC;IAErC,qBACE,KAACG;QAAKF,WAAWL,GAAG,cAAc;YAACG,UAAUA;QAAQ,GAAGE;QAAYG,OAAO;YAACF;QAAiB;kBAC1FJ;;AAGP;AAEA,SAAQD,SAAS,GAAE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/tabs/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/tabs/index.ts"],"sourcesContent":["export * from './tabs';\n"],"names":[],"mappings":"AAAA,cAAc,SAAS"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type HTMLMotionProps, type Transition } from 'framer-motion';
|
|
2
|
+
import { type ComponentProps, type ReactNode } from 'react';
|
|
3
|
+
type TabsContextType<T extends string = string> = {
|
|
4
|
+
activeValue: T;
|
|
5
|
+
handleValueChange: (value: T) => void;
|
|
6
|
+
registerTrigger: (value: string, node: HTMLElement | null) => void;
|
|
7
|
+
getTriggerElement: (value: string) => HTMLElement | undefined;
|
|
8
|
+
getAllTriggerValues: () => string[];
|
|
9
|
+
};
|
|
10
|
+
declare function useTabs<T extends string = string>(): TabsContextType<T>;
|
|
11
|
+
type BaseTabsProps = ComponentProps<'div'> & {
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
};
|
|
14
|
+
type UnControlledTabsProps<T extends string = string> = BaseTabsProps & {
|
|
15
|
+
defaultValue?: T;
|
|
16
|
+
value?: never;
|
|
17
|
+
onValueChange?: never;
|
|
18
|
+
};
|
|
19
|
+
type ControlledTabsProps<T extends string = string> = BaseTabsProps & {
|
|
20
|
+
value: T;
|
|
21
|
+
onValueChange?: (value: T) => void;
|
|
22
|
+
defaultValue?: never;
|
|
23
|
+
};
|
|
24
|
+
type TabsProps<T extends string = string> = UnControlledTabsProps<T> | ControlledTabsProps<T>;
|
|
25
|
+
declare function Tabs<T extends string = string>({ defaultValue, value, onValueChange, children, className, ...props }: TabsProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
type TabsListProps = ComponentProps<'div'> & {
|
|
27
|
+
children: ReactNode;
|
|
28
|
+
activeClassName?: string;
|
|
29
|
+
transition?: Transition;
|
|
30
|
+
};
|
|
31
|
+
declare function TabsList({ children, className, activeClassName, transition, ...props }: TabsListProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
type TabsTriggerProps = Omit<HTMLMotionProps<'button'>, 'ref'> & {
|
|
33
|
+
value: string;
|
|
34
|
+
children: ReactNode;
|
|
35
|
+
};
|
|
36
|
+
declare const TabsTrigger: import("react").ForwardRefExoticComponent<Omit<HTMLMotionProps<"button">, "ref"> & {
|
|
37
|
+
value: string;
|
|
38
|
+
children: ReactNode;
|
|
39
|
+
} & import("react").RefAttributes<HTMLButtonElement>>;
|
|
40
|
+
type TabsContentsProps = ComponentProps<'div'> & {
|
|
41
|
+
children: ReactNode;
|
|
42
|
+
};
|
|
43
|
+
declare function TabsContents({ children, className, ...props }: TabsContentsProps): import("react/jsx-runtime").JSX.Element;
|
|
44
|
+
type TabsContentProps = ComponentProps<'div'> & {
|
|
45
|
+
value: string;
|
|
46
|
+
children: ReactNode;
|
|
47
|
+
};
|
|
48
|
+
declare function TabsContent({ children, value, className, ...props }: TabsContentProps): import("react/jsx-runtime").JSX.Element | null;
|
|
49
|
+
export { Tabs, TabsList, TabsTrigger, TabsContents, TabsContent, useTabs, type TabsContextType, type TabsProps, type TabsListProps, type TabsTriggerProps, type TabsContentsProps, type TabsContentProps, };
|
|
50
|
+
//# sourceMappingURL=tabs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../src/components/tabs/tabs.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { motion } from 'framer-motion';
|
|
3
|
+
import { Children, createContext, forwardRef, isValidElement, useCallback, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import { cn } from '../../utils/cn.js';
|
|
5
|
+
import { debounce } from '../../utils/debounce.js';
|
|
6
|
+
const TabsContext = /*#__PURE__*/ createContext(undefined);
|
|
7
|
+
function useTabs() {
|
|
8
|
+
const context = useContext(TabsContext);
|
|
9
|
+
if (!context) {
|
|
10
|
+
throw new Error('useTabs must be used within a Tabs component');
|
|
11
|
+
}
|
|
12
|
+
return context;
|
|
13
|
+
}
|
|
14
|
+
function Tabs({ defaultValue, value, onValueChange, children, className, ...props }) {
|
|
15
|
+
const [activeValue, setActiveValue] = useState(defaultValue ?? undefined);
|
|
16
|
+
const triggersRef = useRef(new Map());
|
|
17
|
+
const initialSet = useRef(false);
|
|
18
|
+
const isControlled = value !== undefined;
|
|
19
|
+
useEffect(()=>{
|
|
20
|
+
if (!isControlled && activeValue === undefined && triggersRef.current.size > 0 && !initialSet.current) {
|
|
21
|
+
const firstTab = Array.from(triggersRef.current.keys())[0];
|
|
22
|
+
setActiveValue(firstTab);
|
|
23
|
+
initialSet.current = true;
|
|
24
|
+
}
|
|
25
|
+
}, [
|
|
26
|
+
activeValue,
|
|
27
|
+
isControlled
|
|
28
|
+
]);
|
|
29
|
+
const registerTrigger = useCallback((value, node)=>{
|
|
30
|
+
if (node) {
|
|
31
|
+
triggersRef.current.set(value, node);
|
|
32
|
+
if (!isControlled && activeValue === undefined && !initialSet.current) {
|
|
33
|
+
setActiveValue(value);
|
|
34
|
+
initialSet.current = true;
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
triggersRef.current.delete(value);
|
|
38
|
+
}
|
|
39
|
+
}, [
|
|
40
|
+
isControlled,
|
|
41
|
+
activeValue
|
|
42
|
+
]);
|
|
43
|
+
const handleValueChange = useCallback((val)=>{
|
|
44
|
+
if (!isControlled) setActiveValue(val);
|
|
45
|
+
else onValueChange?.(val);
|
|
46
|
+
}, [
|
|
47
|
+
isControlled,
|
|
48
|
+
onValueChange
|
|
49
|
+
]);
|
|
50
|
+
const getTriggerElement = useCallback((val)=>{
|
|
51
|
+
return triggersRef.current.get(val);
|
|
52
|
+
}, []);
|
|
53
|
+
const getAllTriggerValues = useCallback(()=>{
|
|
54
|
+
return Array.from(triggersRef.current.keys());
|
|
55
|
+
}, []);
|
|
56
|
+
const resolvedActiveValue = useMemo(()=>{
|
|
57
|
+
if (value !== undefined) return value;
|
|
58
|
+
if (activeValue !== undefined) return activeValue;
|
|
59
|
+
const firstKey = Array.from(triggersRef.current.keys())[0];
|
|
60
|
+
return firstKey ?? '';
|
|
61
|
+
}, [
|
|
62
|
+
value,
|
|
63
|
+
activeValue
|
|
64
|
+
]);
|
|
65
|
+
return /*#__PURE__*/ _jsx(TabsContext.Provider, {
|
|
66
|
+
value: {
|
|
67
|
+
activeValue: resolvedActiveValue,
|
|
68
|
+
handleValueChange: handleValueChange,
|
|
69
|
+
registerTrigger,
|
|
70
|
+
getTriggerElement,
|
|
71
|
+
getAllTriggerValues
|
|
72
|
+
},
|
|
73
|
+
children: /*#__PURE__*/ _jsx("div", {
|
|
74
|
+
"data-slot": "tabs",
|
|
75
|
+
className: cn('flex flex-col gap-2', className),
|
|
76
|
+
...props,
|
|
77
|
+
children: children
|
|
78
|
+
})
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function TabsList({ children, className, activeClassName, transition = {
|
|
82
|
+
type: 'spring',
|
|
83
|
+
stiffness: 400,
|
|
84
|
+
damping: 30
|
|
85
|
+
}, ...props }) {
|
|
86
|
+
const { activeValue, getTriggerElement } = useTabs();
|
|
87
|
+
const [indicatorStyle, setIndicatorStyle] = useState(null);
|
|
88
|
+
const listRef = useRef(null);
|
|
89
|
+
const updateIndicator = useCallback(()=>{
|
|
90
|
+
const activeTrigger = getTriggerElement(activeValue);
|
|
91
|
+
if (activeTrigger && listRef.current) {
|
|
92
|
+
const listRect = listRef.current.getBoundingClientRect();
|
|
93
|
+
const triggerRect = activeTrigger.getBoundingClientRect();
|
|
94
|
+
setIndicatorStyle({
|
|
95
|
+
left: triggerRect.left - listRect.left,
|
|
96
|
+
width: triggerRect.width
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}, [
|
|
100
|
+
activeValue,
|
|
101
|
+
getTriggerElement
|
|
102
|
+
]);
|
|
103
|
+
useEffect(()=>{
|
|
104
|
+
const debouncedUpdate = debounce(updateIndicator, 100);
|
|
105
|
+
window.addEventListener('resize', debouncedUpdate);
|
|
106
|
+
requestAnimationFrame(updateIndicator);
|
|
107
|
+
return ()=>{
|
|
108
|
+
window.removeEventListener('resize', debouncedUpdate);
|
|
109
|
+
};
|
|
110
|
+
}, [
|
|
111
|
+
updateIndicator
|
|
112
|
+
]);
|
|
113
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
114
|
+
ref: listRef,
|
|
115
|
+
role: "tablist",
|
|
116
|
+
"data-slot": "tabs-list",
|
|
117
|
+
className: cn('relative inline-flex items-center gap-8', className),
|
|
118
|
+
...props,
|
|
119
|
+
children: [
|
|
120
|
+
children,
|
|
121
|
+
indicatorStyle && /*#__PURE__*/ _jsx(motion.div, {
|
|
122
|
+
className: cn('absolute bottom-0 h-2 bg-foreground-highlight-interactive', activeClassName),
|
|
123
|
+
initial: false,
|
|
124
|
+
animate: {
|
|
125
|
+
left: indicatorStyle.left,
|
|
126
|
+
width: indicatorStyle.width
|
|
127
|
+
},
|
|
128
|
+
transition: transition
|
|
129
|
+
})
|
|
130
|
+
]
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
const TabsTrigger = /*#__PURE__*/ forwardRef(({ value, children, className, onKeyDown, ...props }, ref)=>{
|
|
134
|
+
const { activeValue, handleValueChange, registerTrigger, getAllTriggerValues, getTriggerElement } = useTabs();
|
|
135
|
+
const localRef = useRef(null);
|
|
136
|
+
useImperativeHandle(ref, ()=>localRef.current);
|
|
137
|
+
useEffect(()=>{
|
|
138
|
+
registerTrigger(value, localRef.current);
|
|
139
|
+
return ()=>registerTrigger(value, null);
|
|
140
|
+
}, [
|
|
141
|
+
value,
|
|
142
|
+
registerTrigger
|
|
143
|
+
]);
|
|
144
|
+
const isActive = activeValue === value;
|
|
145
|
+
const handleKeyDown = useCallback((event)=>{
|
|
146
|
+
onKeyDown?.(event);
|
|
147
|
+
const allValues = getAllTriggerValues();
|
|
148
|
+
const currentIndex = allValues.indexOf(value);
|
|
149
|
+
if (currentIndex === -1) return;
|
|
150
|
+
let targetIndex = currentIndex;
|
|
151
|
+
let shouldPreventDefault = true;
|
|
152
|
+
switch(event.key){
|
|
153
|
+
case 'ArrowLeft':
|
|
154
|
+
{
|
|
155
|
+
targetIndex = currentIndex > 0 ? currentIndex - 1 : allValues.length - 1;
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
case 'ArrowRight':
|
|
159
|
+
{
|
|
160
|
+
targetIndex = currentIndex < allValues.length - 1 ? currentIndex + 1 : 0;
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
case 'Home':
|
|
164
|
+
{
|
|
165
|
+
targetIndex = 0;
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
case 'End':
|
|
169
|
+
{
|
|
170
|
+
targetIndex = allValues.length - 1;
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
default:
|
|
174
|
+
{
|
|
175
|
+
shouldPreventDefault = false;
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (shouldPreventDefault) {
|
|
180
|
+
event.preventDefault();
|
|
181
|
+
const targetValue = allValues[targetIndex];
|
|
182
|
+
if (targetValue) {
|
|
183
|
+
handleValueChange(targetValue);
|
|
184
|
+
const targetElement = getTriggerElement(targetValue);
|
|
185
|
+
targetElement?.focus();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}, [
|
|
189
|
+
value,
|
|
190
|
+
getAllTriggerValues,
|
|
191
|
+
getTriggerElement,
|
|
192
|
+
handleValueChange,
|
|
193
|
+
onKeyDown
|
|
194
|
+
]);
|
|
195
|
+
return /*#__PURE__*/ _jsx(motion.button, {
|
|
196
|
+
ref: localRef,
|
|
197
|
+
"data-slot": "tabs-trigger",
|
|
198
|
+
role: "tab",
|
|
199
|
+
tabIndex: isActive ? 0 : -1,
|
|
200
|
+
whileTap: {
|
|
201
|
+
scale: 0.95
|
|
202
|
+
},
|
|
203
|
+
onClick: ()=>handleValueChange(value),
|
|
204
|
+
onKeyDown: handleKeyDown,
|
|
205
|
+
"data-state": isActive ? 'active' : 'inactive',
|
|
206
|
+
"aria-selected": isActive,
|
|
207
|
+
"aria-controls": `tabpanel-${value}`,
|
|
208
|
+
id: `tab-${value}`,
|
|
209
|
+
className: cn('relative inline-flex cursor-pointer items-center justify-center whitespace-nowrap px-0 py-10 text-sm font-medium transition-colors outline-none focus-visible:shadow-border-interactive-with-active focus-visible:rounded-2 disabled:pointer-events-none disabled:opacity-50', isActive ? 'text-foreground-neutral-base' : 'text-foreground-neutral-muted', className),
|
|
210
|
+
...props,
|
|
211
|
+
children: children
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
TabsTrigger.displayName = 'TabsTrigger';
|
|
215
|
+
function TabsContents({ children, className, ...props }) {
|
|
216
|
+
const { activeValue } = useTabs();
|
|
217
|
+
const childrenArray = Children.toArray(children);
|
|
218
|
+
const activeChild = childrenArray.find((child)=>/*#__PURE__*/ isValidElement(child) && typeof child.props === 'object' && child.props !== null && 'value' in child.props && child.props.value === activeValue);
|
|
219
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
220
|
+
"data-slot": "tabs-contents",
|
|
221
|
+
className: cn(className),
|
|
222
|
+
...props,
|
|
223
|
+
children: activeChild
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
function TabsContent({ children, value, className, ...props }) {
|
|
227
|
+
const { activeValue } = useTabs();
|
|
228
|
+
const isActive = activeValue === value;
|
|
229
|
+
if (!isActive) {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
233
|
+
role: "tabpanel",
|
|
234
|
+
"data-slot": "tabs-content",
|
|
235
|
+
"aria-labelledby": `tab-${value}`,
|
|
236
|
+
className: cn(className),
|
|
237
|
+
...props,
|
|
238
|
+
children: children
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
export { Tabs, TabsList, TabsTrigger, TabsContents, TabsContent, useTabs };
|
|
242
|
+
|
|
243
|
+
//# sourceMappingURL=tabs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/tabs/tabs.tsx"],"sourcesContent":["import {type HTMLMotionProps, motion, type Transition} from 'framer-motion';\nimport {\n Children,\n type ComponentProps,\n createContext,\n forwardRef,\n isValidElement,\n type ReactElement,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport {cn} from 'utils/cn';\nimport {debounce} from 'utils/debounce';\n\ntype TabsContextType<T extends string = string> = {\n activeValue: T;\n handleValueChange: (value: T) => void;\n registerTrigger: (value: string, node: HTMLElement | null) => void;\n getTriggerElement: (value: string) => HTMLElement | undefined;\n getAllTriggerValues: () => string[];\n};\n\nconst TabsContext = createContext<TabsContextType<string> | undefined>(undefined);\n\nfunction useTabs<T extends string = string>(): TabsContextType<T> {\n const context = useContext(TabsContext);\n if (!context) {\n throw new Error('useTabs must be used within a Tabs component');\n }\n return context as unknown as TabsContextType<T>;\n}\n\ntype BaseTabsProps = ComponentProps<'div'> & {\n children: ReactNode;\n};\n\ntype UnControlledTabsProps<T extends string = string> = BaseTabsProps & {\n defaultValue?: T;\n value?: never;\n onValueChange?: never;\n};\n\ntype ControlledTabsProps<T extends string = string> = BaseTabsProps & {\n value: T;\n onValueChange?: (value: T) => void;\n defaultValue?: never;\n};\n\ntype TabsProps<T extends string = string> = UnControlledTabsProps<T> | ControlledTabsProps<T>;\n\nfunction Tabs<T extends string = string>({\n defaultValue,\n value,\n onValueChange,\n children,\n className,\n ...props\n}: TabsProps<T>) {\n const [activeValue, setActiveValue] = useState<T | undefined>(defaultValue ?? undefined);\n const triggersRef = useRef(new Map<string, HTMLElement>());\n const initialSet = useRef(false);\n const isControlled = value !== undefined;\n\n useEffect(() => {\n if (\n !isControlled &&\n activeValue === undefined &&\n triggersRef.current.size > 0 &&\n !initialSet.current\n ) {\n const firstTab = Array.from(triggersRef.current.keys())[0];\n setActiveValue(firstTab as T);\n initialSet.current = true;\n }\n }, [activeValue, isControlled]);\n\n const registerTrigger = useCallback(\n (value: string, node: HTMLElement | null) => {\n if (node) {\n triggersRef.current.set(value, node);\n if (!isControlled && activeValue === undefined && !initialSet.current) {\n setActiveValue(value as T);\n initialSet.current = true;\n }\n } else {\n triggersRef.current.delete(value);\n }\n },\n [isControlled, activeValue],\n );\n\n const handleValueChange = useCallback(\n (val: T) => {\n if (!isControlled) setActiveValue(val);\n else onValueChange?.(val);\n },\n [isControlled, onValueChange],\n );\n\n const getTriggerElement = useCallback((val: string) => {\n return triggersRef.current.get(val);\n }, []);\n\n const getAllTriggerValues = useCallback(() => {\n return Array.from(triggersRef.current.keys());\n }, []);\n\n const resolvedActiveValue: T = useMemo(() => {\n if (value !== undefined) return value;\n if (activeValue !== undefined) return activeValue;\n const firstKey = Array.from(triggersRef.current.keys())[0];\n return (firstKey ?? '') as T;\n }, [value, activeValue]);\n\n return (\n <TabsContext.Provider\n value={{\n activeValue: resolvedActiveValue as string,\n handleValueChange: handleValueChange as (value: string) => void,\n registerTrigger,\n getTriggerElement,\n getAllTriggerValues,\n }}\n >\n <div\n data-slot=\"tabs\"\n className={cn('flex flex-col gap-2', className)}\n {...(props as ComponentProps<'div'>)}\n >\n {children}\n </div>\n </TabsContext.Provider>\n );\n}\n\ntype TabsListProps = ComponentProps<'div'> & {\n children: ReactNode;\n activeClassName?: string;\n transition?: Transition;\n};\n\nfunction TabsList({\n children,\n className,\n activeClassName,\n transition = {\n type: 'spring',\n stiffness: 400,\n damping: 30,\n },\n ...props\n}: TabsListProps) {\n const {activeValue, getTriggerElement} = useTabs();\n const [indicatorStyle, setIndicatorStyle] = useState<{\n left: number;\n width: number;\n } | null>(null);\n const listRef = useRef<HTMLDivElement>(null);\n\n const updateIndicator = useCallback(() => {\n const activeTrigger = getTriggerElement(activeValue);\n\n if (activeTrigger && listRef.current) {\n const listRect = listRef.current.getBoundingClientRect();\n const triggerRect = activeTrigger.getBoundingClientRect();\n setIndicatorStyle({\n left: triggerRect.left - listRect.left,\n width: triggerRect.width,\n });\n }\n }, [activeValue, getTriggerElement]);\n\n useEffect(() => {\n const debouncedUpdate = debounce(updateIndicator, 100);\n window.addEventListener('resize', debouncedUpdate);\n requestAnimationFrame(updateIndicator);\n\n return () => {\n window.removeEventListener('resize', debouncedUpdate);\n };\n }, [updateIndicator]);\n\n return (\n <div\n ref={listRef}\n role=\"tablist\"\n data-slot=\"tabs-list\"\n className={cn('relative inline-flex items-center gap-8', className)}\n {...(props as ComponentProps<'div'>)}\n >\n {children}\n {indicatorStyle && (\n <motion.div\n className={cn(\n 'absolute bottom-0 h-2 bg-foreground-highlight-interactive',\n activeClassName,\n )}\n initial={false}\n animate={{\n left: indicatorStyle.left,\n width: indicatorStyle.width,\n }}\n transition={transition}\n />\n )}\n </div>\n );\n}\n\ntype TabsTriggerProps = Omit<HTMLMotionProps<'button'>, 'ref'> & {\n value: string;\n children: ReactNode;\n};\n\nconst TabsTrigger = forwardRef<HTMLButtonElement, TabsTriggerProps>(\n ({value, children, className, onKeyDown, ...props}, ref) => {\n const {\n activeValue,\n handleValueChange,\n registerTrigger,\n getAllTriggerValues,\n getTriggerElement,\n } = useTabs();\n\n const localRef = useRef<HTMLButtonElement | null>(null);\n useImperativeHandle(ref, () => localRef.current as HTMLButtonElement);\n\n useEffect(() => {\n registerTrigger(value, localRef.current);\n return () => registerTrigger(value, null);\n }, [value, registerTrigger]);\n\n const isActive = activeValue === value;\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLButtonElement>) => {\n onKeyDown?.(event);\n\n const allValues = getAllTriggerValues();\n const currentIndex = allValues.indexOf(value);\n\n if (currentIndex === -1) return;\n\n let targetIndex = currentIndex;\n let shouldPreventDefault = true;\n\n switch (event.key) {\n case 'ArrowLeft': {\n targetIndex = currentIndex > 0 ? currentIndex - 1 : allValues.length - 1;\n break;\n }\n case 'ArrowRight': {\n targetIndex = currentIndex < allValues.length - 1 ? currentIndex + 1 : 0;\n break;\n }\n case 'Home': {\n targetIndex = 0;\n break;\n }\n case 'End': {\n targetIndex = allValues.length - 1;\n break;\n }\n default: {\n shouldPreventDefault = false;\n return;\n }\n }\n\n if (shouldPreventDefault) {\n event.preventDefault();\n const targetValue = allValues[targetIndex];\n if (targetValue) {\n handleValueChange(targetValue);\n const targetElement = getTriggerElement(targetValue);\n targetElement?.focus();\n }\n }\n },\n [value, getAllTriggerValues, getTriggerElement, handleValueChange, onKeyDown],\n );\n\n return (\n <motion.button\n ref={localRef}\n data-slot=\"tabs-trigger\"\n role=\"tab\"\n tabIndex={isActive ? 0 : -1}\n whileTap={{scale: 0.95}}\n onClick={() => handleValueChange(value)}\n onKeyDown={handleKeyDown}\n data-state={isActive ? 'active' : 'inactive'}\n aria-selected={isActive}\n aria-controls={`tabpanel-${value}`}\n id={`tab-${value}`}\n className={cn(\n 'relative inline-flex cursor-pointer items-center justify-center whitespace-nowrap px-0 py-10 text-sm font-medium transition-colors outline-none focus-visible:shadow-border-interactive-with-active focus-visible:rounded-2 disabled:pointer-events-none disabled:opacity-50',\n isActive ? 'text-foreground-neutral-base' : 'text-foreground-neutral-muted',\n className,\n )}\n {...props}\n >\n {children}\n </motion.button>\n );\n },\n);\n\nTabsTrigger.displayName = 'TabsTrigger';\n\ntype TabsContentsProps = ComponentProps<'div'> & {\n children: ReactNode;\n};\n\nfunction TabsContents({children, className, ...props}: TabsContentsProps) {\n const {activeValue} = useTabs();\n const childrenArray = Children.toArray(children);\n\n const activeChild = childrenArray.find(\n (child): child is ReactElement<{value: string}> =>\n isValidElement(child) &&\n typeof child.props === 'object' &&\n child.props !== null &&\n 'value' in child.props &&\n child.props.value === activeValue,\n );\n\n return (\n <div data-slot=\"tabs-contents\" className={cn(className)} {...(props as ComponentProps<'div'>)}>\n {activeChild}\n </div>\n );\n}\n\ntype TabsContentProps = ComponentProps<'div'> & {\n value: string;\n children: ReactNode;\n};\n\nfunction TabsContent({children, value, className, ...props}: TabsContentProps) {\n const {activeValue} = useTabs();\n const isActive = activeValue === value;\n\n if (!isActive) {\n return null;\n }\n\n return (\n <div\n role=\"tabpanel\"\n data-slot=\"tabs-content\"\n aria-labelledby={`tab-${value}`}\n className={cn(className)}\n {...props}\n >\n {children}\n </div>\n );\n}\n\nexport {\n Tabs,\n TabsList,\n TabsTrigger,\n TabsContents,\n TabsContent,\n useTabs,\n type TabsContextType,\n type TabsProps,\n type TabsListProps,\n type TabsTriggerProps,\n type TabsContentsProps,\n type TabsContentProps,\n};\n"],"names":["motion","Children","createContext","forwardRef","isValidElement","useCallback","useContext","useEffect","useImperativeHandle","useMemo","useRef","useState","cn","debounce","TabsContext","undefined","useTabs","context","Error","Tabs","defaultValue","value","onValueChange","children","className","props","activeValue","setActiveValue","triggersRef","Map","initialSet","isControlled","current","size","firstTab","Array","from","keys","registerTrigger","node","set","delete","handleValueChange","val","getTriggerElement","get","getAllTriggerValues","resolvedActiveValue","firstKey","Provider","div","data-slot","TabsList","activeClassName","transition","type","stiffness","damping","indicatorStyle","setIndicatorStyle","listRef","updateIndicator","activeTrigger","listRect","getBoundingClientRect","triggerRect","left","width","debouncedUpdate","window","addEventListener","requestAnimationFrame","removeEventListener","ref","role","initial","animate","TabsTrigger","onKeyDown","localRef","isActive","handleKeyDown","event","allValues","currentIndex","indexOf","targetIndex","shouldPreventDefault","key","length","preventDefault","targetValue","targetElement","focus","button","tabIndex","whileTap","scale","onClick","data-state","aria-selected","aria-controls","id","displayName","TabsContents","childrenArray","toArray","activeChild","find","child","TabsContent","aria-labelledby"],"mappings":"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"}
|