snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-16 01:21:02 +05:00
commit 30810eecd7
10161 changed files with 987110 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
import type { SelectOption } from '@rocket.chat/fuselage';
import { Box, Field, FieldLabel, FieldRow, Select, Button } from '@rocket.chat/fuselage';
import { useId, useMemo } from 'react';
import { useForm, Controller } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
export type EditInviteLinkProps = {
daysAndMaxUses: { days: string; maxUses: string };
onClickNewLink: (daysAndMaxUses: { days: string; maxUses: string }) => void;
};
const EditInviteLink = ({ daysAndMaxUses, onClickNewLink }: EditInviteLinkProps) => {
const { t } = useTranslation();
const {
handleSubmit,
formState: { isDirty, isSubmitting },
control,
} = useForm({ defaultValues: { days: daysAndMaxUses.days, maxUses: daysAndMaxUses.maxUses } });
const expirationId = useId();
const maxUsesId = useId();
const daysOptions: SelectOption[] = useMemo(
() => [
['1', '1'],
['7', '7'],
['15', '15'],
['30', '30'],
['0', t('Never')],
],
[t],
);
const maxUsesOptions: SelectOption[] = useMemo(
() => [
['5', '5'],
['10', '10'],
['25', '25'],
['50', '50'],
['100', '100'],
['0', t('No_Limit')],
],
[t],
);
return (
<>
<Field>
<FieldLabel htmlFor={expirationId} flexGrow={0}>
{t('Expiration_(Days)')}
</FieldLabel>
<FieldRow>
<Controller
name='days'
control={control}
render={({ field: { onChange, value, name } }) => (
<Select id={expirationId} name={name} value={value} onChange={onChange} options={daysOptions} />
)}
/>
</FieldRow>
</Field>
<Field>
<FieldLabel htmlFor={maxUsesId} flexGrow={0}>
{t('Max_number_of_uses')}
</FieldLabel>
<FieldRow>
<Controller
name='maxUses'
control={control}
render={({ field: { onChange, value, name } }) => (
<Select id={maxUsesId} name={name} value={value} onChange={onChange} options={maxUsesOptions} />
)}
/>
</FieldRow>
</Field>
<Box marginBlockStart={8}>
<Button loading={isSubmitting} disabled={!isDirty} primary onClick={handleSubmit(onClickNewLink)}>
{t('Generate_New_Link')}
</Button>
</Box>
</>
);
};
export default EditInviteLink;

View File

@@ -0,0 +1,45 @@
import { Box, Field, FieldLabel, FieldRow, UrlInput, Icon, Button, InputBoxSkeleton } from '@rocket.chat/fuselage';
import { useId } from 'react';
import { useTranslation } from 'react-i18next';
import useClipboardWithToast from '../../../../../hooks/useClipboardWithToast';
export type InviteLinkProps = {
linkText: string;
captionText: string;
onClickEdit: () => void;
};
const InviteLink = ({ linkText, captionText, onClickEdit }: InviteLinkProps) => {
const { t } = useTranslation();
const { copy } = useClipboardWithToast(linkText);
const inviteLinkId = useId();
return (
<>
<Field>
<FieldLabel htmlFor={inviteLinkId} flexGrow={0}>
{t('Invite_Link')}
</FieldLabel>
<FieldRow>
{!linkText && <InputBoxSkeleton />}
{linkText && (
<UrlInput id={inviteLinkId} value={linkText} endAddon={<Icon onClick={(): Promise<void> => copy()} name='copy' size='x16' />} />
)}
</FieldRow>
{captionText && (
<Box paddingBlock={8} color='annotation' fontScale='c2'>
{captionText}
</Box>
)}
</Field>
{onClickEdit && (
<Box marginBlockStart={8}>
<Button onClick={onClickEdit}>{t('Edit_Invite')}</Button>
</Box>
)}
</>
);
};
export default InviteLink;

View File

@@ -0,0 +1,29 @@
import { composeStories } from '@storybook/react';
import { render } from '@testing-library/react';
import { axe } from 'jest-axe';
import * as stories from './InviteUsers.stories';
const testCases = Object.values(composeStories(stories)).map((Story) => [Story.storyName || 'Story', Story]);
beforeEach(() => {
jest.mock('react', () => ({
...jest.requireActual('react'),
useId: () => 1,
}));
});
test.each(testCases)(`renders %s without crashing`, async (_storyname, Story) => {
const view = render(<Story />);
expect(view.baseElement).toMatchSnapshot();
});
test.each(testCases)('%s should have no a11y violations', async (_storyname, Story) => {
const { container } = render(<Story />);
/**
** Disable 'nested-interactive' rule because our `Select` component is still not a11y compliant
**/
const results = await axe(container, { rules: { 'nested-interactive': { enabled: false } } });
expect(results).toHaveNoViolations();
});

View File

@@ -0,0 +1,50 @@
import { Box } from '@rocket.chat/fuselage';
import { mockAppRoot } from '@rocket.chat/mock-providers';
import type { StoryObj, Meta } from '@storybook/react';
import InviteUsers from './InviteUsers';
import InviteUsersEdit from './InviteUsersEdit';
import InviteUsersError from './InviteUsersError';
import InviteUsersLoading from './InviteUsersLoading';
import { links } from '../../../../../lib/links';
export default {
component: InviteUsers,
parameters: {
layout: 'fullscreen',
actions: { argTypesRegex: '^on.*' },
},
decorators: [
(fn) => <Box height='100vh'>{fn()}</Box>,
mockAppRoot()
.withTranslations('en', 'core', {
'Edit_Invite': 'Edit invite',
'Invite_Users': 'Invite users',
'Invite_Link': 'Invite link',
'Expiration_(Days)': 'Expiration (Days)',
'Max_number_of_uses': 'Max number of uses',
})
.buildStoryDecorator(),
],
} satisfies Meta<typeof InviteUsers>;
export const Default: StoryObj<typeof InviteUsers> = {
name: 'Invite Link',
args: {
linkText: links.go.invite,
captionText: 'Expire on February 4, 2020 4:45 PM.',
},
};
export const InviteEdit: StoryObj<typeof InviteUsersEdit> = {
render: (args) => <InviteUsersEdit {...args} daysAndMaxUses={{ days: '1', maxUses: '5' }} />,
};
export const InviteLoading: StoryObj<typeof InviteUsersLoading> = {
render: (args) => <InviteUsersLoading {...args} />,
};
export const InviteError: StoryObj<typeof InviteUsersError> = {
render: (args) => <InviteUsersError {...args} error={new Error('Error message')} />,
};

View File

@@ -0,0 +1,18 @@
import InviteLink from './InviteLink';
import InviteUsersWrapper from './InviteUsersWrapper';
export type InviteUsersProps = {
onClickBackMembers?: () => void;
onClose: () => void;
onClickEdit: () => void;
captionText: string;
linkText: string;
};
const InviteUsers = ({ onClickBackMembers, onClose, onClickEdit, captionText, linkText }: InviteUsersProps) => (
<InviteUsersWrapper onClickBack={onClickBackMembers} onClose={onClose}>
<InviteLink captionText={captionText} onClickEdit={onClickEdit} linkText={linkText} />
</InviteUsersWrapper>
);
export default InviteUsers;

View File

@@ -0,0 +1,19 @@
import EditInviteLink from './EditInviteLink';
import InviteUsersWrapper from './InviteUsersWrapper';
export type InviteUsersEditProps = {
onClickBackLink?: () => void;
onClickNewLink: (daysAndMaxUses: { days: string; maxUses: string }) => void;
onClose: () => void;
daysAndMaxUses: { days: string; maxUses: string };
};
const InviteUsersEdit = ({ onClickBackLink, onClickNewLink, onClose, daysAndMaxUses }: InviteUsersEditProps) => {
return (
<InviteUsersWrapper onClickBack={onClickBackLink} onClose={onClose}>
<EditInviteLink onClickNewLink={onClickNewLink} daysAndMaxUses={daysAndMaxUses} />
</InviteUsersWrapper>
);
};
export default InviteUsersEdit;

View File

@@ -0,0 +1,17 @@
import { Callout } from '@rocket.chat/fuselage';
import InviteUsersWrapper from './InviteUsersWrapper';
type InviteUsersProps = {
onClose: () => void;
error: Error;
onClickBack?: (() => void) | undefined;
};
const InviteUsersError = ({ onClose, error, onClickBack }: InviteUsersProps) => (
<InviteUsersWrapper onClose={onClose} onClickBack={onClickBack}>
<Callout type='danger'>{(error || '').toString()}</Callout>
</InviteUsersWrapper>
);
export default InviteUsersError;

View File

@@ -0,0 +1,16 @@
import { Skeleton } from '@rocket.chat/fuselage';
import InviteUsersWrapper from './InviteUsersWrapper';
type InviteUsersProps = {
onClose: () => void;
onClickBack: (() => void) | undefined;
};
const InviteUsersLoading = ({ onClose, onClickBack: onClickBackMembers }: InviteUsersProps) => (
<InviteUsersWrapper onClose={onClose} onClickBack={onClickBackMembers}>
<Skeleton width='full' />
</InviteUsersWrapper>
);
export default InviteUsersLoading;

View File

@@ -0,0 +1,127 @@
import type { IRoom } from '@rocket.chat/core-typings';
import { useStableCallback } from '@rocket.chat/fuselage-hooks';
import { useEndpoint, useTranslation, useToastMessageDispatch, useRoomToolbox } from '@rocket.chat/ui-contexts';
import { useQuery } from '@tanstack/react-query';
import { useState, useEffect } from 'react';
import InviteUsers from './InviteUsers';
import InviteUsersEdit from './InviteUsersEdit';
import InviteUsersError from './InviteUsersError';
import InviteUsersLoading from './InviteUsersLoading';
import { useFormatDateAndTime } from '../../../../../hooks/useFormatDateAndTime';
export type InviteUsersWithDataProps = {
rid: IRoom['_id'];
onClickBack: () => void;
};
const InviteUsersWithData = ({ rid, onClickBack }: InviteUsersWithDataProps) => {
const t = useTranslation();
const dispatchToastMessage = useToastMessageDispatch();
const [
{
isEditing,
daysAndMaxUses: { days, maxUses },
},
setInviteState,
] = useState({
isEditing: false,
daysAndMaxUses: { days: '1', maxUses: '0' },
});
const { closeTab } = useRoomToolbox();
const format = useFormatDateAndTime();
const findOrCreateInvite = useEndpoint('POST', '/v1/findOrCreateInvite');
const handleEdit = useStableCallback(() => setInviteState((prevState) => ({ ...prevState, isEditing: true })));
const handleBackToLink = useStableCallback(() => setInviteState((prevState) => ({ ...prevState, isEditing: false })));
const linkExpirationText = useStableCallback(
(data?: {
days: number;
maxUses: number;
rid: string;
userId: string;
createdAt: string;
expires: string | null;
uses: number;
url: string;
_id: string;
_updatedAt: string;
}) => {
if (!data) {
return '';
}
if (data.expires) {
const expiration = new Date(data.expires);
if (data.maxUses) {
const usesLeft = data.maxUses - data.uses;
return t('Your_invite_link_will_expire_on__date__or_after__usesLeft__uses', {
date: format(expiration),
usesLeft,
});
}
return t('Your_invite_link_will_expire_on__date__', { date: format(expiration) });
}
if (data.maxUses) {
const usesLeft = data.maxUses - data.uses;
return t('Your_invite_link_will_expire_after__usesLeft__uses', { usesLeft });
}
return t('Your_invite_link_will_never_expire');
},
);
const { data, isSuccess, error, isError, isLoading } = useQuery({
queryKey: ['findOrCreateInvite', days, maxUses],
queryFn: async () => findOrCreateInvite({ rid, days: Number(days), maxUses: Number(maxUses) }),
});
useEffect(() => {
if (isSuccess) {
dispatchToastMessage({ type: 'success', message: t('Invite_link_generated') });
}
}, [dispatchToastMessage, isSuccess, t]);
const handleGenerateLink = useStableCallback((daysAndMaxUses: { days: string; maxUses: string }) => {
setInviteState((prevState) => ({ ...prevState, daysAndMaxUses, isEditing: false }));
});
if (isError) {
return <InviteUsersError error={error} onClose={closeTab} onClickBack={onClickBack} />;
}
if (isLoading) {
return <InviteUsersLoading onClose={closeTab} onClickBack={onClickBack} />;
}
if (isEditing) {
return (
<InviteUsersEdit
daysAndMaxUses={{ days, maxUses }}
onClickBackLink={handleBackToLink}
onClickNewLink={handleGenerateLink}
onClose={closeTab}
/>
);
}
if (isSuccess) {
return (
<InviteUsers
linkText={data.url}
captionText={linkExpirationText(data)}
onClose={closeTab}
onClickBackMembers={onClickBack}
onClickEdit={handleEdit}
/>
);
}
return <InviteUsersError error={new Error(t('Something_Went_Wrong'))} onClose={closeTab} onClickBack={onClickBack} />;
};
export default InviteUsersWithData;

View File

@@ -0,0 +1,33 @@
import {
ContextualbarHeader,
ContextualbarTitle,
ContextualbarBack,
ContextualbarClose,
ContextualbarScrollableContent,
ContextualbarDialog,
} from '@rocket.chat/ui-client';
import type { ReactNode } from 'react';
import { useTranslation } from 'react-i18next';
export type InviteUsersWrapperProps = {
children: ReactNode;
onClickBack: (() => void) | undefined;
onClose: () => void;
};
const InviteUsersWrapper = ({ children, onClickBack, onClose }: InviteUsersWrapperProps) => {
const { t } = useTranslation();
return (
<ContextualbarDialog>
<ContextualbarHeader>
<ContextualbarBack onClick={onClickBack} />
<ContextualbarTitle>{t('Invite_Users')}</ContextualbarTitle>
<ContextualbarClose onClick={onClose} />
</ContextualbarHeader>
<ContextualbarScrollableContent>{children}</ContextualbarScrollableContent>
</ContextualbarDialog>
);
};
export default InviteUsersWrapper;

View File

@@ -0,0 +1,847 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`renders Default without crashing 1`] = `
<body>
<div>
<div
class="rcx-box rcx-box--full rcx-css-llf9s1"
>
<span
data-focus-scope-start="true"
hidden=""
/>
<div
style="position: relative; user-select: auto; width: 380px; height: 100%; max-width: 50%; min-width: 380px; min-height: 100%; box-sizing: border-box; flex-shrink: 0;"
>
<div
aria-labelledby="contextualbarTitle"
class="rcx-box rcx-box--full rcx-vertical-bar rcx-css-nlfrt3"
role="dialog"
tabindex="-1"
>
<div
class="rcx-box rcx-box--full rcx-css-lm07yg"
>
<div
class="rcx-box rcx-box--full rcx-css-1bdyjik rcx-css-1l4fxfb"
>
<button
class="rcx-box rcx-box--full rcx-button--small-square rcx-button--square rcx-button--icon rcx-button rcx-css-ue04py"
title="Back"
type="button"
>
<i
aria-hidden="true"
class="rcx-box rcx-box--full rcx-icon--name-arrow-back rcx-icon rcx-css-4pvxx3"
>
⦉
</i>
</button>
<h5
class="rcx-box rcx-box--full rcx-css-1spko5i"
id="contextualbarTitle"
>
Invite users
</h5>
<button
aria-label="Close"
class="rcx-box rcx-box--full rcx-button--small-square rcx-button--square rcx-button--icon rcx-button rcx-css-ue04py"
data-qa="ContextualbarActionClose"
type="button"
>
<i
aria-hidden="true"
class="rcx-box rcx-box--full rcx-icon--name-cross rcx-icon rcx-css-4pvxx3"
>
</i>
</button>
</div>
</div>
<div
class="rcx-box rcx-box--full rcx-css-1svuzur"
>
<div
class="rcx-box rcx-box--full rcx-css-1pd039f rcx-css-1cb6i7s"
data-overlayscrollbars="host"
>
<div
class="os-size-observer"
>
<div
class="os-size-observer-listener"
/>
</div>
<div
class=""
data-overlayscrollbars-viewport="scrollbarHidden overflowXHidden overflowYHidden"
style="margin-right: 0px; margin-bottom: 0px; margin-left: 0px; top: 0px; left: 0px; width: calc(100% + 0px); padding: 0px 0px 0px 0px;"
tabindex="-1"
>
<div
class="rcx-box rcx-box--full rcx-css-zg7o7h"
>
<div
class="rcx-box rcx-box--full rcx-field rcx-css-1fuhgt0"
>
<label
class="rcx-box rcx-box--full rcx-field__label rcx-label rcx-css-irxdij"
for="_r_1_"
>
Invite link
</label>
<span
class="rcx-box rcx-box--full rcx-field__row"
>
<label
class="rcx-box rcx-box--full rcx-label rcx-box rcx-box--full rcx-box--animated rcx-input-box__wrapper"
>
<input
class="rcx-box rcx-box--full rcx-box--animated rcx-input-box--undecorated rcx-input-box--type-url rcx-input-box"
id="_r_1_"
size="1"
type="url"
value="https://go.rocket.chat/invite?host=open.rocket.chat&path=invite%2F5sBs3a"
/>
<span
class="rcx-box rcx-box--full rcx-input-box__addon"
>
<i
aria-hidden="true"
class="rcx-box rcx-box--full rcx-icon--name-copy rcx-icon rcx-css-1g87xs3"
>
</i>
</span>
</label>
</span>
<div
class="rcx-box rcx-box--full rcx-css-14258hb"
>
Expire on February 4, 2020 4:45 PM.
</div>
</div>
</div>
</div>
<div
class="os-scrollbar os-scrollbar-horizontal os-theme-dark os-scrollbar-auto-hide os-scrollbar-auto-hide-hidden os-scrollbar-handle-interactive os-scrollbar-cornerless os-scrollbar-unusable"
style="--os-scroll-percent: 0; --os-viewport-percent: 0; --os-scroll-direction: 0;"
>
<div
class="os-scrollbar-track"
>
<div
class="os-scrollbar-handle"
/>
</div>
</div>
<div
class="os-scrollbar os-scrollbar-vertical os-theme-dark os-scrollbar-auto-hide os-scrollbar-auto-hide-hidden os-scrollbar-handle-interactive os-scrollbar-cornerless os-scrollbar-unusable"
style="--os-scroll-percent: 0; --os-viewport-percent: 0; --os-scroll-direction: 0;"
>
<div
class="os-scrollbar-track"
>
<div
class="os-scrollbar-handle"
/>
</div>
</div>
</div>
</div>
</div>
<div>
<div
style="position: absolute; user-select: none; width: 100%; height: 10px; top: -5px; left: 0px; cursor: row-resize;"
/>
<div
style="position: absolute; user-select: none; width: 10px; height: 100%; top: 0px; cursor: col-resize; right: -5px;"
/>
<div
style="position: absolute; user-select: none; width: 100%; height: 10px; left: 0px; cursor: row-resize; bottom: -5px;"
/>
<div
style="position: absolute; user-select: none; width: 3px; height: 100%; top: 0px; left: 0px; cursor: col-resize; z-index: 99;"
>
<div
class="rcx-box rcx-box--full rcx-css-124vum9"
/>
</div>
<div
style="position: absolute; user-select: none; width: 20px; height: 20px; z-index: 1; right: -10px; top: -10px; cursor: ne-resize;"
/>
<div
style="position: absolute; user-select: none; width: 20px; height: 20px; z-index: 1; right: -10px; bottom: -10px; cursor: se-resize;"
/>
<div
style="position: absolute; user-select: none; width: 20px; height: 20px; z-index: 1; left: -10px; bottom: -10px; cursor: sw-resize;"
/>
<div
style="position: absolute; user-select: none; width: 20px; height: 20px; z-index: 1; left: -10px; top: -10px; cursor: nw-resize;"
/>
</div>
</div>
<span
data-focus-scope-end="true"
hidden=""
/>
</div>
</div>
</body>
`;
exports[`renders InviteEdit without crashing 1`] = `
<body>
<div>
<div
class="rcx-box rcx-box--full rcx-css-llf9s1"
>
<span
data-focus-scope-start="true"
hidden=""
/>
<div
style="position: relative; user-select: auto; width: 380px; height: 100%; max-width: 50%; min-width: 380px; min-height: 100%; box-sizing: border-box; flex-shrink: 0;"
>
<div
aria-labelledby="contextualbarTitle"
class="rcx-box rcx-box--full rcx-vertical-bar rcx-css-nlfrt3"
role="dialog"
tabindex="-1"
>
<div
class="rcx-box rcx-box--full rcx-css-lm07yg"
>
<div
class="rcx-box rcx-box--full rcx-css-1bdyjik rcx-css-1l4fxfb"
>
<button
class="rcx-box rcx-box--full rcx-button--small-square rcx-button--square rcx-button--icon rcx-button rcx-css-ue04py"
title="Back"
type="button"
>
<i
aria-hidden="true"
class="rcx-box rcx-box--full rcx-icon--name-arrow-back rcx-icon rcx-css-4pvxx3"
>
⦉
</i>
</button>
<h5
class="rcx-box rcx-box--full rcx-css-1spko5i"
id="contextualbarTitle"
>
Invite users
</h5>
<button
aria-label="Close"
class="rcx-box rcx-box--full rcx-button--small-square rcx-button--square rcx-button--icon rcx-button rcx-css-ue04py"
data-qa="ContextualbarActionClose"
type="button"
>
<i
aria-hidden="true"
class="rcx-box rcx-box--full rcx-icon--name-cross rcx-icon rcx-css-4pvxx3"
>
</i>
</button>
</div>
</div>
<div
class="rcx-box rcx-box--full rcx-css-1svuzur"
>
<div
class="rcx-box rcx-box--full rcx-css-1pd039f rcx-css-1cb6i7s"
data-overlayscrollbars="host"
>
<div
class="os-size-observer"
>
<div
class="os-size-observer-listener"
/>
</div>
<div
class=""
data-overlayscrollbars-viewport="scrollbarHidden overflowXHidden overflowYHidden"
style="margin-right: 0px; margin-bottom: 0px; margin-left: 0px; top: 0px; left: 0px; width: calc(100% + 0px); padding: 0px 0px 0px 0px;"
tabindex="-1"
>
<div
class="rcx-box rcx-box--full rcx-css-zg7o7h"
>
<div
class="rcx-box rcx-box--full rcx-field rcx-css-1fuhgt0"
>
<label
class="rcx-box rcx-box--full rcx-field__label rcx-label rcx-css-irxdij"
for="_r_3_"
>
Expiration (Days)
</label>
<span
class="rcx-box rcx-box--full rcx-field__row"
>
<div
class="rcx-box rcx-box--full rcx-css-1mbgoc8"
>
<div
aria-hidden="true"
data-a11y-ignore="aria-hidden-focus"
data-react-aria-prevent-focus="true"
data-testid="hidden-select-container"
style="border: 0px; clip-path: inset(50%); height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px; white-space: nowrap;"
>
<label>
<select
name="days"
tabindex="-1"
>
<option />
<option
value="1"
>
1
</option>
<option
value="7"
>
7
</option>
<option
value="15"
>
15
</option>
<option
value="30"
>
30
</option>
<option
value="0"
>
0
</option>
</select>
</label>
</div>
</div>
<button
aria-expanded="false"
aria-haspopup="listbox"
aria-labelledby="react-aria-_r_c_"
class="rcx-box rcx-box--full rcx-box--animated rcx-select rcx-css-1vw6rc6"
id="_r_3_"
type="button"
>
<span
class="rcx-box rcx-box--full rcx-css-1ah8hdc"
id="react-aria-_r_c_"
>
1
</span>
<i
aria-hidden="true"
class="rcx-box rcx-box--full rcx-icon--name-chevron-down rcx-icon rcx-css-l5txo2"
>
</i>
</button>
</span>
</div>
<div
class="rcx-box rcx-box--full rcx-field rcx-css-1fuhgt0"
>
<label
class="rcx-box rcx-box--full rcx-field__label rcx-label rcx-css-irxdij"
for="_r_4_"
>
Max number of uses
</label>
<span
class="rcx-box rcx-box--full rcx-field__row"
>
<div
class="rcx-box rcx-box--full rcx-css-1mbgoc8"
>
<div
aria-hidden="true"
data-a11y-ignore="aria-hidden-focus"
data-react-aria-prevent-focus="true"
data-testid="hidden-select-container"
style="border: 0px; clip-path: inset(50%); height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px; white-space: nowrap;"
>
<label>
<select
name="maxUses"
tabindex="-1"
>
<option />
<option
value="5"
>
5
</option>
<option
value="10"
>
10
</option>
<option
value="25"
>
25
</option>
<option
value="50"
>
50
</option>
<option
value="100"
>
100
</option>
<option
value="0"
>
0
</option>
</select>
</label>
</div>
</div>
<button
aria-expanded="false"
aria-haspopup="listbox"
aria-labelledby="react-aria-_r_k_"
class="rcx-box rcx-box--full rcx-box--animated rcx-select rcx-css-1vw6rc6"
id="_r_4_"
type="button"
>
<span
class="rcx-box rcx-box--full rcx-css-1ah8hdc"
id="react-aria-_r_k_"
>
5
</span>
<i
aria-hidden="true"
class="rcx-box rcx-box--full rcx-icon--name-chevron-down rcx-icon rcx-css-l5txo2"
>
</i>
</button>
</span>
</div>
<div
class="rcx-box rcx-box--full rcx-css-31obua"
>
<button
class="rcx-box rcx-box--full rcx-button--primary rcx-button"
disabled=""
type="button"
>
<span
class="rcx-button--content"
>
Generate_New_Link
</span>
</button>
</div>
</div>
</div>
<div
class="os-scrollbar os-scrollbar-horizontal os-theme-dark os-scrollbar-auto-hide os-scrollbar-auto-hide-hidden os-scrollbar-handle-interactive os-scrollbar-cornerless os-scrollbar-unusable"
style="--os-scroll-percent: 0; --os-viewport-percent: 0; --os-scroll-direction: 0;"
>
<div
class="os-scrollbar-track"
>
<div
class="os-scrollbar-handle"
/>
</div>
</div>
<div
class="os-scrollbar os-scrollbar-vertical os-theme-dark os-scrollbar-auto-hide os-scrollbar-auto-hide-hidden os-scrollbar-handle-interactive os-scrollbar-cornerless os-scrollbar-unusable"
style="--os-scroll-percent: 0; --os-viewport-percent: 0; --os-scroll-direction: 0;"
>
<div
class="os-scrollbar-track"
>
<div
class="os-scrollbar-handle"
/>
</div>
</div>
</div>
</div>
</div>
<div>
<div
style="position: absolute; user-select: none; width: 100%; height: 10px; top: -5px; left: 0px; cursor: row-resize;"
/>
<div
style="position: absolute; user-select: none; width: 10px; height: 100%; top: 0px; cursor: col-resize; right: -5px;"
/>
<div
style="position: absolute; user-select: none; width: 100%; height: 10px; left: 0px; cursor: row-resize; bottom: -5px;"
/>
<div
style="position: absolute; user-select: none; width: 3px; height: 100%; top: 0px; left: 0px; cursor: col-resize; z-index: 99;"
>
<div
class="rcx-box rcx-box--full rcx-css-124vum9"
/>
</div>
<div
style="position: absolute; user-select: none; width: 20px; height: 20px; z-index: 1; right: -10px; top: -10px; cursor: ne-resize;"
/>
<div
style="position: absolute; user-select: none; width: 20px; height: 20px; z-index: 1; right: -10px; bottom: -10px; cursor: se-resize;"
/>
<div
style="position: absolute; user-select: none; width: 20px; height: 20px; z-index: 1; left: -10px; bottom: -10px; cursor: sw-resize;"
/>
<div
style="position: absolute; user-select: none; width: 20px; height: 20px; z-index: 1; left: -10px; top: -10px; cursor: nw-resize;"
/>
</div>
</div>
<span
data-focus-scope-end="true"
hidden=""
/>
</div>
</div>
</body>
`;
exports[`renders InviteError without crashing 1`] = `
<body>
<div>
<div
class="rcx-box rcx-box--full rcx-css-llf9s1"
>
<span
data-focus-scope-start="true"
hidden=""
/>
<div
style="position: relative; user-select: auto; width: 380px; height: 100%; max-width: 50%; min-width: 380px; min-height: 100%; box-sizing: border-box; flex-shrink: 0;"
>
<div
aria-labelledby="contextualbarTitle"
class="rcx-box rcx-box--full rcx-vertical-bar rcx-css-nlfrt3"
role="dialog"
tabindex="-1"
>
<div
class="rcx-box rcx-box--full rcx-css-lm07yg"
>
<div
class="rcx-box rcx-box--full rcx-css-1bdyjik rcx-css-1l4fxfb"
>
<button
class="rcx-box rcx-box--full rcx-button--small-square rcx-button--square rcx-button--icon rcx-button rcx-css-ue04py"
title="Back"
type="button"
>
<i
aria-hidden="true"
class="rcx-box rcx-box--full rcx-icon--name-arrow-back rcx-icon rcx-css-4pvxx3"
>
⦉
</i>
</button>
<h5
class="rcx-box rcx-box--full rcx-css-1spko5i"
id="contextualbarTitle"
>
Invite users
</h5>
<button
aria-label="Close"
class="rcx-box rcx-box--full rcx-button--small-square rcx-button--square rcx-button--icon rcx-button rcx-css-ue04py"
data-qa="ContextualbarActionClose"
type="button"
>
<i
aria-hidden="true"
class="rcx-box rcx-box--full rcx-icon--name-cross rcx-icon rcx-css-4pvxx3"
>
</i>
</button>
</div>
</div>
<div
class="rcx-box rcx-box--full rcx-css-1svuzur"
>
<div
class="rcx-box rcx-box--full rcx-css-1pd039f rcx-css-1cb6i7s"
data-overlayscrollbars="host"
>
<div
class="os-size-observer"
>
<div
class="os-size-observer-listener"
/>
</div>
<div
class=""
data-overlayscrollbars-viewport="scrollbarHidden overflowXHidden overflowYHidden"
style="margin-right: 0px; margin-bottom: 0px; margin-left: 0px; top: 0px; left: 0px; width: calc(100% + 0px); padding: 0px 0px 0px 0px;"
tabindex="-1"
>
<div
class="rcx-box rcx-box--full rcx-css-zg7o7h"
>
<section
class="rcx-box rcx-box--full rcx-callout rcx-callout--danger rcx-css-1jggbrp rcx-css-1fuhgt0"
>
<i
aria-hidden="true"
class="rcx-box rcx-box--full rcx-icon--name-ban rcx-icon rcx-callout__icon rcx-css-4pvxx3"
>
</i>
<div
class="rcx-box rcx-box--full rcx-callout__wrapper"
>
<div
class="rcx-box rcx-box--full rcx-callout__wrapper-content"
>
<div
class="rcx-box rcx-box--full rcx-callout__content"
>
Error: Error message
</div>
</div>
</div>
</section>
</div>
</div>
<div
class="os-scrollbar os-scrollbar-horizontal os-theme-dark os-scrollbar-auto-hide os-scrollbar-auto-hide-hidden os-scrollbar-handle-interactive os-scrollbar-cornerless os-scrollbar-unusable"
style="--os-scroll-percent: 0; --os-viewport-percent: 0; --os-scroll-direction: 0;"
>
<div
class="os-scrollbar-track"
>
<div
class="os-scrollbar-handle"
/>
</div>
</div>
<div
class="os-scrollbar os-scrollbar-vertical os-theme-dark os-scrollbar-auto-hide os-scrollbar-auto-hide-hidden os-scrollbar-handle-interactive os-scrollbar-cornerless os-scrollbar-unusable"
style="--os-scroll-percent: 0; --os-viewport-percent: 0; --os-scroll-direction: 0;"
>
<div
class="os-scrollbar-track"
>
<div
class="os-scrollbar-handle"
/>
</div>
</div>
</div>
</div>
</div>
<div>
<div
style="position: absolute; user-select: none; width: 100%; height: 10px; top: -5px; left: 0px; cursor: row-resize;"
/>
<div
style="position: absolute; user-select: none; width: 10px; height: 100%; top: 0px; cursor: col-resize; right: -5px;"
/>
<div
style="position: absolute; user-select: none; width: 100%; height: 10px; left: 0px; cursor: row-resize; bottom: -5px;"
/>
<div
style="position: absolute; user-select: none; width: 3px; height: 100%; top: 0px; left: 0px; cursor: col-resize; z-index: 99;"
>
<div
class="rcx-box rcx-box--full rcx-css-124vum9"
/>
</div>
<div
style="position: absolute; user-select: none; width: 20px; height: 20px; z-index: 1; right: -10px; top: -10px; cursor: ne-resize;"
/>
<div
style="position: absolute; user-select: none; width: 20px; height: 20px; z-index: 1; right: -10px; bottom: -10px; cursor: se-resize;"
/>
<div
style="position: absolute; user-select: none; width: 20px; height: 20px; z-index: 1; left: -10px; bottom: -10px; cursor: sw-resize;"
/>
<div
style="position: absolute; user-select: none; width: 20px; height: 20px; z-index: 1; left: -10px; top: -10px; cursor: nw-resize;"
/>
</div>
</div>
<span
data-focus-scope-end="true"
hidden=""
/>
</div>
</div>
</body>
`;
exports[`renders InviteLoading without crashing 1`] = `
<body>
<div>
<div
class="rcx-box rcx-box--full rcx-css-llf9s1"
>
<span
data-focus-scope-start="true"
hidden=""
/>
<div
style="position: relative; user-select: auto; width: 380px; height: 100%; max-width: 50%; min-width: 380px; min-height: 100%; box-sizing: border-box; flex-shrink: 0;"
>
<div
aria-labelledby="contextualbarTitle"
class="rcx-box rcx-box--full rcx-vertical-bar rcx-css-nlfrt3"
role="dialog"
tabindex="-1"
>
<div
class="rcx-box rcx-box--full rcx-css-lm07yg"
>
<div
class="rcx-box rcx-box--full rcx-css-1bdyjik rcx-css-1l4fxfb"
>
<button
class="rcx-box rcx-box--full rcx-button--small-square rcx-button--square rcx-button--icon rcx-button rcx-css-ue04py"
title="Back"
type="button"
>
<i
aria-hidden="true"
class="rcx-box rcx-box--full rcx-icon--name-arrow-back rcx-icon rcx-css-4pvxx3"
>
⦉
</i>
</button>
<h5
class="rcx-box rcx-box--full rcx-css-1spko5i"
id="contextualbarTitle"
>
Invite users
</h5>
<button
aria-label="Close"
class="rcx-box rcx-box--full rcx-button--small-square rcx-button--square rcx-button--icon rcx-button rcx-css-ue04py"
data-qa="ContextualbarActionClose"
type="button"
>
<i
aria-hidden="true"
class="rcx-box rcx-box--full rcx-icon--name-cross rcx-icon rcx-css-4pvxx3"
>
</i>
</button>
</div>
</div>
<div
class="rcx-box rcx-box--full rcx-css-1svuzur"
>
<div
class="rcx-box rcx-box--full rcx-css-1pd039f rcx-css-1cb6i7s"
data-overlayscrollbars="host"
>
<div
class="os-size-observer"
>
<div
class="os-size-observer-listener"
/>
</div>
<div
class=""
data-overlayscrollbars-viewport="scrollbarHidden overflowXHidden overflowYHidden"
style="margin-right: 0px; margin-bottom: 0px; margin-left: 0px; top: 0px; left: 0px; width: calc(100% + 0px); padding: 0px 0px 0px 0px;"
tabindex="-1"
>
<div
class="rcx-box rcx-box--full rcx-css-zg7o7h"
>
<span
class="rcx-skeleton rcx-skeleton--text rcx-css-1jggbrp rcx-css-1qcz93u"
/>
</div>
</div>
<div
class="os-scrollbar os-scrollbar-horizontal os-theme-dark os-scrollbar-auto-hide os-scrollbar-auto-hide-hidden os-scrollbar-handle-interactive os-scrollbar-cornerless os-scrollbar-unusable"
style="--os-scroll-percent: 0; --os-viewport-percent: 0; --os-scroll-direction: 0;"
>
<div
class="os-scrollbar-track"
>
<div
class="os-scrollbar-handle"
/>
</div>
</div>
<div
class="os-scrollbar os-scrollbar-vertical os-theme-dark os-scrollbar-auto-hide os-scrollbar-auto-hide-hidden os-scrollbar-handle-interactive os-scrollbar-cornerless os-scrollbar-unusable"
style="--os-scroll-percent: 0; --os-viewport-percent: 0; --os-scroll-direction: 0;"
>
<div
class="os-scrollbar-track"
>
<div
class="os-scrollbar-handle"
/>
</div>
</div>
</div>
</div>
</div>
<div>
<div
style="position: absolute; user-select: none; width: 100%; height: 10px; top: -5px; left: 0px; cursor: row-resize;"
/>
<div
style="position: absolute; user-select: none; width: 10px; height: 100%; top: 0px; cursor: col-resize; right: -5px;"
/>
<div
style="position: absolute; user-select: none; width: 100%; height: 10px; left: 0px; cursor: row-resize; bottom: -5px;"
/>
<div
style="position: absolute; user-select: none; width: 3px; height: 100%; top: 0px; left: 0px; cursor: col-resize; z-index: 99;"
>
<div
class="rcx-box rcx-box--full rcx-css-124vum9"
/>
</div>
<div
style="position: absolute; user-select: none; width: 20px; height: 20px; z-index: 1; right: -10px; top: -10px; cursor: ne-resize;"
/>
<div
style="position: absolute; user-select: none; width: 20px; height: 20px; z-index: 1; right: -10px; bottom: -10px; cursor: se-resize;"
/>
<div
style="position: absolute; user-select: none; width: 20px; height: 20px; z-index: 1; left: -10px; bottom: -10px; cursor: sw-resize;"
/>
<div
style="position: absolute; user-select: none; width: 20px; height: 20px; z-index: 1; left: -10px; top: -10px; cursor: nw-resize;"
/>
</div>
</div>
<span
data-focus-scope-end="true"
hidden=""
/>
</div>
</div>
</body>
`;

View File

@@ -0,0 +1 @@
export { default } from './InviteUsersWithData';