Upgrade Storybook
Co-authored-by: Scott Nonnenberg <scott@signal.org>
This commit is contained in:
parent
8c966dfbd8
commit
502ea174ab
328 changed files with 10863 additions and 12432 deletions
|
@ -14,6 +14,7 @@ libtextsecure/components.js
|
||||||
libtextsecure/test/test.js
|
libtextsecure/test/test.js
|
||||||
test/test.js
|
test/test.js
|
||||||
ts/protobuf/compiled.d.ts
|
ts/protobuf/compiled.d.ts
|
||||||
|
storybook-static/**
|
||||||
|
|
||||||
# Third-party files
|
# Third-party files
|
||||||
js/Mp3LameEncoder.min.js
|
js/Mp3LameEncoder.min.js
|
||||||
|
|
|
@ -300,6 +300,12 @@ module.exports = {
|
||||||
'local-rules/type-alias-readonlydeep': 'error',
|
'local-rules/type-alias-readonlydeep': 'error',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
files: ['ts/**/*_test.{ts,tsx}'],
|
||||||
|
rules: {
|
||||||
|
'func-names': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
rules: {
|
rules: {
|
||||||
|
|
23
.github/workflows/stories.yml
vendored
Normal file
23
.github/workflows/stories.yml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# Copyright 2023 Signal Messenger, LLC
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
name: Stories
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- development
|
||||||
|
- main
|
||||||
|
- '[0-9]+.[0-9]+.x'
|
||||||
|
pull_request:
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest-8-cores
|
||||||
|
timeout-minutes: 30
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: '18.15.0'
|
||||||
|
cache: 'yarn'
|
||||||
|
- run: yarn install --frozen-lockfile
|
||||||
|
- run: yarn build:storybook
|
||||||
|
- run: yarn run-p --race test:storybook:serve test:storybook:test
|
|
@ -1,29 +0,0 @@
|
||||||
// Copyright 2022 Signal Messenger, LLC
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
typescript: {
|
|
||||||
reactDocgen: false,
|
|
||||||
},
|
|
||||||
stories: ['../ts/components/**/*.stories.tsx'],
|
|
||||||
addons: [
|
|
||||||
'@storybook/addon-a11y',
|
|
||||||
'@storybook/addon-actions',
|
|
||||||
'@storybook/addon-controls',
|
|
||||||
'@storybook/addon-measure',
|
|
||||||
'@storybook/addon-toolbars',
|
|
||||||
'@storybook/addon-viewport',
|
|
||||||
|
|
||||||
// This must be imported last.
|
|
||||||
'@storybook/addon-interactions',
|
|
||||||
|
|
||||||
// Deprecated! Please remove when all uses have been migrated to controls.
|
|
||||||
'@storybook/addon-knobs',
|
|
||||||
],
|
|
||||||
core: {
|
|
||||||
builder: 'webpack5',
|
|
||||||
},
|
|
||||||
features: {
|
|
||||||
storyStoreV7: true,
|
|
||||||
},
|
|
||||||
};
|
|
98
.storybook/main.ts
Normal file
98
.storybook/main.ts
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
// Copyright 2022 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import type { StorybookConfig } from '@storybook/react-webpack5';
|
||||||
|
import { ProvidePlugin } from 'webpack';
|
||||||
|
|
||||||
|
const config: StorybookConfig = {
|
||||||
|
typescript: {
|
||||||
|
reactDocgen: false,
|
||||||
|
},
|
||||||
|
stories: ['../ts/components/**/*.stories.tsx'],
|
||||||
|
addons: [
|
||||||
|
'@storybook/addon-a11y',
|
||||||
|
'@storybook/addon-actions',
|
||||||
|
'@storybook/addon-controls',
|
||||||
|
'@storybook/addon-measure',
|
||||||
|
'@storybook/addon-toolbars',
|
||||||
|
'@storybook/addon-viewport',
|
||||||
|
'@storybook/addon-jest',
|
||||||
|
|
||||||
|
// This must be imported last.
|
||||||
|
'@storybook/addon-interactions',
|
||||||
|
],
|
||||||
|
framework: '@storybook/react-webpack5',
|
||||||
|
core: {},
|
||||||
|
features: {
|
||||||
|
storyStoreV7: true,
|
||||||
|
},
|
||||||
|
staticDirs: [
|
||||||
|
{ from: '../fonts', to: 'fonts' },
|
||||||
|
{ from: '../images', to: 'images' },
|
||||||
|
{ from: '../fixtures', to: 'fixtures' },
|
||||||
|
],
|
||||||
|
webpackFinal(config) {
|
||||||
|
config.cache = {
|
||||||
|
type: 'filesystem',
|
||||||
|
};
|
||||||
|
|
||||||
|
config.resolve!.extensions = ['.tsx', '.ts', '...'];
|
||||||
|
|
||||||
|
config.module!.rules!.unshift({
|
||||||
|
test: /\.scss$/,
|
||||||
|
use: [
|
||||||
|
{ loader: 'style-loader' },
|
||||||
|
{ loader: 'css-loader', options: { modules: false, url: false } },
|
||||||
|
{ loader: 'sass-loader' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
config.module!.rules!.unshift({
|
||||||
|
test: /\.css$/,
|
||||||
|
use: [
|
||||||
|
// prevent storybook defaults from being applied
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
config.node = { global: true };
|
||||||
|
|
||||||
|
config.externals = {
|
||||||
|
net: 'commonjs net',
|
||||||
|
vm: 'commonjs vm',
|
||||||
|
fs: 'commonjs fs',
|
||||||
|
async_hooks: 'commonjs async_hooks',
|
||||||
|
module: 'commonjs module',
|
||||||
|
stream: 'commonjs stream',
|
||||||
|
tls: 'commonjs tls',
|
||||||
|
dns: 'commonjs dns',
|
||||||
|
http: 'commonjs http',
|
||||||
|
https: 'commonjs https',
|
||||||
|
os: 'commonjs os',
|
||||||
|
constants: 'commonjs constants',
|
||||||
|
zlib: 'commonjs zlib',
|
||||||
|
'@signalapp/libsignal-client': 'commonjs @signalapp/libsignal-client',
|
||||||
|
'@signalapp/libsignal-client/zkgroup':
|
||||||
|
'commonjs @signalapp/libsignal-client/zkgroup',
|
||||||
|
'@signalapp/ringrtc': 'commonjs @signalapp/ringrtc',
|
||||||
|
'@signalapp/better-sqlite3': 'commonjs @signalapp/better-sqlite3',
|
||||||
|
electron: 'commonjs electron',
|
||||||
|
'fs-xattr': 'commonjs fs-xattr',
|
||||||
|
fsevents: 'commonjs fsevents',
|
||||||
|
'mac-screen-capture-permissions':
|
||||||
|
'commonjs mac-screen-capture-permissions',
|
||||||
|
sass: 'commonjs sass',
|
||||||
|
bufferutil: 'commonjs bufferutil',
|
||||||
|
'utf-8-validate': 'commonjs utf-8-validate',
|
||||||
|
};
|
||||||
|
|
||||||
|
config.plugins!.push(
|
||||||
|
new ProvidePlugin({
|
||||||
|
Buffer: ['buffer', 'Buffer'],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
|
@ -1,63 +0,0 @@
|
||||||
<!-- Copyright 2019 Signal Messenger, LLC -->
|
|
||||||
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
|
||||||
|
|
||||||
<!-- prettier-ignore -->
|
|
||||||
<link rel="stylesheet" href="../stylesheets/manifest.css" />
|
|
||||||
<link
|
|
||||||
href="../node_modules/@indutny/frameless-titlebar/dist/styles.css"
|
|
||||||
rel="stylesheet"
|
|
||||||
type="text/css"
|
|
||||||
/>
|
|
||||||
<script>
|
|
||||||
// eslint-disable-next-line
|
|
||||||
const noop = () => {};
|
|
||||||
|
|
||||||
window.Whisper = window.Whisper || {};
|
|
||||||
window.Whisper.events = {
|
|
||||||
on: noop,
|
|
||||||
};
|
|
||||||
|
|
||||||
window.SignalWindow = window.SignalWindow || {};
|
|
||||||
window.SignalWindow.log = {
|
|
||||||
fatal: console.error.bind(console),
|
|
||||||
error: console.error.bind(console),
|
|
||||||
warn: console.warn.bind(console),
|
|
||||||
info: console.info.bind(console),
|
|
||||||
debug: console.debug.bind(console),
|
|
||||||
trace: console.trace.bind(console),
|
|
||||||
};
|
|
||||||
window.SignalContext = {
|
|
||||||
activeWindowService: {
|
|
||||||
isActive: () => true,
|
|
||||||
registerForActive: noop,
|
|
||||||
unregisterForActive: noop,
|
|
||||||
registerForChange: noop,
|
|
||||||
unregisterForChange: noop,
|
|
||||||
},
|
|
||||||
|
|
||||||
nativeThemeListener: {
|
|
||||||
getSystemValue: async () => 'light',
|
|
||||||
subscribe: noop,
|
|
||||||
unsubscribe: noop,
|
|
||||||
},
|
|
||||||
Settings: {
|
|
||||||
themeSetting: {
|
|
||||||
getValue: async () => 'light',
|
|
||||||
},
|
|
||||||
waitForChange: () => new Promise(noop),
|
|
||||||
},
|
|
||||||
OS: {
|
|
||||||
hasCustomTitleBar: () => false,
|
|
||||||
},
|
|
||||||
usernames: {
|
|
||||||
hash: x => x,
|
|
||||||
},
|
|
||||||
config: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
window.ConversationController = window.ConversationController || {};
|
|
||||||
window.ConversationController.isSignalConversationId = () => false;
|
|
||||||
window.ConversationController.onConvoMessageMount = noop;
|
|
||||||
window.getPreferredSystemLocales = () => ['en'];
|
|
||||||
window.getResolvedMessagesLocaleDirection = () => 'ltr';
|
|
||||||
</script>
|
|
|
@ -1,17 +1,29 @@
|
||||||
// Copyright 2019 Signal Messenger, LLC
|
// Copyright 2019 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import '../ts/window.d.ts';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classnames from 'classnames';
|
|
||||||
import { withKnobs, boolean, optionsKnob } from '@storybook/addon-knobs';
|
import 'sanitize.css';
|
||||||
|
import '../stylesheets/manifest.scss';
|
||||||
|
import '../node_modules/@indutny/frameless-titlebar/dist/styles.css';
|
||||||
|
|
||||||
import * as styles from './styles.scss';
|
import * as styles from './styles.scss';
|
||||||
import messages from '../_locales/en/messages.json';
|
import messages from '../_locales/en/messages.json';
|
||||||
import { ClassyProvider } from '../ts/components/PopperRootContext';
|
|
||||||
import { StorybookThemeContext } from './StorybookThemeContext';
|
import { StorybookThemeContext } from './StorybookThemeContext';
|
||||||
import { ThemeType } from '../ts/types/Util';
|
import { ThemeType } from '../ts/types/Util';
|
||||||
import { setupI18n } from '../ts/util/setupI18n';
|
import { setupI18n } from '../ts/util/setupI18n';
|
||||||
import { HourCyclePreference } from '../ts/types/I18N';
|
import { HourCyclePreference } from '../ts/types/I18N';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
import { Store, combineReducers, createStore } from 'redux';
|
||||||
|
import { StateType } from '../ts/state/reducer';
|
||||||
|
import {
|
||||||
|
ScrollerLockContext,
|
||||||
|
createScrollerLock,
|
||||||
|
} from '../ts/hooks/useScrollLock';
|
||||||
|
|
||||||
|
const i18n = setupI18n('en', messages);
|
||||||
|
|
||||||
export const globalTypes = {
|
export const globalTypes = {
|
||||||
mode: {
|
mode: {
|
||||||
|
@ -38,8 +50,73 @@ export const globalTypes = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
window.i18n = setupI18n('en', messages);
|
const mockStore: Store<StateType> = createStore(
|
||||||
window.getHourCyclePreference = () => HourCyclePreference.UnknownPreference;
|
combineReducers({
|
||||||
|
calling: (state = {}) => state,
|
||||||
|
conversations: (
|
||||||
|
state = {
|
||||||
|
conversationLookup: {},
|
||||||
|
targetedConversationPanels: {},
|
||||||
|
}
|
||||||
|
) => state,
|
||||||
|
globalModals: (state = {}) => state,
|
||||||
|
user: (state = {}) => state,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// eslint-disable-next-line
|
||||||
|
const noop = () => {};
|
||||||
|
|
||||||
|
window.Whisper = window.Whisper || {};
|
||||||
|
window.Whisper.events = {
|
||||||
|
on: noop,
|
||||||
|
};
|
||||||
|
|
||||||
|
window.SignalContext = {
|
||||||
|
i18n,
|
||||||
|
|
||||||
|
activeWindowService: {
|
||||||
|
isActive: () => true,
|
||||||
|
registerForActive: noop,
|
||||||
|
unregisterForActive: noop,
|
||||||
|
registerForChange: noop,
|
||||||
|
unregisterForChange: noop,
|
||||||
|
},
|
||||||
|
|
||||||
|
nativeThemeListener: {
|
||||||
|
getSystemTheme: () => 'light',
|
||||||
|
subscribe: noop,
|
||||||
|
unsubscribe: noop,
|
||||||
|
update: () => 'light',
|
||||||
|
},
|
||||||
|
Settings: {
|
||||||
|
themeSetting: {
|
||||||
|
getValue: async () => 'light',
|
||||||
|
setValue: async () => 'light',
|
||||||
|
},
|
||||||
|
waitForChange: () => new Promise(noop),
|
||||||
|
},
|
||||||
|
OS: {
|
||||||
|
hasCustomTitleBar: () => false,
|
||||||
|
getClassName: () => '',
|
||||||
|
platform: '',
|
||||||
|
release: '',
|
||||||
|
},
|
||||||
|
usernames: {
|
||||||
|
hash: input => Buffer.from(input),
|
||||||
|
} as any,
|
||||||
|
config: {} as any,
|
||||||
|
|
||||||
|
getHourCyclePreference: () => HourCyclePreference.UnknownPreference,
|
||||||
|
getPreferredSystemLocales: () => ['en'],
|
||||||
|
getResolvedMessagesLocaleDirection: () => 'ltr',
|
||||||
|
};
|
||||||
|
|
||||||
|
window.i18n = i18n;
|
||||||
|
window.ConversationController = window.ConversationController || {};
|
||||||
|
window.ConversationController.isSignalConversationId = () => false;
|
||||||
|
window.ConversationController.onConvoMessageMount = noop;
|
||||||
|
window.reduxStore = mockStore;
|
||||||
|
|
||||||
const withModeAndThemeProvider = (Story, context) => {
|
const withModeAndThemeProvider = (Story, context) => {
|
||||||
const theme =
|
const theme =
|
||||||
|
@ -75,7 +152,29 @@ const withModeAndThemeProvider = (Story, context) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const decorators = [withModeAndThemeProvider];
|
function withMockStoreProvider(Story, context) {
|
||||||
|
return (
|
||||||
|
<Provider store={mockStore}>
|
||||||
|
<Story {...context} />
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function withScrollLockProvider(Story, context) {
|
||||||
|
return (
|
||||||
|
<ScrollerLockContext.Provider
|
||||||
|
value={createScrollerLock('MockStories', () => {})}
|
||||||
|
>
|
||||||
|
<Story {...context} />
|
||||||
|
</ScrollerLockContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const decorators = [
|
||||||
|
withModeAndThemeProvider,
|
||||||
|
withMockStoreProvider,
|
||||||
|
withScrollLockProvider,
|
||||||
|
];
|
||||||
|
|
||||||
export const parameters = {
|
export const parameters = {
|
||||||
axe: {
|
axe: {
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
// Copyright 2019 Signal Messenger, LLC
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
const webpack = require('webpack');
|
|
||||||
|
|
||||||
module.exports = ({ config }) => {
|
|
||||||
config.entry.unshift('!!style-loader!css-loader!sanitize.css');
|
|
||||||
|
|
||||||
config.cache = {
|
|
||||||
type: 'filesystem',
|
|
||||||
};
|
|
||||||
|
|
||||||
config.module.rules.unshift({
|
|
||||||
test: /\.scss$/,
|
|
||||||
use: [
|
|
||||||
{ loader: 'style-loader' },
|
|
||||||
{ loader: 'css-loader?modules=true&localsConvention=camelCaseOnly' },
|
|
||||||
{ loader: 'sass-loader' },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
config.node = { global: true };
|
|
||||||
|
|
||||||
config.externals = {
|
|
||||||
net: 'commonjs net',
|
|
||||||
vm: 'commonjs vm',
|
|
||||||
fs: 'commonjs fs',
|
|
||||||
async_hooks: 'commonjs async_hooks',
|
|
||||||
module: 'commonjs module',
|
|
||||||
stream: 'commonjs stream',
|
|
||||||
tls: 'commonjs tls',
|
|
||||||
dns: 'commonjs dns',
|
|
||||||
http: 'commonjs http',
|
|
||||||
https: 'commonjs https',
|
|
||||||
os: 'commonjs os',
|
|
||||||
constants: 'commonjs constants',
|
|
||||||
zlib: 'commonjs zlib',
|
|
||||||
'@signalapp/libsignal-client': 'commonjs @signalapp/libsignal-client',
|
|
||||||
'@signalapp/libsignal-client/zkgroup':
|
|
||||||
'commonjs @signalapp/libsignal-client/zkgroup',
|
|
||||||
'@signalapp/ringrtc': 'commonjs @signalapp/ringrtc',
|
|
||||||
'@signalapp/better-sqlite3': 'commonjs @signalapp/better-sqlite3',
|
|
||||||
electron: 'commonjs electron',
|
|
||||||
'fs-xattr': 'commonjs fs-xattr',
|
|
||||||
fsevents: 'commonjs fsevents',
|
|
||||||
'mac-screen-capture-permissions': 'commonjs mac-screen-capture-permissions',
|
|
||||||
sass: 'commonjs sass',
|
|
||||||
bufferutil: 'commonjs bufferutil',
|
|
||||||
'utf-8-validate': 'commonjs utf-8-validate',
|
|
||||||
};
|
|
||||||
|
|
||||||
return config;
|
|
||||||
};
|
|
|
@ -41,3 +41,6 @@ Gruntfile.js
|
||||||
|
|
||||||
# asset directories
|
# asset directories
|
||||||
!nyc/node_modules/istanbul-reports/lib/html/assets
|
!nyc/node_modules/istanbul-reports/lib/html/assets
|
||||||
|
|
||||||
|
# bad matches
|
||||||
|
!patch-package/node_modules/yaml/dist/doc
|
||||||
|
|
67
package.json
67
package.json
|
@ -62,11 +62,11 @@
|
||||||
"clean-transpile": "yarn run clean-transpile-once && yarn run clean-transpile-once",
|
"clean-transpile": "yarn run clean-transpile-once && yarn run clean-transpile-once",
|
||||||
"open-coverage": "open coverage/lcov-report/index.html",
|
"open-coverage": "open coverage/lcov-report/index.html",
|
||||||
"ready": "npm-run-all --print-label clean-transpile generate --parallel lint lint-deps lint-intl test-node test-electron",
|
"ready": "npm-run-all --print-label clean-transpile generate --parallel lint lint-deps lint-intl test-node test-electron",
|
||||||
"dev": "run-p --print-label dev:*",
|
"dev": "yarn build-protobuf && cross-env SIGNAL_ENV=storybook storybook dev --port 6006",
|
||||||
"dev:transpile": "run-p \"check:types --watch\" dev:esbuild",
|
"build:storybook": "yarn build-protobuf && cross-env SIGNAL_ENV=storybook storybook build",
|
||||||
"dev:esbuild": "node scripts/esbuild.js --watch",
|
"test:storybook": "yarn build:storybook && run-p --race test:storybook:*",
|
||||||
"dev:storybook": "cross-env SIGNAL_ENV=storybook start-storybook -p 6006 -s ./",
|
"test:storybook:serve": "http-server storybook-static --port 6006 --silent",
|
||||||
"dev:sass": "yarn sass --watch",
|
"test:storybook:test": "wait-on http://127.0.0.1:6006/ --timeout 5000 && test-storybook",
|
||||||
"build": "run-s --print-label generate build:esbuild:prod build:release",
|
"build": "run-s --print-label generate build:esbuild:prod build:release",
|
||||||
"build-linux": "yarn generate && yarn build:esbuild:prod && yarn build:release -- --publish=never",
|
"build-linux": "yarn generate && yarn build:esbuild:prod && yarn build:release -- --publish=never",
|
||||||
"build:acknowledgments": "node scripts/generate-acknowledgments.js",
|
"build:acknowledgments": "node scripts/generate-acknowledgments.js",
|
||||||
|
@ -184,33 +184,33 @@
|
||||||
"zod": "3.21.4"
|
"zod": "3.21.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.14.3",
|
"@babel/core": "7.23.0",
|
||||||
"@babel/plugin-proposal-class-properties": "7.17.12",
|
"@babel/plugin-proposal-class-properties": "7.18.6",
|
||||||
"@babel/plugin-proposal-nullish-coalescing-operator": "7.17.12",
|
"@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6",
|
||||||
"@babel/plugin-proposal-optional-chaining": "7.17.12",
|
"@babel/plugin-proposal-optional-chaining": "7.21.0",
|
||||||
"@babel/plugin-transform-runtime": "7.18.2",
|
"@babel/plugin-transform-runtime": "7.22.15",
|
||||||
"@babel/plugin-transform-typescript": "7.18.4",
|
"@babel/plugin-transform-typescript": "7.22.15",
|
||||||
"@babel/preset-react": "7.17.12",
|
"@babel/preset-react": "7.22.15",
|
||||||
"@babel/preset-typescript": "7.17.12",
|
"@babel/preset-typescript": "7.23.0",
|
||||||
"@electron/fuses": "1.5.0",
|
"@electron/fuses": "1.5.0",
|
||||||
"@formatjs/intl": "2.6.7",
|
"@formatjs/intl": "2.6.7",
|
||||||
"@mixer/parallel-prettier": "2.0.3",
|
"@mixer/parallel-prettier": "2.0.3",
|
||||||
"@signalapp/mock-server": "4.1.2",
|
"@signalapp/mock-server": "4.1.2",
|
||||||
"@storybook/addon-a11y": "6.5.6",
|
"@storybook/addon-a11y": "7.4.5",
|
||||||
"@storybook/addon-actions": "6.5.6",
|
"@storybook/addon-actions": "7.4.5",
|
||||||
"@storybook/addon-controls": "6.5.6",
|
"@storybook/addon-controls": "7.4.5",
|
||||||
"@storybook/addon-interactions": "6.5.9",
|
"@storybook/addon-interactions": "7.4.5",
|
||||||
"@storybook/addon-knobs": "6.4.0",
|
"@storybook/addon-jest": "7.4.5",
|
||||||
"@storybook/addon-measure": "6.5.6",
|
"@storybook/addon-measure": "7.4.5",
|
||||||
"@storybook/addon-toolbars": "6.5.6",
|
"@storybook/addon-toolbars": "7.4.5",
|
||||||
"@storybook/addon-viewport": "6.5.6",
|
"@storybook/addon-viewport": "7.4.5",
|
||||||
"@storybook/addons": "6.5.6",
|
"@storybook/addons": "7.4.5",
|
||||||
"@storybook/builder-webpack5": "6.5.15",
|
"@storybook/jest": "0.2.2",
|
||||||
"@storybook/jest": "0.0.10",
|
"@storybook/react": "7.4.5",
|
||||||
"@storybook/manager-webpack5": "6.5.15",
|
"@storybook/react-webpack5": "7.4.5",
|
||||||
"@storybook/react": "6.5.6",
|
"@storybook/test-runner": "0.13.0",
|
||||||
"@storybook/testing-library": "0.0.13",
|
"@storybook/testing-library": "0.2.2",
|
||||||
"@types/backbone": "1.4.5",
|
"@types/backbone": "1.4.16",
|
||||||
"@types/blueimp-load-image": "5.14.1",
|
"@types/blueimp-load-image": "5.14.1",
|
||||||
"@types/chai": "4.2.18",
|
"@types/chai": "4.2.18",
|
||||||
"@types/chai-as-promised": "7.1.4",
|
"@types/chai-as-promised": "7.1.4",
|
||||||
|
@ -258,7 +258,7 @@
|
||||||
"asar": "3.1.0",
|
"asar": "3.1.0",
|
||||||
"axe-core": "4.1.4",
|
"axe-core": "4.1.4",
|
||||||
"babel-core": "7.0.0-bridge.0",
|
"babel-core": "7.0.0-bridge.0",
|
||||||
"babel-loader": "8.0.6",
|
"babel-loader": "9.1.3",
|
||||||
"babel-plugin-lodash": "3.3.4",
|
"babel-plugin-lodash": "3.3.4",
|
||||||
"casual": "1.6.2",
|
"casual": "1.6.2",
|
||||||
"chai": "4.3.4",
|
"chai": "4.3.4",
|
||||||
|
@ -285,19 +285,23 @@
|
||||||
"eslint-plugin-react": "7.31.10",
|
"eslint-plugin-react": "7.31.10",
|
||||||
"execa": "5.1.1",
|
"execa": "5.1.1",
|
||||||
"html-webpack-plugin": "5.3.1",
|
"html-webpack-plugin": "5.3.1",
|
||||||
|
"http-server": "14.1.1",
|
||||||
"json-to-ast": "2.1.0",
|
"json-to-ast": "2.1.0",
|
||||||
|
"mini-css-extract-plugin": "2.7.6",
|
||||||
"mocha": "9.1.3",
|
"mocha": "9.1.3",
|
||||||
"node-gyp": "9.0.0",
|
"node-gyp": "9.0.0",
|
||||||
"npm-run-all": "4.1.5",
|
"npm-run-all": "4.1.5",
|
||||||
"nyc": "11.4.1",
|
"nyc": "11.4.1",
|
||||||
"p-limit": "3.1.0",
|
"p-limit": "3.1.0",
|
||||||
"patch-package": "6.4.7",
|
"patch-package": "8.0.0",
|
||||||
"playwright": "1.33.0",
|
"playwright": "1.33.0",
|
||||||
"prettier": "2.8.0",
|
"prettier": "2.8.0",
|
||||||
"protobufjs-cli": "1.1.1",
|
"protobufjs-cli": "1.1.1",
|
||||||
|
"resolve-url-loader": "5.0.0",
|
||||||
"sass": "1.49.7",
|
"sass": "1.49.7",
|
||||||
"sass-loader": "10.2.0",
|
"sass-loader": "10.2.0",
|
||||||
"sinon": "11.1.1",
|
"sinon": "11.1.1",
|
||||||
|
"storybook": "7.4.5",
|
||||||
"style-loader": "1.0.0",
|
"style-loader": "1.0.0",
|
||||||
"stylelint": "15.4.0",
|
"stylelint": "15.4.0",
|
||||||
"stylelint-config-css-modules": "4.2.0",
|
"stylelint-config-css-modules": "4.2.0",
|
||||||
|
@ -309,7 +313,8 @@
|
||||||
"ts-node": "8.3.0",
|
"ts-node": "8.3.0",
|
||||||
"typed-scss-modules": "4.1.1",
|
"typed-scss-modules": "4.1.1",
|
||||||
"typescript": "5.1.3",
|
"typescript": "5.1.3",
|
||||||
"webpack": "5.76.0",
|
"wait-on": "7.0.1",
|
||||||
|
"webpack": "5.88.2",
|
||||||
"webpack-cli": "4.9.2",
|
"webpack-cli": "4.9.2",
|
||||||
"webpack-dev-server": "4.11.1"
|
"webpack-dev-server": "4.11.1"
|
||||||
},
|
},
|
||||||
|
|
13
patches/@storybook+manager-api+7.4.5.patch
Normal file
13
patches/@storybook+manager-api+7.4.5.patch
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
diff --git a/node_modules/@storybook/manager-api/dist/index.d.ts b/node_modules/@storybook/manager-api/dist/index.d.ts
|
||||||
|
index 7afb86e..a15b801 100644
|
||||||
|
--- a/node_modules/@storybook/manager-api/dist/index.d.ts
|
||||||
|
+++ b/node_modules/@storybook/manager-api/dist/index.d.ts
|
||||||
|
@@ -822,7 +822,7 @@ declare class ManagerProvider extends Component<ManagerProviderProps, State> {
|
||||||
|
static getDerivedStateFromProps(props: ManagerProviderProps, state: State): State;
|
||||||
|
shouldComponentUpdate(nextProps: ManagerProviderProps, nextState: State): boolean;
|
||||||
|
initModules: () => void;
|
||||||
|
- render(): React.JSX.Element;
|
||||||
|
+ render(): JSX.Element;
|
||||||
|
}
|
||||||
|
interface ManagerConsumerProps<P = unknown> {
|
||||||
|
filter?: (combo: Combo) => P;
|
22
patches/@storybook+router+7.4.5.patch
Normal file
22
patches/@storybook+router+7.4.5.patch
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
diff --git a/node_modules/@storybook/router/dist/index.d.ts b/node_modules/@storybook/router/dist/index.d.ts
|
||||||
|
index ed699f7..71f48eb 100644
|
||||||
|
--- a/node_modules/@storybook/router/dist/index.d.ts
|
||||||
|
+++ b/node_modules/@storybook/router/dist/index.d.ts
|
||||||
|
@@ -335,7 +335,7 @@ declare const useNavigate: () => (to: To | number, { plain, ...options }?: any)
|
||||||
|
* A component that will navigate to a new location/path when clicked
|
||||||
|
*/
|
||||||
|
declare const Link: {
|
||||||
|
- ({ to, children, ...rest }: LinkProps): React__default.JSX.Element;
|
||||||
|
+ ({ to, children, ...rest }: LinkProps): JSX.Element;
|
||||||
|
displayName: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
@@ -343,7 +343,7 @@ declare const Link: {
|
||||||
|
* and will be called whenever it changes when it changes
|
||||||
|
*/
|
||||||
|
declare const Location: {
|
||||||
|
- ({ children }: LocationProps): React__default.JSX.Element;
|
||||||
|
+ ({ children }: LocationProps): JSX.Element;
|
||||||
|
displayName: string;
|
||||||
|
};
|
||||||
|
/**
|
49
patches/@types+backbone+1.4.16.patch
Normal file
49
patches/@types+backbone+1.4.16.patch
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
diff --git a/node_modules/@types/backbone/index.d.ts b/node_modules/@types/backbone/index.d.ts
|
||||||
|
index 3935075..22a4c2e 100644
|
||||||
|
--- a/node_modules/@types/backbone/index.d.ts
|
||||||
|
+++ b/node_modules/@types/backbone/index.d.ts
|
||||||
|
@@ -81,7 +81,7 @@ declare namespace Backbone {
|
||||||
|
collection?: Collection<TModel> | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
- type CombinedModelConstructorOptions<E, M extends Model<any, any, E> = Model> = ModelConstructorOptions<M> & E;
|
||||||
|
+ type CombinedModelConstructorOptions<E, M extends Model<any, any, E> = Model<any, any, E>> = ModelConstructorOptions<M> & E;
|
||||||
|
|
||||||
|
interface ModelSetOptions extends Silenceable, Validable {}
|
||||||
|
|
||||||
|
@@ -219,7 +219,7 @@ declare namespace Backbone {
|
||||||
|
*/
|
||||||
|
static extend(properties: any, classProperties?: any): any;
|
||||||
|
|
||||||
|
- attributes: Partial<T>;
|
||||||
|
+ attributes: T;
|
||||||
|
changed: Partial<T>;
|
||||||
|
cidPrefix: string;
|
||||||
|
cid: string;
|
||||||
|
@@ -235,7 +235,7 @@ declare namespace Backbone {
|
||||||
|
* That works only if you set it in the constructor or the initialize method.
|
||||||
|
*/
|
||||||
|
defaults(): Partial<T>;
|
||||||
|
- id: string | number;
|
||||||
|
+ id: string;
|
||||||
|
idAttribute: string;
|
||||||
|
validationError: any;
|
||||||
|
|
||||||
|
@@ -266,7 +266,7 @@ declare namespace Backbone {
|
||||||
|
* return super.get("name");
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
- get<A extends _StringKey<T>>(attributeName: A): T[A] | undefined;
|
||||||
|
+ get<A extends _StringKey<T>>(attributeName: A): T[A];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For strongly-typed assignment of attributes, use the `set` method only privately in public setter properties.
|
||||||
|
@@ -300,7 +300,7 @@ declare namespace Backbone {
|
||||||
|
previousAttributes(): Partial<T>;
|
||||||
|
save(attributes?: Partial<T> | null, options?: ModelSaveOptions): JQueryXHR;
|
||||||
|
unset(attribute: _StringKey<T>, options?: Silenceable): this;
|
||||||
|
- validate(attributes: Partial<T>, options?: any): any;
|
||||||
|
+ validate(attributes: T, options?: any): any;
|
||||||
|
private _validate(attributes: Partial<T>, options: any): boolean;
|
||||||
|
|
||||||
|
// mixins from underscore
|
|
@ -1,30 +0,0 @@
|
||||||
diff --git a/node_modules/@types/backbone/index.d.ts b/node_modules/@types/backbone/index.d.ts
|
|
||||||
index a172230..2c62e92 100644
|
|
||||||
--- a/node_modules/@types/backbone/index.d.ts
|
|
||||||
+++ b/node_modules/@types/backbone/index.d.ts
|
|
||||||
@@ -81,7 +81,7 @@ declare namespace Backbone {
|
|
||||||
collection?: Backbone.Collection<TModel>;
|
|
||||||
}
|
|
||||||
|
|
||||||
- type CombinedModelConstructorOptions<E, M extends Model<any, any, E> = Model> = ModelConstructorOptions<M> & E;
|
|
||||||
+ type CombinedModelConstructorOptions<E, M extends Model<any, any, E> = Model<any, any, E>> = ModelConstructorOptions<M> & E;
|
|
||||||
|
|
||||||
interface ModelSetOptions extends Silenceable, Validable {
|
|
||||||
}
|
|
||||||
@@ -218,14 +218,14 @@ declare namespace Backbone {
|
|
||||||
* E - Extensions to the model constructor options. You can accept additional constructor options
|
|
||||||
* by listing them in the E parameter.
|
|
||||||
*/
|
|
||||||
- class Model<T = any, S = Backbone.ModelSetOptions, E = {}> extends ModelBase implements Events {
|
|
||||||
+ class Model<T extends Record<string, any> = any, S = Backbone.ModelSetOptions, E = {}> extends ModelBase implements Events {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do not use, prefer TypeScript's extend functionality.
|
|
||||||
**/
|
|
||||||
public static extend(properties: any, classProperties?: any): any;
|
|
||||||
|
|
||||||
- attributes: any;
|
|
||||||
+ attributes: T;
|
|
||||||
changed: any[];
|
|
||||||
cidPrefix: string;
|
|
||||||
cid: string;
|
|
|
@ -1,10 +1,10 @@
|
||||||
diff --git a/node_modules/@types/jest/index.d.ts b/node_modules/@types/jest/index.d.ts
|
diff --git a/node_modules/@types/jest/index.d.ts b/node_modules/@types/jest/index.d.ts
|
||||||
index 272822a..87ebd1f 100755
|
index b37b188..1908c0c 100755
|
||||||
--- a/node_modules/@types/jest/index.d.ts
|
--- a/node_modules/@types/jest/index.d.ts
|
||||||
+++ b/node_modules/@types/jest/index.d.ts
|
+++ b/node_modules/@types/jest/index.d.ts
|
||||||
@@ -30,18 +30,18 @@
|
@@ -30,18 +30,18 @@
|
||||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||||
// Minimum TypeScript Version: 3.8
|
// Minimum TypeScript Version: 4.3
|
||||||
|
|
||||||
-declare var beforeAll: jest.Lifecycle;
|
-declare var beforeAll: jest.Lifecycle;
|
||||||
-declare var beforeEach: jest.Lifecycle;
|
-declare var beforeEach: jest.Lifecycle;
|
|
@ -13,8 +13,6 @@ import { getBytesSubarray } from './util/uuidToBytes';
|
||||||
|
|
||||||
export { HashType, CipherType };
|
export { HashType, CipherType };
|
||||||
|
|
||||||
export const UUID_BYTE_SIZE = 16;
|
|
||||||
|
|
||||||
const PROFILE_IV_LENGTH = 12; // bytes
|
const PROFILE_IV_LENGTH = 12; // bytes
|
||||||
const PROFILE_KEY_LENGTH = 32; // bytes
|
const PROFILE_KEY_LENGTH = 32; // bytes
|
||||||
|
|
||||||
|
|
|
@ -3288,13 +3288,14 @@ export async function startApp(): Promise<void> {
|
||||||
'onDeliveryReceipt: missing valid sourceServiceId'
|
'onDeliveryReceipt: missing valid sourceServiceId'
|
||||||
);
|
);
|
||||||
strictAssert(sourceDevice, 'onDeliveryReceipt: missing sourceDevice');
|
strictAssert(sourceDevice, 'onDeliveryReceipt: missing sourceDevice');
|
||||||
|
strictAssert(sourceConversation, 'onDeliveryReceipt: missing conversation');
|
||||||
|
|
||||||
const attributes: MessageReceiptAttributesType = {
|
const attributes: MessageReceiptAttributesType = {
|
||||||
envelopeId: ev.deliveryReceipt.envelopeId,
|
envelopeId: ev.deliveryReceipt.envelopeId,
|
||||||
removeFromMessageReceiverCache: ev.confirm,
|
removeFromMessageReceiverCache: ev.confirm,
|
||||||
messageSentAt: timestamp,
|
messageSentAt: timestamp,
|
||||||
receiptTimestamp: envelopeTimestamp,
|
receiptTimestamp: envelopeTimestamp,
|
||||||
sourceConversationId: sourceConversation?.id,
|
sourceConversationId: sourceConversation.id,
|
||||||
sourceServiceId,
|
sourceServiceId,
|
||||||
sourceDevice,
|
sourceDevice,
|
||||||
type: MessageReceipts.MessageReceiptType.Delivery,
|
type: MessageReceipts.MessageReceiptType.Delivery,
|
||||||
|
|
|
@ -5,8 +5,10 @@ import React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
import type { PropsType } from './AddGroupMemberErrorDialog';
|
||||||
import {
|
import {
|
||||||
AddGroupMemberErrorDialog,
|
AddGroupMemberErrorDialog,
|
||||||
AddGroupMemberErrorDialogMode,
|
AddGroupMemberErrorDialogMode,
|
||||||
|
@ -16,24 +18,22 @@ const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/AddGroupMemberErrorDialog',
|
title: 'Components/AddGroupMemberErrorDialog',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
i18n,
|
i18n,
|
||||||
onClose: action('onClose'),
|
onClose: action('onClose'),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const _MaximumGroupSize = (): JSX.Element => (
|
export function MaximumGroupSize(): JSX.Element {
|
||||||
<AddGroupMemberErrorDialog
|
return (
|
||||||
{...defaultProps}
|
<AddGroupMemberErrorDialog
|
||||||
mode={AddGroupMemberErrorDialogMode.MaximumGroupSize}
|
{...defaultProps}
|
||||||
maximumNumberOfContacts={123}
|
mode={AddGroupMemberErrorDialogMode.MaximumGroupSize}
|
||||||
/>
|
maximumNumberOfContacts={123}
|
||||||
);
|
/>
|
||||||
|
);
|
||||||
_MaximumGroupSize.story = {
|
}
|
||||||
name: 'Maximum group size',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function MaximumRecommendedGroupSize(): JSX.Element {
|
export function MaximumRecommendedGroupSize(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
@ -44,7 +44,3 @@ export function MaximumRecommendedGroupSize(): JSX.Element {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
MaximumRecommendedGroupSize.story = {
|
|
||||||
name: 'Maximum recommended group size',
|
|
||||||
};
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ type PropsDataType =
|
||||||
recommendedMaximumNumberOfContacts: number;
|
recommendedMaximumNumberOfContacts: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type PropsType = {
|
export type PropsType = {
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
} & PropsDataType;
|
} & PropsDataType;
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
// Copyright 2022 Signal Messenger, LLC
|
// Copyright 2022 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React from 'react';
|
import React, { useContext } from 'react';
|
||||||
import type { Meta, Story } from '@storybook/react';
|
import type { Meta, StoryFn } from '@storybook/react';
|
||||||
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
import type { Props } from './AddUserToAnotherGroupModal';
|
import type { Props } from './AddUserToAnotherGroupModal';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
@ -19,28 +20,25 @@ const i18n = setupI18n('en', enMessages);
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/AddUserToAnotherGroupModal',
|
title: 'Components/AddUserToAnotherGroupModal',
|
||||||
component: AddUserToAnotherGroupModal,
|
component: AddUserToAnotherGroupModal,
|
||||||
argTypes: {
|
args: {
|
||||||
candidateConversations: {
|
i18n,
|
||||||
defaultValue: Array.from(Array(100), () => getDefaultGroup()),
|
candidateConversations: Array.from(Array(100), () => getDefaultGroup()),
|
||||||
},
|
contact: getDefaultConversation(),
|
||||||
contact: {
|
|
||||||
defaultValue: getDefaultConversation(),
|
|
||||||
},
|
|
||||||
i18n: {
|
|
||||||
defaultValue: i18n,
|
|
||||||
},
|
|
||||||
addMembersToGroup: { action: true },
|
|
||||||
toggleAddUserToAnotherGroupModal: { action: true },
|
|
||||||
},
|
},
|
||||||
} as Meta;
|
} satisfies Meta<Props>;
|
||||||
|
|
||||||
// eslint-disable-next-line react/function-component-definition
|
// eslint-disable-next-line react/function-component-definition
|
||||||
const Template: Story<Props> = args => (
|
const Template: StoryFn<Props> = args => {
|
||||||
<AddUserToAnotherGroupModal
|
return (
|
||||||
{...args}
|
<AddUserToAnotherGroupModal
|
||||||
theme={React.useContext(StorybookThemeContext)}
|
{...args}
|
||||||
/>
|
addMembersToGroup={action('addMembersToGroup')}
|
||||||
);
|
toggleAddUserToAnotherGroupModal={action(
|
||||||
|
'toggleAddUserToAnotherGroupModal'
|
||||||
|
)}
|
||||||
|
theme={useContext(StorybookThemeContext)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const Modal = Template.bind({});
|
export const Modal = Template.bind({});
|
||||||
Modal.args = {};
|
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
import type { PropsType } from './Alert';
|
||||||
import { Alert } from './Alert';
|
import { Alert } from './Alert';
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/Alert',
|
title: 'Components/Alert',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
i18n,
|
i18n,
|
||||||
|
@ -33,10 +33,6 @@ export function TitleAndBodyAreStrings(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
TitleAndBodyAreStrings.story = {
|
|
||||||
name: 'Title and body are strings',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function BodyIsAReactNode(): JSX.Element {
|
export function BodyIsAReactNode(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Alert
|
<Alert
|
||||||
|
@ -52,10 +48,6 @@ export function BodyIsAReactNode(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
BodyIsAReactNode.story = {
|
|
||||||
name: 'Body is a ReactNode',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function LongBodyWithoutTitle(): JSX.Element {
|
export function LongBodyWithoutTitle(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Alert
|
<Alert
|
||||||
|
@ -72,10 +64,6 @@ export function LongBodyWithoutTitle(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
LongBodyWithoutTitle.story = {
|
|
||||||
name: 'Long body (without title)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function LongBodyWithTitle(): JSX.Element {
|
export function LongBodyWithTitle(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Alert
|
<Alert
|
||||||
|
@ -92,7 +80,3 @@ export function LongBodyWithTitle(): JSX.Element {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
LongBodyWithTitle.story = {
|
|
||||||
name: 'Long body (with title)',
|
|
||||||
};
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import type { Theme } from '../util/theme';
|
||||||
import { Button } from './Button';
|
import { Button } from './Button';
|
||||||
import { Modal } from './Modal';
|
import { Modal } from './Modal';
|
||||||
|
|
||||||
type PropsType = {
|
export type PropsType = {
|
||||||
body: ReactNode;
|
body: ReactNode;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
|
|
@ -4,12 +4,13 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import type { PropsType } from './AnimatedEmojiGalore';
|
import type { PropsType } from './AnimatedEmojiGalore';
|
||||||
import { AnimatedEmojiGalore } from './AnimatedEmojiGalore';
|
import { AnimatedEmojiGalore } from './AnimatedEmojiGalore';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/AnimatedEmojiGalore',
|
title: 'Components/AnimatedEmojiGalore',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
function getDefaultProps(): PropsType {
|
function getDefaultProps(): PropsType {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
// Copyright 2020 Signal Messenger, LLC
|
// Copyright 2020 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { Meta, Story } from '@storybook/react';
|
import type { Meta, StoryFn } from '@storybook/react';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import { expect } from '@storybook/jest';
|
import { expect, jest } from '@storybook/jest';
|
||||||
import { isBoolean } from 'lodash';
|
import { isBoolean } from 'lodash';
|
||||||
import { within, userEvent } from '@storybook/testing-library';
|
import { within, userEvent } from '@storybook/testing-library';
|
||||||
|
|
||||||
import type { AvatarColorType } from '../types/Colors';
|
import type { AvatarColorType } from '../types/Colors';
|
||||||
import type { Props } from './Avatar';
|
import type { Props } from './Avatar';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
@ -42,7 +41,6 @@ export default {
|
||||||
},
|
},
|
||||||
blur: {
|
blur: {
|
||||||
control: { type: 'radio' },
|
control: { type: 'radio' },
|
||||||
defaultValue: undefined,
|
|
||||||
options: {
|
options: {
|
||||||
Undefined: undefined,
|
Undefined: undefined,
|
||||||
NoBlur: AvatarBlur.NoBlur,
|
NoBlur: AvatarBlur.NoBlur,
|
||||||
|
@ -51,14 +49,12 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
color: {
|
color: {
|
||||||
defaultValue: AvatarColors[0],
|
|
||||||
options: colorMap,
|
options: colorMap,
|
||||||
},
|
},
|
||||||
conversationType: {
|
conversationType: {
|
||||||
control: { type: 'radio' },
|
control: { type: 'radio' },
|
||||||
options: conversationTypeMap,
|
options: conversationTypeMap,
|
||||||
},
|
},
|
||||||
onClick: { action: true },
|
|
||||||
size: {
|
size: {
|
||||||
control: false,
|
control: false,
|
||||||
},
|
},
|
||||||
|
@ -68,11 +64,16 @@ export default {
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
control: { type: 'radio' },
|
control: { type: 'radio' },
|
||||||
defaultValue: ThemeType.light,
|
|
||||||
options: ThemeType,
|
options: ThemeType,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as Meta;
|
args: {
|
||||||
|
blur: undefined,
|
||||||
|
color: AvatarColors[0],
|
||||||
|
onClick: action('onClick'),
|
||||||
|
theme: ThemeType.light,
|
||||||
|
},
|
||||||
|
} satisfies Meta<Props>;
|
||||||
|
|
||||||
const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||||
acceptedMessageRequest: isBoolean(overrideProps.acceptedMessageRequest)
|
acceptedMessageRequest: isBoolean(overrideProps.acceptedMessageRequest)
|
||||||
|
@ -87,7 +88,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||||
isMe: false,
|
isMe: false,
|
||||||
loading: Boolean(overrideProps.loading),
|
loading: Boolean(overrideProps.loading),
|
||||||
noteToSelf: Boolean(overrideProps.noteToSelf),
|
noteToSelf: Boolean(overrideProps.noteToSelf),
|
||||||
onClick: action('onClick'),
|
onClick: jest.fn(action('onClick')),
|
||||||
onClickBadge: action('onClickBadge'),
|
onClickBadge: action('onClickBadge'),
|
||||||
phoneNumber: overrideProps.phoneNumber || '',
|
phoneNumber: overrideProps.phoneNumber || '',
|
||||||
searchResult: Boolean(overrideProps.searchResult),
|
searchResult: Boolean(overrideProps.searchResult),
|
||||||
|
@ -103,16 +104,18 @@ const sizes = Object.values(AvatarSize).filter(
|
||||||
) as Array<AvatarSize>;
|
) as Array<AvatarSize>;
|
||||||
|
|
||||||
// eslint-disable-next-line react/function-component-definition
|
// eslint-disable-next-line react/function-component-definition
|
||||||
const Template: Story<Props> = args => (
|
const Template: StoryFn<Props> = (args: Props) => {
|
||||||
<>
|
return (
|
||||||
{sizes.map(size => (
|
<>
|
||||||
<Avatar key={size} {...args} size={size} />
|
{sizes.map(size => (
|
||||||
))}
|
<Avatar key={size} {...args} size={size} />
|
||||||
</>
|
))}
|
||||||
);
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line react/function-component-definition
|
// eslint-disable-next-line react/function-component-definition
|
||||||
const TemplateSingle: Story<Props> = args => (
|
const TemplateSingle: StoryFn<Props> = (args: Props) => (
|
||||||
<Avatar {...args} size={AvatarSize.EIGHTY} />
|
<Avatar {...args} size={AvatarSize.EIGHTY} />
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -120,72 +123,50 @@ export const Default = Template.bind({});
|
||||||
Default.args = createProps({
|
Default.args = createProps({
|
||||||
avatarPath: '/fixtures/giphy-GVNvOUpeYmI7e.gif',
|
avatarPath: '/fixtures/giphy-GVNvOUpeYmI7e.gif',
|
||||||
});
|
});
|
||||||
Default.play = async ({ args, canvasElement }) => {
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
Default.play = async (context: any) => {
|
||||||
|
const { args, canvasElement } = context;
|
||||||
const canvas = within(canvasElement);
|
const canvas = within(canvasElement);
|
||||||
const [avatar] = canvas.getAllByRole('button');
|
const [avatar] = canvas.getAllByRole('button');
|
||||||
await userEvent.click(avatar);
|
await userEvent.click(avatar);
|
||||||
await expect(args.onClick).toHaveBeenCalled();
|
await expect(args.onClick).toHaveBeenCalled();
|
||||||
};
|
};
|
||||||
Default.story = {
|
|
||||||
name: 'Avatar',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const WithBadge = Template.bind({});
|
export const WithBadge = Template.bind({});
|
||||||
WithBadge.args = createProps({
|
WithBadge.args = createProps({
|
||||||
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
||||||
badge: getFakeBadge(),
|
badge: getFakeBadge(),
|
||||||
});
|
});
|
||||||
WithBadge.story = {
|
|
||||||
name: 'With badge',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const WideImage = Template.bind({});
|
export const WideImage = Template.bind({});
|
||||||
WideImage.args = createProps({
|
WideImage.args = createProps({
|
||||||
avatarPath: '/fixtures/wide.jpg',
|
avatarPath: '/fixtures/wide.jpg',
|
||||||
});
|
});
|
||||||
WideImage.story = {
|
|
||||||
name: 'Wide image',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const OneWordName = Template.bind({});
|
export const OneWordName = Template.bind({});
|
||||||
OneWordName.args = createProps({
|
OneWordName.args = createProps({
|
||||||
title: 'John',
|
title: 'John',
|
||||||
});
|
});
|
||||||
OneWordName.story = {
|
|
||||||
name: 'One-word Name',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const TwoWordName = Template.bind({});
|
export const TwoWordName = Template.bind({});
|
||||||
TwoWordName.args = createProps({
|
TwoWordName.args = createProps({
|
||||||
title: 'John Smith',
|
title: 'John Smith',
|
||||||
});
|
});
|
||||||
TwoWordName.story = {
|
|
||||||
name: 'Two-word Name',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const WideInitials = Template.bind({});
|
export const WideInitials = Template.bind({});
|
||||||
WideInitials.args = createProps({
|
WideInitials.args = createProps({
|
||||||
title: 'Walter White',
|
title: 'Walter White',
|
||||||
});
|
});
|
||||||
WideInitials.story = {
|
|
||||||
name: 'Wide initials',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ThreeWordName = Template.bind({});
|
export const ThreeWordName = Template.bind({});
|
||||||
ThreeWordName.args = createProps({
|
ThreeWordName.args = createProps({
|
||||||
title: 'Walter H. White',
|
title: 'Walter H. White',
|
||||||
});
|
});
|
||||||
ThreeWordName.story = {
|
|
||||||
name: 'Three-word name',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const NoteToSelf = Template.bind({});
|
export const NoteToSelf = Template.bind({});
|
||||||
NoteToSelf.args = createProps({
|
NoteToSelf.args = createProps({
|
||||||
noteToSelf: true,
|
noteToSelf: true,
|
||||||
});
|
});
|
||||||
NoteToSelf.story = {
|
|
||||||
name: 'Note to Self',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ContactIcon = Template.bind({});
|
export const ContactIcon = Template.bind({});
|
||||||
ContactIcon.args = createProps();
|
ContactIcon.args = createProps();
|
||||||
|
@ -227,9 +208,6 @@ BrokenAvatarForGroup.args = createProps({
|
||||||
avatarPath: 'badimage.png',
|
avatarPath: 'badimage.png',
|
||||||
conversationType: 'group',
|
conversationType: 'group',
|
||||||
});
|
});
|
||||||
BrokenAvatarForGroup.story = {
|
|
||||||
name: 'Broken Avatar for Group',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Loading = Template.bind({});
|
export const Loading = Template.bind({});
|
||||||
Loading.args = createProps({
|
Loading.args = createProps({
|
||||||
|
@ -242,42 +220,26 @@ BlurredBasedOnProps.args = createProps({
|
||||||
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
||||||
});
|
});
|
||||||
|
|
||||||
BlurredBasedOnProps.story = {
|
|
||||||
name: 'Blurred based on props',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ForceBlurred = TemplateSingle.bind({});
|
export const ForceBlurred = TemplateSingle.bind({});
|
||||||
ForceBlurred.args = createProps({
|
ForceBlurred.args = createProps({
|
||||||
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
||||||
blur: AvatarBlur.BlurPicture,
|
blur: AvatarBlur.BlurPicture,
|
||||||
});
|
});
|
||||||
ForceBlurred.story = {
|
|
||||||
name: 'Force-blurred',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const BlurredWithClickToView = TemplateSingle.bind({});
|
export const BlurredWithClickToView = TemplateSingle.bind({});
|
||||||
BlurredWithClickToView.args = createProps({
|
BlurredWithClickToView.args = createProps({
|
||||||
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
||||||
blur: AvatarBlur.BlurPictureWithClickToView,
|
blur: AvatarBlur.BlurPictureWithClickToView,
|
||||||
});
|
});
|
||||||
BlurredWithClickToView.story = {
|
|
||||||
name: 'Blurred with "click to view"',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const StoryUnread = TemplateSingle.bind({});
|
export const StoryUnread = TemplateSingle.bind({});
|
||||||
StoryUnread.args = createProps({
|
StoryUnread.args = createProps({
|
||||||
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
||||||
storyRing: HasStories.Unread,
|
storyRing: HasStories.Unread,
|
||||||
});
|
});
|
||||||
StoryUnread.story = {
|
|
||||||
name: 'Story: unread',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const StoryRead = TemplateSingle.bind({});
|
export const StoryRead = TemplateSingle.bind({});
|
||||||
StoryRead.args = createProps({
|
StoryRead.args = createProps({
|
||||||
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
||||||
storyRing: HasStories.Read,
|
storyRing: HasStories.Read,
|
||||||
});
|
});
|
||||||
StoryRead.story = {
|
|
||||||
name: 'Story: read',
|
|
||||||
};
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/AvatarColorPicker',
|
title: 'Components/AvatarColorPicker',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Default(): JSX.Element {
|
export function Default(): JSX.Element {
|
||||||
return <AvatarColorPicker {...createProps()} />;
|
return <AvatarColorPicker {...createProps()} />;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
|
@ -80,7 +81,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/AvatarEditor',
|
title: 'Components/AvatarEditor',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function NoAvatarGroup(): JSX.Element {
|
export function NoAvatarGroup(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
@ -93,20 +94,12 @@ export function NoAvatarGroup(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
NoAvatarGroup.story = {
|
|
||||||
name: 'No Avatar (group)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function NoAvatarMe(): JSX.Element {
|
export function NoAvatarMe(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<AvatarEditor {...createProps({ userAvatarData: getDefaultAvatars() })} />
|
<AvatarEditor {...createProps({ userAvatarData: getDefaultAvatars() })} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
NoAvatarMe.story = {
|
|
||||||
name: 'No Avatar (me)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function HasAvatar(): JSX.Element {
|
export function HasAvatar(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<AvatarEditor
|
<AvatarEditor
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/AvatarIconEditor',
|
title: 'Components/AvatarIconEditor',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function PersonalIcon(): JSX.Element {
|
export function PersonalIcon(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -2,10 +2,8 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import { select } from '@storybook/addon-knobs';
|
import type { Meta } from '@storybook/react';
|
||||||
|
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
import { AvatarColors } from '../types/Colors';
|
import { AvatarColors } from '../types/Colors';
|
||||||
import type { PropsType } from './AvatarLightbox';
|
import type { PropsType } from './AvatarLightbox';
|
||||||
|
@ -15,51 +13,37 @@ import { getDefaultConversation } from '../test-both/helpers/getDefaultConversat
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|
||||||
avatarColor: select(
|
|
||||||
'Color',
|
|
||||||
AvatarColors,
|
|
||||||
overrideProps.avatarColor || AvatarColors[0]
|
|
||||||
),
|
|
||||||
avatarPath: overrideProps.avatarPath,
|
|
||||||
conversationTitle: overrideProps.conversationTitle,
|
|
||||||
i18n,
|
|
||||||
isGroup: Boolean(overrideProps.isGroup),
|
|
||||||
onClose: action('onClose'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/AvatarLightbox',
|
title: 'Components/AvatarLightbox',
|
||||||
};
|
component: AvatarLightbox,
|
||||||
|
argTypes: {
|
||||||
|
avatarColor: {
|
||||||
|
control: { type: 'select' },
|
||||||
|
options: AvatarColors,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
i18n,
|
||||||
|
avatarColor: AvatarColors[0],
|
||||||
|
onClose: action('onClose'),
|
||||||
|
},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Group(): JSX.Element {
|
export function Group(args: PropsType): JSX.Element {
|
||||||
return (
|
return <AvatarLightbox {...args} isGroup />;
|
||||||
<AvatarLightbox
|
|
||||||
{...createProps({
|
|
||||||
isGroup: true,
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Person(): JSX.Element {
|
export function Person(args: PropsType): JSX.Element {
|
||||||
const conversation = getDefaultConversation();
|
const conversation = getDefaultConversation();
|
||||||
return (
|
return (
|
||||||
<AvatarLightbox
|
<AvatarLightbox
|
||||||
{...createProps({
|
{...args}
|
||||||
avatarColor: conversation.color,
|
avatarColor={conversation.color}
|
||||||
conversationTitle: conversation.title,
|
conversationTitle={conversation.title}
|
||||||
})}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Photo(): JSX.Element {
|
export function Photo(args: PropsType): JSX.Element {
|
||||||
return (
|
return <AvatarLightbox {...args} avatarPath="/fixtures/kitten-1-64-64.jpg" />;
|
||||||
<AvatarLightbox
|
|
||||||
{...createProps({
|
|
||||||
avatarPath: '/fixtures/kitten-1-64-64.jpg',
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
import type { PropsType } from './AvatarModalButtons';
|
import type { PropsType } from './AvatarModalButtons';
|
||||||
import { AvatarModalButtons } from './AvatarModalButtons';
|
import { AvatarModalButtons } from './AvatarModalButtons';
|
||||||
|
@ -21,7 +22,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/AvatarModalButtons',
|
title: 'Components/AvatarModalButtons',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function HasChanges(): JSX.Element {
|
export function HasChanges(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
@ -33,14 +34,6 @@ export function HasChanges(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
HasChanges.story = {
|
|
||||||
name: 'Has changes',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function NoChanges(): JSX.Element {
|
export function NoChanges(): JSX.Element {
|
||||||
return <AvatarModalButtons {...createProps()} />;
|
return <AvatarModalButtons {...createProps()} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
NoChanges.story = {
|
|
||||||
name: 'No changes',
|
|
||||||
};
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { chunk } from 'lodash';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import type { PropsType } from './AvatarPreview';
|
import type { PropsType } from './AvatarPreview';
|
||||||
import { AvatarPreview } from './AvatarPreview';
|
import { AvatarPreview } from './AvatarPreview';
|
||||||
import { AvatarColors } from '../types/Colors';
|
import { AvatarColors } from '../types/Colors';
|
||||||
|
@ -37,7 +38,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/AvatarPreview',
|
title: 'Components/AvatarPreview',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function NoStatePersonal(): JSX.Element {
|
export function NoStatePersonal(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
@ -50,10 +51,6 @@ export function NoStatePersonal(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
NoStatePersonal.story = {
|
|
||||||
name: 'No state (personal)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function NoStateGroup(): JSX.Element {
|
export function NoStateGroup(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<AvatarPreview
|
<AvatarPreview
|
||||||
|
@ -65,10 +62,6 @@ export function NoStateGroup(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
NoStateGroup.story = {
|
|
||||||
name: 'No state (group)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function NoStateGroupUploadMe(): JSX.Element {
|
export function NoStateGroupUploadMe(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<AvatarPreview
|
<AvatarPreview
|
||||||
|
@ -81,18 +74,10 @@ export function NoStateGroupUploadMe(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
NoStateGroupUploadMe.story = {
|
|
||||||
name: 'No state (group) + upload me',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Value(): JSX.Element {
|
export function Value(): JSX.Element {
|
||||||
return <AvatarPreview {...createProps({ avatarValue: TEST_IMAGE })} />;
|
return <AvatarPreview {...createProps({ avatarValue: TEST_IMAGE })} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value.story = {
|
|
||||||
name: 'value',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Path(): JSX.Element {
|
export function Path(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<AvatarPreview
|
<AvatarPreview
|
||||||
|
@ -101,11 +86,7 @@ export function Path(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Path.story = {
|
export function ValueAndPath(): JSX.Element {
|
||||||
name: 'path',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ValuePath(): JSX.Element {
|
|
||||||
return (
|
return (
|
||||||
<AvatarPreview
|
<AvatarPreview
|
||||||
{...createProps({
|
{...createProps({
|
||||||
|
@ -116,10 +97,6 @@ export function ValuePath(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ValuePath.story = {
|
|
||||||
name: 'value & path',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Style(): JSX.Element {
|
export function Style(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<AvatarPreview
|
<AvatarPreview
|
||||||
|
@ -130,7 +107,3 @@ export function Style(): JSX.Element {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Style.story = {
|
|
||||||
name: 'style',
|
|
||||||
};
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
|
@ -22,7 +23,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/AvatarTextEditor',
|
title: 'Components/AvatarTextEditor',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Empty(): JSX.Element {
|
export function Empty(): JSX.Element {
|
||||||
return <AvatarTextEditor {...createProps()} />;
|
return <AvatarTextEditor {...createProps()} />;
|
||||||
|
@ -42,10 +43,6 @@ export function WithData(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
WithData.story = {
|
|
||||||
name: 'with Data',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function WithWideCharacters(): JSX.Element {
|
export function WithWideCharacters(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<AvatarTextEditor
|
<AvatarTextEditor
|
||||||
|
@ -59,7 +56,3 @@ export function WithWideCharacters(): JSX.Element {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
WithWideCharacters.story = {
|
|
||||||
name: 'with wide characters',
|
|
||||||
};
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/AvatarUploadButton',
|
title: 'Components/AvatarUploadButton',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Default(): JSX.Element {
|
export function Default(): JSX.Element {
|
||||||
return <AvatarUploadButton {...createProps()} />;
|
return <AvatarUploadButton {...createProps()} />;
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
|
import type { Props } from './BadgeDescription';
|
||||||
import { BadgeDescription } from './BadgeDescription';
|
import { BadgeDescription } from './BadgeDescription';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/BadgeDescription',
|
title: 'Components/BadgeDescription',
|
||||||
};
|
} satisfies Meta<Props>;
|
||||||
|
|
||||||
export function NormalName(): JSX.Element {
|
export function NormalName(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
@ -19,11 +21,7 @@ export function NormalName(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
NormalName.story = {
|
export function NameWithRTLOverrides(): JSX.Element {
|
||||||
name: 'Normal name',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function NameWithRtlOverrides(): JSX.Element {
|
|
||||||
return (
|
return (
|
||||||
<BadgeDescription
|
<BadgeDescription
|
||||||
template="Hello, {short_name}! {short_name}, I think you're great."
|
template="Hello, {short_name}! {short_name}, I think you're great."
|
||||||
|
@ -31,7 +29,3 @@ export function NameWithRtlOverrides(): JSX.Element {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
NameWithRtlOverrides.story = {
|
|
||||||
name: 'Name with RTL overrides',
|
|
||||||
};
|
|
||||||
|
|
|
@ -5,15 +5,17 @@ import type { ReactChild, ReactElement } from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ContactName } from './conversation/ContactName';
|
import { ContactName } from './conversation/ContactName';
|
||||||
|
|
||||||
|
export type Props = Readonly<{
|
||||||
|
firstName?: string;
|
||||||
|
template: string;
|
||||||
|
title: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
export function BadgeDescription({
|
export function BadgeDescription({
|
||||||
firstName,
|
firstName,
|
||||||
template,
|
template,
|
||||||
title,
|
title,
|
||||||
}: Readonly<{
|
}: Props): ReactElement {
|
||||||
firstName?: string;
|
|
||||||
template: string;
|
|
||||||
title: string;
|
|
||||||
}>): ReactElement {
|
|
||||||
const result: Array<ReactChild> = [];
|
const result: Array<ReactChild> = [];
|
||||||
|
|
||||||
let lastIndex = 0;
|
let lastIndex = 0;
|
||||||
|
|
|
@ -5,18 +5,20 @@ import type { ComponentProps } from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
import { getFakeBadge, getFakeBadges } from '../test-both/helpers/getFakeBadge';
|
import { getFakeBadge, getFakeBadges } from '../test-both/helpers/getFakeBadge';
|
||||||
import { repeat, zipObject } from '../util/iterables';
|
import { repeat, zipObject } from '../util/iterables';
|
||||||
import { BadgeImageTheme } from '../badges/BadgeImageTheme';
|
import { BadgeImageTheme } from '../badges/BadgeImageTheme';
|
||||||
|
import type { PropsType } from './BadgeDialog';
|
||||||
import { BadgeDialog } from './BadgeDialog';
|
import { BadgeDialog } from './BadgeDialog';
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/BadgeDialog',
|
title: 'Components/BadgeDialog',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
const defaultProps: ComponentProps<typeof BadgeDialog> = {
|
const defaultProps: ComponentProps<typeof BadgeDialog> = {
|
||||||
areWeASubscriber: false,
|
areWeASubscriber: false,
|
||||||
|
@ -31,18 +33,10 @@ export function NoBadgesClosedImmediately(): JSX.Element {
|
||||||
return <BadgeDialog {...defaultProps} badges={[]} />;
|
return <BadgeDialog {...defaultProps} badges={[]} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
NoBadgesClosedImmediately.story = {
|
|
||||||
name: 'No badges (closed immediately)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function OneBadge(): JSX.Element {
|
export function OneBadge(): JSX.Element {
|
||||||
return <BadgeDialog {...defaultProps} badges={getFakeBadges(1)} />;
|
return <BadgeDialog {...defaultProps} badges={getFakeBadges(1)} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
OneBadge.story = {
|
|
||||||
name: 'One badge',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function BadgeWithNoImageShouldBeImpossible(): JSX.Element {
|
export function BadgeWithNoImageShouldBeImpossible(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<BadgeDialog
|
<BadgeDialog
|
||||||
|
@ -57,10 +51,6 @@ export function BadgeWithNoImageShouldBeImpossible(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
BadgeWithNoImageShouldBeImpossible.story = {
|
|
||||||
name: 'Badge with no image (should be impossible)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function BadgeWithPendingImage(): JSX.Element {
|
export function BadgeWithPendingImage(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<BadgeDialog
|
<BadgeDialog
|
||||||
|
@ -80,10 +70,6 @@ export function BadgeWithPendingImage(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
BadgeWithPendingImage.story = {
|
|
||||||
name: 'Badge with pending image',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function BadgeWithOnlyOneLowDetailImage(): JSX.Element {
|
export function BadgeWithOnlyOneLowDetailImage(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<BadgeDialog
|
<BadgeDialog
|
||||||
|
@ -112,26 +98,14 @@ export function BadgeWithOnlyOneLowDetailImage(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
BadgeWithOnlyOneLowDetailImage.story = {
|
|
||||||
name: 'Badge with only one, low-detail image',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function FiveBadges(): JSX.Element {
|
export function FiveBadges(): JSX.Element {
|
||||||
return <BadgeDialog {...defaultProps} badges={getFakeBadges(5)} />;
|
return <BadgeDialog {...defaultProps} badges={getFakeBadges(5)} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
FiveBadges.story = {
|
|
||||||
name: 'Five badges',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ManyBadges(): JSX.Element {
|
export function ManyBadges(): JSX.Element {
|
||||||
return <BadgeDialog {...defaultProps} badges={getFakeBadges(50)} />;
|
return <BadgeDialog {...defaultProps} badges={getFakeBadges(50)} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
ManyBadges.story = {
|
|
||||||
name: 'Many badges',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ManyBadgesUserIsASubscriber(): JSX.Element {
|
export function ManyBadgesUserIsASubscriber(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<BadgeDialog
|
<BadgeDialog
|
||||||
|
@ -141,7 +115,3 @@ export function ManyBadgesUserIsASubscriber(): JSX.Element {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ManyBadgesUserIsASubscriber.story = {
|
|
||||||
name: 'Many badges, user is a subscriber',
|
|
||||||
};
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { BadgeImage } from './BadgeImage';
|
||||||
import { BadgeCarouselIndex } from './BadgeCarouselIndex';
|
import { BadgeCarouselIndex } from './BadgeCarouselIndex';
|
||||||
import { BadgeSustainerInstructionsDialog } from './BadgeSustainerInstructionsDialog';
|
import { BadgeSustainerInstructionsDialog } from './BadgeSustainerInstructionsDialog';
|
||||||
|
|
||||||
type PropsType = Readonly<{
|
export type PropsType = Readonly<{
|
||||||
areWeASubscriber: boolean;
|
areWeASubscriber: boolean;
|
||||||
badges: ReadonlyArray<BadgeType>;
|
badges: ReadonlyArray<BadgeType>;
|
||||||
firstName?: string;
|
firstName?: string;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
import { AvatarColors } from '../types/Colors';
|
import { AvatarColors } from '../types/Colors';
|
||||||
import { GroupAvatarIcons, PersonalAvatarIcons } from '../types/Avatar';
|
import { GroupAvatarIcons, PersonalAvatarIcons } from '../types/Avatar';
|
||||||
|
@ -28,7 +29,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/BetterAvatar',
|
title: 'Components/BetterAvatar',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Text(): JSX.Element {
|
export function Text(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -5,6 +5,7 @@ import React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
import { AvatarColors } from '../types/Colors';
|
import { AvatarColors } from '../types/Colors';
|
||||||
import type { PropsType } from './BetterAvatarBubble';
|
import type { PropsType } from './BetterAvatarBubble';
|
||||||
|
@ -25,7 +26,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/BetterAvatarBubble',
|
title: 'Components/BetterAvatarBubble',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Children(): JSX.Element {
|
export function Children(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
|
import type { PropsType } from './Button';
|
||||||
import { Button, ButtonSize, ButtonVariant } from './Button';
|
import { Button, ButtonSize, ButtonVariant } from './Button';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/Button',
|
title: 'Components/Button',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function KitchenSink(): JSX.Element {
|
export function KitchenSink(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
@ -44,10 +45,6 @@ export function KitchenSink(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
KitchenSink.story = {
|
|
||||||
name: 'Kitchen sink',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function AriaLabel(): JSX.Element {
|
export function AriaLabel(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
|
@ -58,10 +55,6 @@ export function AriaLabel(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
AriaLabel.story = {
|
|
||||||
name: 'aria-label',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function CustomStyles(): JSX.Element {
|
export function CustomStyles(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Button onClick={action('onClick')} style={{ transform: 'rotate(5deg)' }}>
|
<Button onClick={action('onClick')} style={{ transform: 'rotate(5deg)' }}>
|
||||||
|
@ -69,7 +62,3 @@ export function CustomStyles(): JSX.Element {
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomStyles.story = {
|
|
||||||
name: 'Custom styles',
|
|
||||||
};
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ export enum ButtonIconType {
|
||||||
video = 'video',
|
video = 'video',
|
||||||
}
|
}
|
||||||
|
|
||||||
type PropsType = {
|
export type PropsType = {
|
||||||
className?: string;
|
className?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
icon?: ButtonIconType;
|
icon?: ButtonIconType;
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import { boolean, select, text } from '@storybook/addon-knobs';
|
import type { Meta } from '@storybook/react';
|
||||||
|
|
||||||
import type { PropsType } from './CallManager';
|
import type { PropsType } from './CallManager';
|
||||||
import { CallManager } from './CallManager';
|
import { CallManager } from './CallManager';
|
||||||
import {
|
import {
|
||||||
|
@ -16,7 +15,6 @@ import {
|
||||||
GroupCallJoinState,
|
GroupCallJoinState,
|
||||||
} from '../types/Calling';
|
} from '../types/Calling';
|
||||||
import type { ConversationTypeType } from '../state/ducks/conversations';
|
import type { ConversationTypeType } from '../state/ducks/conversations';
|
||||||
import type { AvatarColorType } from '../types/Colors';
|
|
||||||
import { AvatarColors } from '../types/Colors';
|
import { AvatarColors } from '../types/Colors';
|
||||||
import { generateAci } from '../types/ServiceId';
|
import { generateAci } from '../types/ServiceId';
|
||||||
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
|
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
|
||||||
|
@ -33,13 +31,9 @@ const getConversation = () =>
|
||||||
getDefaultConversation({
|
getDefaultConversation({
|
||||||
id: '3051234567',
|
id: '3051234567',
|
||||||
avatarPath: undefined,
|
avatarPath: undefined,
|
||||||
color: select(
|
color: AvatarColors[0],
|
||||||
'Callee color',
|
title: 'Rick Sanchez',
|
||||||
AvatarColors,
|
name: 'Rick Sanchez',
|
||||||
'ultramarine' as AvatarColorType
|
|
||||||
),
|
|
||||||
title: text('Callee Title', 'Rick Sanchez'),
|
|
||||||
name: text('Callee Name', 'Rick Sanchez'),
|
|
||||||
phoneNumber: '3051234567',
|
phoneNumber: '3051234567',
|
||||||
profileName: 'Rick Sanchez',
|
profileName: 'Rick Sanchez',
|
||||||
markedUnread: false,
|
markedUnread: false,
|
||||||
|
@ -50,18 +44,14 @@ const getConversation = () =>
|
||||||
const getCommonActiveCallData = () => ({
|
const getCommonActiveCallData = () => ({
|
||||||
conversation: getConversation(),
|
conversation: getConversation(),
|
||||||
joinedAt: Date.now(),
|
joinedAt: Date.now(),
|
||||||
hasLocalAudio: boolean('hasLocalAudio', true),
|
hasLocalAudio: true,
|
||||||
hasLocalVideo: boolean('hasLocalVideo', false),
|
hasLocalVideo: false,
|
||||||
localAudioLevel: select('localAudioLevel', [0, 0.5, 1], 0),
|
localAudioLevel: 0,
|
||||||
viewMode: select(
|
viewMode: CallViewMode.Grid,
|
||||||
'viewMode',
|
outgoingRing: true,
|
||||||
[CallViewMode.Grid, CallViewMode.Presentation, CallViewMode.Speaker],
|
pip: false,
|
||||||
CallViewMode.Grid
|
settingsDialogOpen: false,
|
||||||
),
|
showParticipantsList: false,
|
||||||
outgoingRing: boolean('outgoingRing', true),
|
|
||||||
pip: boolean('pip', false),
|
|
||||||
settingsDialogOpen: boolean('settingsDialogOpen', false),
|
|
||||||
showParticipantsList: boolean('showParticipantsList', false),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
|
const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
|
@ -83,12 +73,8 @@ const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
keyChangeOk: action('key-change-ok'),
|
keyChangeOk: action('key-change-ok'),
|
||||||
me: {
|
me: {
|
||||||
...getDefaultConversation({
|
...getDefaultConversation({
|
||||||
color: select(
|
color: AvatarColors[0],
|
||||||
'Caller color',
|
title: 'Morty Smith',
|
||||||
AvatarColors,
|
|
||||||
'ultramarine' as AvatarColorType
|
|
||||||
),
|
|
||||||
title: text('Caller Title', 'Morty Smith'),
|
|
||||||
}),
|
}),
|
||||||
serviceId: generateAci(),
|
serviceId: generateAci(),
|
||||||
},
|
},
|
||||||
|
@ -123,7 +109,9 @@ const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CallManager',
|
title: 'Components/CallManager',
|
||||||
};
|
argTypes: {},
|
||||||
|
args: {},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function NoCall(): JSX.Element {
|
export function NoCall(): JSX.Element {
|
||||||
return <CallManager {...createProps()} />;
|
return <CallManager {...createProps()} />;
|
||||||
|
@ -184,10 +172,6 @@ export function RingingDirectCall(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
RingingDirectCall.story = {
|
|
||||||
name: 'Ringing (direct call)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function RingingGroupCall(): JSX.Element {
|
export function RingingGroupCall(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallManager
|
<CallManager
|
||||||
|
@ -212,10 +196,6 @@ export function RingingGroupCall(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
RingingGroupCall.story = {
|
|
||||||
name: 'Ringing (group call)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function CallRequestNeeded(): JSX.Element {
|
export function CallRequestNeeded(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallManager
|
<CallManager
|
||||||
|
@ -263,7 +243,3 @@ export function GroupCallSafetyNumberChanged(): JSX.Element {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCallSafetyNumberChanged.story = {
|
|
||||||
name: 'Group call - Safety Number Changed',
|
|
||||||
};
|
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { times } from 'lodash';
|
import { times } from 'lodash';
|
||||||
import { boolean, select, number } from '@storybook/addon-knobs';
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import type { GroupCallRemoteParticipantType } from '../types/Calling';
|
import type { GroupCallRemoteParticipantType } from '../types/Calling';
|
||||||
import {
|
import {
|
||||||
CallMode,
|
CallMode,
|
||||||
|
@ -60,6 +60,7 @@ type GroupCallOverrideProps = OverridePropsBase & {
|
||||||
connectionState?: GroupCallConnectionState;
|
connectionState?: GroupCallConnectionState;
|
||||||
peekedParticipants?: Array<ConversationType>;
|
peekedParticipants?: Array<ConversationType>;
|
||||||
remoteParticipants?: Array<GroupCallRemoteParticipantType>;
|
remoteParticipants?: Array<GroupCallRemoteParticipantType>;
|
||||||
|
remoteAudioLevel?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const createActiveDirectCallProp = (
|
const createActiveDirectCallProp = (
|
||||||
|
@ -67,18 +68,11 @@ const createActiveDirectCallProp = (
|
||||||
) => ({
|
) => ({
|
||||||
callMode: CallMode.Direct as CallMode.Direct,
|
callMode: CallMode.Direct as CallMode.Direct,
|
||||||
conversation,
|
conversation,
|
||||||
callState: select(
|
callState: overrideProps.callState ?? CallState.Accepted,
|
||||||
'callState',
|
|
||||||
CallState,
|
|
||||||
overrideProps.callState || CallState.Accepted
|
|
||||||
),
|
|
||||||
peekedParticipants: [] as [],
|
peekedParticipants: [] as [],
|
||||||
remoteParticipants: [
|
remoteParticipants: [
|
||||||
{
|
{
|
||||||
hasRemoteVideo: boolean(
|
hasRemoteVideo: overrideProps.hasRemoteVideo ?? false,
|
||||||
'hasRemoteVideo',
|
|
||||||
Boolean(overrideProps.hasRemoteVideo)
|
|
||||||
),
|
|
||||||
presenting: false,
|
presenting: false,
|
||||||
title: 'test',
|
title: 'test',
|
||||||
},
|
},
|
||||||
|
@ -109,12 +103,7 @@ const createActiveGroupCallProp = (overrideProps: GroupCallOverrideProps) => ({
|
||||||
remoteAudioLevels: new Map<number, number>(
|
remoteAudioLevels: new Map<number, number>(
|
||||||
overrideProps.remoteParticipants?.map((_participant, index) => [
|
overrideProps.remoteParticipants?.map((_participant, index) => [
|
||||||
index,
|
index,
|
||||||
number('remoteAudioLevel', 0, {
|
overrideProps.remoteAudioLevel ?? 0,
|
||||||
range: true,
|
|
||||||
min: 0,
|
|
||||||
max: 1,
|
|
||||||
step: 0.01,
|
|
||||||
}),
|
|
||||||
])
|
])
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
@ -125,24 +114,10 @@ const createActiveCallProp = (
|
||||||
const baseResult = {
|
const baseResult = {
|
||||||
joinedAt: Date.now(),
|
joinedAt: Date.now(),
|
||||||
conversation,
|
conversation,
|
||||||
hasLocalAudio: boolean(
|
hasLocalAudio: overrideProps.hasLocalAudio ?? false,
|
||||||
'hasLocalAudio',
|
hasLocalVideo: overrideProps.hasLocalVideo ?? false,
|
||||||
overrideProps.hasLocalAudio || false
|
localAudioLevel: overrideProps.localAudioLevel ?? 0,
|
||||||
),
|
viewMode: overrideProps.viewMode ?? CallViewMode.Grid,
|
||||||
hasLocalVideo: boolean(
|
|
||||||
'hasLocalVideo',
|
|
||||||
overrideProps.hasLocalVideo || false
|
|
||||||
),
|
|
||||||
localAudioLevel: select(
|
|
||||||
'localAudioLevel',
|
|
||||||
[0, 0.5, 1],
|
|
||||||
overrideProps.localAudioLevel || 0
|
|
||||||
),
|
|
||||||
viewMode: select(
|
|
||||||
'viewMode',
|
|
||||||
[CallViewMode.Grid, CallViewMode.Speaker, CallViewMode.Presentation],
|
|
||||||
overrideProps.viewMode || CallViewMode.Grid
|
|
||||||
),
|
|
||||||
outgoingRing: true,
|
outgoingRing: true,
|
||||||
pip: false,
|
pip: false,
|
||||||
settingsDialogOpen: false,
|
settingsDialogOpen: false,
|
||||||
|
@ -184,7 +159,7 @@ const createProps = (
|
||||||
setLocalVideo: action('set-local-video'),
|
setLocalVideo: action('set-local-video'),
|
||||||
setPresenting: action('toggle-presenting'),
|
setPresenting: action('toggle-presenting'),
|
||||||
setRendererCanvas: action('set-renderer-canvas'),
|
setRendererCanvas: action('set-renderer-canvas'),
|
||||||
stickyControls: boolean('stickyControls', false),
|
stickyControls: false,
|
||||||
switchToPresentationView: action('switch-to-presentation-view'),
|
switchToPresentationView: action('switch-to-presentation-view'),
|
||||||
switchFromPresentationView: action('switch-from-presentation-view'),
|
switchFromPresentationView: action('switch-from-presentation-view'),
|
||||||
toggleParticipants: action('toggle-participants'),
|
toggleParticipants: action('toggle-participants'),
|
||||||
|
@ -198,7 +173,9 @@ const createProps = (
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CallScreen',
|
title: 'Components/CallScreen',
|
||||||
};
|
argTypes: {},
|
||||||
|
args: {},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Default(): JSX.Element {
|
export function Default(): JSX.Element {
|
||||||
return <CallScreen {...createProps()} />;
|
return <CallScreen {...createProps()} />;
|
||||||
|
@ -215,11 +192,7 @@ export function PreRing(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
PreRing.story = {
|
export function Ringing(): JSX.Element {
|
||||||
name: 'Pre-Ring',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const _Ringing = (): JSX.Element => {
|
|
||||||
return (
|
return (
|
||||||
<CallScreen
|
<CallScreen
|
||||||
{...createProps({
|
{...createProps({
|
||||||
|
@ -228,9 +201,9 @@ export const _Ringing = (): JSX.Element => {
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
export const _Reconnecting = (): JSX.Element => {
|
export function Reconnecting(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallScreen
|
<CallScreen
|
||||||
{...createProps({
|
{...createProps({
|
||||||
|
@ -239,9 +212,9 @@ export const _Reconnecting = (): JSX.Element => {
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
export const _Ended = (): JSX.Element => {
|
export function Ended(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallScreen
|
<CallScreen
|
||||||
{...createProps({
|
{...createProps({
|
||||||
|
@ -250,7 +223,7 @@ export const _Ended = (): JSX.Element => {
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
export function HasLocalAudio(): JSX.Element {
|
export function HasLocalAudio(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
@ -263,10 +236,6 @@ export function HasLocalAudio(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
HasLocalAudio.story = {
|
|
||||||
name: 'hasLocalAudio',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function HasLocalVideo(): JSX.Element {
|
export function HasLocalVideo(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallScreen
|
<CallScreen
|
||||||
|
@ -278,10 +247,6 @@ export function HasLocalVideo(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
HasLocalVideo.story = {
|
|
||||||
name: 'hasLocalVideo',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function HasRemoteVideo(): JSX.Element {
|
export function HasRemoteVideo(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallScreen
|
<CallScreen
|
||||||
|
@ -293,10 +258,6 @@ export function HasRemoteVideo(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
HasRemoteVideo.story = {
|
|
||||||
name: 'hasRemoteVideo',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function GroupCall1(): JSX.Element {
|
export function GroupCall1(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallScreen
|
<CallScreen
|
||||||
|
@ -323,10 +284,6 @@ export function GroupCall1(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCall1.story = {
|
|
||||||
name: 'Group call - 1',
|
|
||||||
};
|
|
||||||
|
|
||||||
// We generate these upfront so that the list is stable when you move the slider.
|
// We generate these upfront so that the list is stable when you move the slider.
|
||||||
const allRemoteParticipants = times(MAX_PARTICIPANTS).map(index => ({
|
const allRemoteParticipants = times(MAX_PARTICIPANTS).map(index => ({
|
||||||
aci: generateAci(),
|
aci: generateAci(),
|
||||||
|
@ -347,24 +304,12 @@ export function GroupCallMany(): JSX.Element {
|
||||||
<CallScreen
|
<CallScreen
|
||||||
{...createProps({
|
{...createProps({
|
||||||
callMode: CallMode.Group,
|
callMode: CallMode.Group,
|
||||||
remoteParticipants: allRemoteParticipants.slice(
|
remoteParticipants: allRemoteParticipants.slice(0, 40),
|
||||||
0,
|
|
||||||
number('Participant count', 40, {
|
|
||||||
range: true,
|
|
||||||
min: 0,
|
|
||||||
max: MAX_PARTICIPANTS,
|
|
||||||
step: 1,
|
|
||||||
})
|
|
||||||
),
|
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCallMany.story = {
|
|
||||||
name: 'Group call - Many',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function GroupCallReconnecting(): JSX.Element {
|
export function GroupCallReconnecting(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallScreen
|
<CallScreen
|
||||||
|
@ -392,10 +337,6 @@ export function GroupCallReconnecting(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCallReconnecting.story = {
|
|
||||||
name: 'Group call - reconnecting',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function GroupCall0(): JSX.Element {
|
export function GroupCall0(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallScreen
|
<CallScreen
|
||||||
|
@ -407,10 +348,6 @@ export function GroupCall0(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCall0.story = {
|
|
||||||
name: 'Group call - 0',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function GroupCallSomeoneIsSharingScreen(): JSX.Element {
|
export function GroupCallSomeoneIsSharingScreen(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallScreen
|
<CallScreen
|
||||||
|
@ -428,10 +365,6 @@ export function GroupCallSomeoneIsSharingScreen(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCallSomeoneIsSharingScreen.story = {
|
|
||||||
name: 'Group call - someone is sharing screen',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function GroupCallSomeoneIsSharingScreenAndYoureReconnecting(): JSX.Element {
|
export function GroupCallSomeoneIsSharingScreenAndYoureReconnecting(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallScreen
|
<CallScreen
|
||||||
|
@ -449,7 +382,3 @@ export function GroupCallSomeoneIsSharingScreenAndYoureReconnecting(): JSX.Eleme
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCallSomeoneIsSharingScreenAndYoureReconnecting.story = {
|
|
||||||
name: "Group call - someone is sharing screen and you're reconnecting",
|
|
||||||
};
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { boolean } from '@storybook/addon-knobs';
|
import type { Meta } from '@storybook/react';
|
||||||
|
import type { Props } from './CallingAudioIndicator';
|
||||||
import {
|
import {
|
||||||
CallingAudioIndicator,
|
CallingAudioIndicator,
|
||||||
SPEAKING_LINGER_MS,
|
SPEAKING_LINGER_MS,
|
||||||
|
@ -13,9 +13,18 @@ import { useValueAtFixedRate } from '../hooks/useValueAtFixedRate';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CallingAudioIndicator',
|
title: 'Components/CallingAudioIndicator',
|
||||||
};
|
component: CallingAudioIndicator,
|
||||||
|
argTypes: {
|
||||||
|
hasAudio: {
|
||||||
|
control: { type: 'boolean' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
hasAudio: true,
|
||||||
|
},
|
||||||
|
} satisfies Meta<Props>;
|
||||||
|
|
||||||
export function Extreme(): JSX.Element {
|
export function Extreme(args: Props): JSX.Element {
|
||||||
const [audioLevel, setAudioLevel] = useState(1);
|
const [audioLevel, setAudioLevel] = useState(1);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -32,14 +41,14 @@ export function Extreme(): JSX.Element {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CallingAudioIndicator
|
<CallingAudioIndicator
|
||||||
hasAudio={boolean('hasAudio', true)}
|
hasAudio={args.hasAudio}
|
||||||
audioLevel={audioLevel}
|
audioLevel={audioLevel}
|
||||||
shouldShowSpeaking={isSpeaking}
|
shouldShowSpeaking={isSpeaking}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Random(): JSX.Element {
|
export function Random(args: Props): JSX.Element {
|
||||||
const [audioLevel, setAudioLevel] = useState(1);
|
const [audioLevel, setAudioLevel] = useState(1);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -56,7 +65,7 @@ export function Random(): JSX.Element {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CallingAudioIndicator
|
<CallingAudioIndicator
|
||||||
hasAudio={boolean('hasAudio', true)}
|
hasAudio={args.hasAudio}
|
||||||
audioLevel={audioLevel}
|
audioLevel={audioLevel}
|
||||||
shouldShowSpeaking={isSpeaking}
|
shouldShowSpeaking={isSpeaking}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -99,15 +99,17 @@ function Bars({ audioLevel }: { audioLevel: number }): ReactElement {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Props = Readonly<{
|
||||||
|
hasAudio: boolean;
|
||||||
|
audioLevel: number;
|
||||||
|
shouldShowSpeaking: boolean;
|
||||||
|
}>;
|
||||||
|
|
||||||
export function CallingAudioIndicator({
|
export function CallingAudioIndicator({
|
||||||
hasAudio,
|
hasAudio,
|
||||||
audioLevel,
|
audioLevel,
|
||||||
shouldShowSpeaking,
|
shouldShowSpeaking,
|
||||||
}: Readonly<{
|
}: Props): ReactElement {
|
||||||
hasAudio: boolean;
|
|
||||||
audioLevel: number;
|
|
||||||
shouldShowSpeaking: boolean;
|
|
||||||
}>): ReactElement {
|
|
||||||
if (!hasAudio) {
|
if (!hasAudio) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { select } from '@storybook/addon-knobs';
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import type { PropsType } from './CallingButton';
|
import type { PropsType } from './CallingButton';
|
||||||
import { CallingButton, CallingButtonType } from './CallingButton';
|
import { CallingButton, CallingButtonType } from './CallingButton';
|
||||||
import { TooltipPlacement } from './Tooltip';
|
import { TooltipPlacement } from './Tooltip';
|
||||||
|
@ -13,101 +12,79 @@ import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|
||||||
buttonType:
|
|
||||||
overrideProps.buttonType ||
|
|
||||||
select('buttonType', CallingButtonType, CallingButtonType.HANG_UP),
|
|
||||||
i18n,
|
|
||||||
onClick: action('on-click'),
|
|
||||||
onMouseEnter: action('on-mouse-enter'),
|
|
||||||
onMouseLeave: action('on-mouse-leave'),
|
|
||||||
tooltipDirection: select(
|
|
||||||
'tooltipDirection',
|
|
||||||
TooltipPlacement,
|
|
||||||
overrideProps.tooltipDirection || TooltipPlacement.Bottom
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CallingButton',
|
title: 'Components/CallingButton',
|
||||||
};
|
component: CallingButton,
|
||||||
|
argTypes: {
|
||||||
|
buttonType: {
|
||||||
|
control: { type: 'select' },
|
||||||
|
options: Object.values(CallingButtonType),
|
||||||
|
},
|
||||||
|
tooltipDirection: {
|
||||||
|
control: { type: 'select' },
|
||||||
|
options: Object.values(TooltipPlacement),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
buttonType: CallingButtonType.HANG_UP,
|
||||||
|
i18n,
|
||||||
|
onClick: action('on-click'),
|
||||||
|
onMouseEnter: action('on-mouse-enter'),
|
||||||
|
onMouseLeave: action('on-mouse-leave'),
|
||||||
|
tooltipDirection: TooltipPlacement.Bottom,
|
||||||
|
},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function KitchenSink(): JSX.Element {
|
export function KitchenSink(args: PropsType): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{Object.keys(CallingButtonType).map(buttonType => (
|
{Object.values(CallingButtonType).map(buttonType => (
|
||||||
<CallingButton
|
<CallingButton key={buttonType} {...args} buttonType={buttonType} />
|
||||||
key={buttonType}
|
|
||||||
{...createProps({ buttonType: buttonType as CallingButtonType })}
|
|
||||||
/>
|
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AudioOn(): JSX.Element {
|
export function AudioOn(args: PropsType): JSX.Element {
|
||||||
const props = createProps({
|
return <CallingButton {...args} buttonType={CallingButtonType.AUDIO_ON} />;
|
||||||
buttonType: CallingButtonType.AUDIO_ON,
|
|
||||||
});
|
|
||||||
return <CallingButton {...props} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AudioOff(): JSX.Element {
|
export function AudioOff(args: PropsType): JSX.Element {
|
||||||
const props = createProps({
|
return <CallingButton {...args} buttonType={CallingButtonType.AUDIO_OFF} />;
|
||||||
buttonType: CallingButtonType.AUDIO_OFF,
|
|
||||||
});
|
|
||||||
return <CallingButton {...props} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AudioDisabled(): JSX.Element {
|
export function AudioDisabled(args: PropsType): JSX.Element {
|
||||||
const props = createProps({
|
return (
|
||||||
buttonType: CallingButtonType.AUDIO_DISABLED,
|
<CallingButton {...args} buttonType={CallingButtonType.AUDIO_DISABLED} />
|
||||||
});
|
);
|
||||||
return <CallingButton {...props} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VideoOn(): JSX.Element {
|
export function VideoOn(args: PropsType): JSX.Element {
|
||||||
const props = createProps({
|
return <CallingButton {...args} buttonType={CallingButtonType.VIDEO_ON} />;
|
||||||
buttonType: CallingButtonType.VIDEO_ON,
|
|
||||||
});
|
|
||||||
return <CallingButton {...props} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VideoOff(): JSX.Element {
|
export function VideoOff(args: PropsType): JSX.Element {
|
||||||
const props = createProps({
|
return <CallingButton {...args} buttonType={CallingButtonType.VIDEO_OFF} />;
|
||||||
buttonType: CallingButtonType.VIDEO_OFF,
|
|
||||||
});
|
|
||||||
return <CallingButton {...props} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VideoDisabled(): JSX.Element {
|
export function VideoDisabled(args: PropsType): JSX.Element {
|
||||||
const props = createProps({
|
return (
|
||||||
buttonType: CallingButtonType.VIDEO_DISABLED,
|
<CallingButton {...args} buttonType={CallingButtonType.VIDEO_DISABLED} />
|
||||||
});
|
);
|
||||||
return <CallingButton {...props} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TooltipRight(): JSX.Element {
|
export function TooltipRight(args: PropsType): JSX.Element {
|
||||||
const props = createProps({
|
return <CallingButton {...args} tooltipDirection={TooltipPlacement.Right} />;
|
||||||
tooltipDirection: TooltipPlacement.Right,
|
|
||||||
});
|
|
||||||
return <CallingButton {...props} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TooltipRight.story = {
|
export function PresentingOn(args: PropsType): JSX.Element {
|
||||||
name: 'Tooltip right',
|
return (
|
||||||
};
|
<CallingButton {...args} buttonType={CallingButtonType.PRESENTING_ON} />
|
||||||
|
);
|
||||||
export function PresentingOn(): JSX.Element {
|
|
||||||
const props = createProps({
|
|
||||||
buttonType: CallingButtonType.PRESENTING_ON,
|
|
||||||
});
|
|
||||||
return <CallingButton {...props} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PresentingOff(): JSX.Element {
|
export function PresentingOff(args: PropsType): JSX.Element {
|
||||||
const props = createProps({
|
return (
|
||||||
buttonType: CallingButtonType.PRESENTING_OFF,
|
<CallingButton {...args} buttonType={CallingButtonType.PRESENTING_OFF} />
|
||||||
});
|
);
|
||||||
return <CallingButton {...props} />;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import type { Props } from './CallingDeviceSelection';
|
import type { Props } from './CallingDeviceSelection';
|
||||||
import { CallingDeviceSelection } from './CallingDeviceSelection';
|
import { CallingDeviceSelection } from './CallingDeviceSelection';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
|
@ -39,7 +40,7 @@ const createProps = ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CallingDeviceSelection',
|
title: 'Components/CallingDeviceSelection',
|
||||||
};
|
} satisfies Meta<Props>;
|
||||||
|
|
||||||
export function Default(): JSX.Element {
|
export function Default(): JSX.Element {
|
||||||
return <CallingDeviceSelection {...createProps()} />;
|
return <CallingDeviceSelection {...createProps()} />;
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { boolean, number } from '@storybook/addon-knobs';
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import type { PropsType } from './CallingHeader';
|
import type { PropsType } from './CallingHeader';
|
||||||
import { CallingHeader } from './CallingHeader';
|
import { CallingHeader } from './CallingHeader';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
|
@ -12,36 +11,35 @@ import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|
||||||
i18n,
|
|
||||||
isGroupCall: boolean('isGroupCall', Boolean(overrideProps.isGroupCall)),
|
|
||||||
message: overrideProps.message,
|
|
||||||
participantCount: number(
|
|
||||||
'participantCount',
|
|
||||||
overrideProps.participantCount || 0
|
|
||||||
),
|
|
||||||
showParticipantsList: boolean(
|
|
||||||
'showParticipantsList',
|
|
||||||
Boolean(overrideProps.showParticipantsList)
|
|
||||||
),
|
|
||||||
title: overrideProps.title || 'With Someone',
|
|
||||||
toggleParticipants: () => action('toggle-participants'),
|
|
||||||
togglePip: () => action('toggle-pip'),
|
|
||||||
toggleSettings: () => action('toggle-settings'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CallingHeader',
|
title: 'Components/CallingHeader',
|
||||||
};
|
component: CallingHeader,
|
||||||
|
argTypes: {
|
||||||
|
isGroupCall: { control: { type: 'boolean' } },
|
||||||
|
participantCount: { control: { type: 'number' } },
|
||||||
|
title: { control: { type: 'text' } },
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
i18n,
|
||||||
|
isGroupCall: false,
|
||||||
|
message: '',
|
||||||
|
participantCount: 0,
|
||||||
|
showParticipantsList: false,
|
||||||
|
title: 'With Someone',
|
||||||
|
toggleParticipants: action('toggle-participants'),
|
||||||
|
togglePip: action('toggle-pip'),
|
||||||
|
toggleSettings: action('toggle-settings'),
|
||||||
|
},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Default(): JSX.Element {
|
export function Default(args: PropsType): JSX.Element {
|
||||||
return <CallingHeader {...createProps()} />;
|
return <CallingHeader {...args} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function LobbyStyle(): JSX.Element {
|
export function LobbyStyle(args: PropsType): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingHeader
|
<CallingHeader
|
||||||
{...createProps()}
|
{...args}
|
||||||
title={undefined}
|
title={undefined}
|
||||||
togglePip={undefined}
|
togglePip={undefined}
|
||||||
onCancel={action('onClose')}
|
onCancel={action('onClose')}
|
||||||
|
@ -49,59 +47,32 @@ export function LobbyStyle(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
LobbyStyle.story = {
|
export function WithParticipants(args: PropsType): JSX.Element {
|
||||||
name: 'Lobby style',
|
return <CallingHeader {...args} isGroupCall participantCount={10} />;
|
||||||
};
|
}
|
||||||
|
|
||||||
export function WithParticipants(): JSX.Element {
|
export function WithParticipantsShown(args: PropsType): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingHeader
|
<CallingHeader
|
||||||
{...createProps({
|
{...args}
|
||||||
isGroupCall: true,
|
isGroupCall
|
||||||
participantCount: 10,
|
participantCount={10}
|
||||||
})}
|
showParticipantsList
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function WithParticipantsShown(): JSX.Element {
|
export function LongTitle(args: PropsType): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingHeader
|
<CallingHeader
|
||||||
{...createProps({
|
{...args}
|
||||||
isGroupCall: true,
|
title="What do I got to, what do I got to do to wake you up? To shake you up, to break the structure up?"
|
||||||
participantCount: 10,
|
|
||||||
showParticipantsList: true,
|
|
||||||
})}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
WithParticipantsShown.story = {
|
export function TitleWithMessage(args: PropsType): JSX.Element {
|
||||||
name: 'With Participants (shown)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function LongTitle(): JSX.Element {
|
|
||||||
return (
|
return (
|
||||||
<CallingHeader
|
<CallingHeader {...args} title="Hello world" message="Goodbye earth" />
|
||||||
{...createProps({
|
|
||||||
title:
|
|
||||||
'What do I got to, what do I got to do to wake you up? To shake you up, to break the structure up?',
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TitleWithMessage(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<CallingHeader
|
|
||||||
{...createProps({
|
|
||||||
title: 'Hello world',
|
|
||||||
message: 'Goodbye earth',
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
TitleWithMessage.story = {
|
|
||||||
name: 'Title with message',
|
|
||||||
};
|
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { times } from 'lodash';
|
import { times } from 'lodash';
|
||||||
import { boolean } from '@storybook/addon-knobs';
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import { v4 as generateUuid } from 'uuid';
|
import { v4 as generateUuid } from 'uuid';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { AvatarColors } from '../types/Colors';
|
import { AvatarColors } from '../types/Colors';
|
||||||
import type { ConversationType } from '../state/ducks/conversations';
|
import type { ConversationType } from '../state/ducks/conversations';
|
||||||
import type { PropsType } from './CallingLobby';
|
import type { PropsType } from './CallingLobby';
|
||||||
|
@ -32,10 +32,7 @@ const camera = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
||||||
const isGroupCall = boolean(
|
const isGroupCall = overrideProps.isGroupCall ?? false;
|
||||||
'isGroupCall',
|
|
||||||
overrideProps.isGroupCall || false
|
|
||||||
);
|
|
||||||
const conversation = isGroupCall
|
const conversation = isGroupCall
|
||||||
? getDefaultConversation({
|
? getDefaultConversation({
|
||||||
title: 'Tahoe Trip',
|
title: 'Tahoe Trip',
|
||||||
|
@ -49,19 +46,13 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
||||||
groupMembers:
|
groupMembers:
|
||||||
overrideProps.groupMembers ||
|
overrideProps.groupMembers ||
|
||||||
(isGroupCall ? times(3, () => getDefaultConversation()) : undefined),
|
(isGroupCall ? times(3, () => getDefaultConversation()) : undefined),
|
||||||
hasLocalAudio: boolean(
|
hasLocalAudio: overrideProps.hasLocalAudio ?? true,
|
||||||
'hasLocalAudio',
|
hasLocalVideo: overrideProps.hasLocalVideo ?? false,
|
||||||
overrideProps.hasLocalAudio ?? true
|
|
||||||
),
|
|
||||||
hasLocalVideo: boolean(
|
|
||||||
'hasLocalVideo',
|
|
||||||
overrideProps.hasLocalVideo ?? false
|
|
||||||
),
|
|
||||||
i18n,
|
i18n,
|
||||||
isGroupCall,
|
isGroupCall,
|
||||||
isGroupCallOutboundRingEnabled: true,
|
isGroupCallOutboundRingEnabled: true,
|
||||||
isConversationTooBigToRing: false,
|
isConversationTooBigToRing: false,
|
||||||
isCallFull: boolean('isCallFull', overrideProps.isCallFull || false),
|
isCallFull: overrideProps.isCallFull ?? false,
|
||||||
me:
|
me:
|
||||||
overrideProps.me ||
|
overrideProps.me ||
|
||||||
getDefaultConversation({
|
getDefaultConversation({
|
||||||
|
@ -71,16 +62,13 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
||||||
}),
|
}),
|
||||||
onCallCanceled: action('on-call-canceled'),
|
onCallCanceled: action('on-call-canceled'),
|
||||||
onJoinCall: action('on-join-call'),
|
onJoinCall: action('on-join-call'),
|
||||||
outgoingRing: boolean('outgoingRing', Boolean(overrideProps.outgoingRing)),
|
outgoingRing: overrideProps.outgoingRing ?? false,
|
||||||
peekedParticipants: overrideProps.peekedParticipants || [],
|
peekedParticipants: overrideProps.peekedParticipants || [],
|
||||||
setLocalAudio: action('set-local-audio'),
|
setLocalAudio: action('set-local-audio'),
|
||||||
setLocalPreview: action('set-local-preview'),
|
setLocalPreview: action('set-local-preview'),
|
||||||
setLocalVideo: action('set-local-video'),
|
setLocalVideo: action('set-local-video'),
|
||||||
setOutgoingRing: action('set-outgoing-ring'),
|
setOutgoingRing: action('set-outgoing-ring'),
|
||||||
showParticipantsList: boolean(
|
showParticipantsList: overrideProps.showParticipantsList ?? false,
|
||||||
'showParticipantsList',
|
|
||||||
Boolean(overrideProps.showParticipantsList)
|
|
||||||
),
|
|
||||||
toggleParticipants: action('toggle-participants'),
|
toggleParticipants: action('toggle-participants'),
|
||||||
toggleSettings: action('toggle-settings'),
|
toggleSettings: action('toggle-settings'),
|
||||||
};
|
};
|
||||||
|
@ -93,7 +81,9 @@ const fakePeekedParticipant = (conversationProps: Partial<ConversationType>) =>
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CallingLobby',
|
title: 'Components/CallingLobby',
|
||||||
};
|
argTypes: {},
|
||||||
|
args: {},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Default(): JSX.Element {
|
export function Default(): JSX.Element {
|
||||||
const props = createProps();
|
const props = createProps();
|
||||||
|
@ -107,10 +97,6 @@ export function NoCameraNoAvatar(): JSX.Element {
|
||||||
return <CallingLobby {...props} />;
|
return <CallingLobby {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
NoCameraNoAvatar.story = {
|
|
||||||
name: 'No Camera, no avatar',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function NoCameraLocalAvatar(): JSX.Element {
|
export function NoCameraLocalAvatar(): JSX.Element {
|
||||||
const props = createProps({
|
const props = createProps({
|
||||||
availableCameras: [],
|
availableCameras: [],
|
||||||
|
@ -124,10 +110,6 @@ export function NoCameraLocalAvatar(): JSX.Element {
|
||||||
return <CallingLobby {...props} />;
|
return <CallingLobby {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
NoCameraLocalAvatar.story = {
|
|
||||||
name: 'No Camera, local avatar',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function LocalVideo(): JSX.Element {
|
export function LocalVideo(): JSX.Element {
|
||||||
const props = createProps({
|
const props = createProps({
|
||||||
hasLocalVideo: true,
|
hasLocalVideo: true,
|
||||||
|
@ -142,20 +124,12 @@ export function InitiallyMuted(): JSX.Element {
|
||||||
return <CallingLobby {...props} />;
|
return <CallingLobby {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
InitiallyMuted.story = {
|
export function GroupCallWithNoPeekedParticipants(): JSX.Element {
|
||||||
name: 'Initially muted',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function GroupCall0PeekedParticipants(): JSX.Element {
|
|
||||||
const props = createProps({ isGroupCall: true, peekedParticipants: [] });
|
const props = createProps({ isGroupCall: true, peekedParticipants: [] });
|
||||||
return <CallingLobby {...props} />;
|
return <CallingLobby {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCall0PeekedParticipants.story = {
|
export function GroupCallWith1PeekedParticipant(): JSX.Element {
|
||||||
name: 'Group Call - 0 peeked participants',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function GroupCall1PeekedParticipant(): JSX.Element {
|
|
||||||
const props = createProps({
|
const props = createProps({
|
||||||
isGroupCall: true,
|
isGroupCall: true,
|
||||||
peekedParticipants: [{ title: 'Sam' }].map(fakePeekedParticipant),
|
peekedParticipants: [{ title: 'Sam' }].map(fakePeekedParticipant),
|
||||||
|
@ -163,11 +137,7 @@ export function GroupCall1PeekedParticipant(): JSX.Element {
|
||||||
return <CallingLobby {...props} />;
|
return <CallingLobby {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCall1PeekedParticipant.story = {
|
export function GroupCallWith1PeekedParticipantSelf(): JSX.Element {
|
||||||
name: 'Group Call - 1 peeked participant',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function GroupCall1PeekedParticipantSelf(): JSX.Element {
|
|
||||||
const serviceId = generateAci();
|
const serviceId = generateAci();
|
||||||
const props = createProps({
|
const props = createProps({
|
||||||
isGroupCall: true,
|
isGroupCall: true,
|
||||||
|
@ -180,11 +150,7 @@ export function GroupCall1PeekedParticipantSelf(): JSX.Element {
|
||||||
return <CallingLobby {...props} />;
|
return <CallingLobby {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCall1PeekedParticipantSelf.story = {
|
export function GroupCallWith4PeekedParticipants(): JSX.Element {
|
||||||
name: 'Group Call - 1 peeked participant (self)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function GroupCall4PeekedParticipants(): JSX.Element {
|
|
||||||
const props = createProps({
|
const props = createProps({
|
||||||
isGroupCall: true,
|
isGroupCall: true,
|
||||||
peekedParticipants: ['Sam', 'Cayce', 'April', 'Logan', 'Carl'].map(title =>
|
peekedParticipants: ['Sam', 'Cayce', 'April', 'Logan', 'Carl'].map(title =>
|
||||||
|
@ -194,11 +160,7 @@ export function GroupCall4PeekedParticipants(): JSX.Element {
|
||||||
return <CallingLobby {...props} />;
|
return <CallingLobby {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCall4PeekedParticipants.story = {
|
export function GroupCallWith4PeekedParticipantsParticipantsList(): JSX.Element {
|
||||||
name: 'Group Call - 4 peeked participants',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function GroupCall4PeekedParticipantsParticipantsList(): JSX.Element {
|
|
||||||
const props = createProps({
|
const props = createProps({
|
||||||
isGroupCall: true,
|
isGroupCall: true,
|
||||||
peekedParticipants: ['Sam', 'Cayce', 'April', 'Logan', 'Carl'].map(title =>
|
peekedParticipants: ['Sam', 'Cayce', 'April', 'Logan', 'Carl'].map(title =>
|
||||||
|
@ -209,11 +171,7 @@ export function GroupCall4PeekedParticipantsParticipantsList(): JSX.Element {
|
||||||
return <CallingLobby {...props} />;
|
return <CallingLobby {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCall4PeekedParticipantsParticipantsList.story = {
|
export function GroupCallWithCallFull(): JSX.Element {
|
||||||
name: 'Group Call - 4 peeked participants (participants list)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function GroupCallCallFull(): JSX.Element {
|
|
||||||
const props = createProps({
|
const props = createProps({
|
||||||
isGroupCall: true,
|
isGroupCall: true,
|
||||||
isCallFull: true,
|
isCallFull: true,
|
||||||
|
@ -224,18 +182,10 @@ export function GroupCallCallFull(): JSX.Element {
|
||||||
return <CallingLobby {...props} />;
|
return <CallingLobby {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCallCallFull.story = {
|
export function GroupCallWith0PeekedParticipantsBigGroup(): JSX.Element {
|
||||||
name: 'Group Call - call full',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function GroupCall0PeekedParticipantsBigGroup(): JSX.Element {
|
|
||||||
const props = createProps({
|
const props = createProps({
|
||||||
isGroupCall: true,
|
isGroupCall: true,
|
||||||
groupMembers: times(100, () => getDefaultConversation()),
|
groupMembers: times(100, () => getDefaultConversation()),
|
||||||
});
|
});
|
||||||
return <CallingLobby {...props} />;
|
return <CallingLobby {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCall0PeekedParticipantsBigGroup.story = {
|
|
||||||
name: 'Group Call - 0 peeked participants, big group',
|
|
||||||
};
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import * as React from 'react';
|
||||||
import { sample } from 'lodash';
|
import { sample } from 'lodash';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import type { PropsType } from './CallingParticipantsList';
|
import type { PropsType } from './CallingParticipantsList';
|
||||||
import { CallingParticipantsList } from './CallingParticipantsList';
|
import { CallingParticipantsList } from './CallingParticipantsList';
|
||||||
import { AvatarColors } from '../types/Colors';
|
import { AvatarColors } from '../types/Colors';
|
||||||
|
@ -47,17 +48,13 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CallingParticipantsList',
|
title: 'Components/CallingParticipantsList',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function NoOne(): JSX.Element {
|
export function NoOne(): JSX.Element {
|
||||||
const props = createProps();
|
const props = createProps();
|
||||||
return <CallingParticipantsList {...props} />;
|
return <CallingParticipantsList {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
NoOne.story = {
|
|
||||||
name: 'No one',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function SoloCall(): JSX.Element {
|
export function SoloCall(): JSX.Element {
|
||||||
const props = createProps({
|
const props = createProps({
|
||||||
participants: [
|
participants: [
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { times } from 'lodash';
|
import { times } from 'lodash';
|
||||||
import { boolean, select } from '@storybook/addon-knobs';
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { AvatarColors } from '../types/Colors';
|
import { AvatarColors } from '../types/Colors';
|
||||||
import type { ConversationType } from '../state/ducks/conversations';
|
import type { ConversationType } from '../state/ducks/conversations';
|
||||||
import type { PropsType } from './CallingPip';
|
import type { PropsType } from './CallingPip';
|
||||||
|
@ -35,16 +34,19 @@ const conversation: ConversationType = getDefaultConversation({
|
||||||
profileName: 'Rick Sanchez',
|
profileName: 'Rick Sanchez',
|
||||||
});
|
});
|
||||||
|
|
||||||
const getCommonActiveCallData = () => ({
|
type Overrides = {
|
||||||
|
hasLocalAudio?: boolean;
|
||||||
|
hasLocalVideo?: boolean;
|
||||||
|
localAudioLevel?: number;
|
||||||
|
viewMode?: CallViewMode;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCommonActiveCallData = (overrides: Overrides) => ({
|
||||||
conversation,
|
conversation,
|
||||||
hasLocalAudio: boolean('hasLocalAudio', true),
|
hasLocalAudio: overrides.hasLocalAudio ?? true,
|
||||||
hasLocalVideo: boolean('hasLocalVideo', false),
|
hasLocalVideo: overrides.hasLocalVideo ?? false,
|
||||||
localAudioLevel: select('localAudioLevel', [0, 0.5, 1], 0),
|
localAudioLevel: overrides.localAudioLevel ?? 0,
|
||||||
viewMode: select(
|
viewMode: overrides.viewMode ?? CallViewMode.Grid,
|
||||||
'viewMode',
|
|
||||||
[CallViewMode.Grid, CallViewMode.Speaker, CallViewMode.Presentation],
|
|
||||||
CallViewMode.Grid
|
|
||||||
),
|
|
||||||
joinedAt: Date.now(),
|
joinedAt: Date.now(),
|
||||||
outgoingRing: true,
|
outgoingRing: true,
|
||||||
pip: true,
|
pip: true,
|
||||||
|
@ -52,92 +54,93 @@ const getCommonActiveCallData = () => ({
|
||||||
showParticipantsList: false,
|
showParticipantsList: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultCall: ActiveDirectCallType = {
|
const getDefaultCall = (overrides: Overrides): ActiveDirectCallType => {
|
||||||
...getCommonActiveCallData(),
|
return {
|
||||||
callMode: CallMode.Direct as CallMode.Direct,
|
...getCommonActiveCallData(overrides),
|
||||||
callState: CallState.Accepted,
|
callMode: CallMode.Direct as CallMode.Direct,
|
||||||
peekedParticipants: [],
|
callState: CallState.Accepted,
|
||||||
remoteParticipants: [
|
peekedParticipants: [],
|
||||||
{ hasRemoteVideo: true, presenting: false, title: 'Arsene' },
|
remoteParticipants: [
|
||||||
],
|
{ hasRemoteVideo: true, presenting: false, title: 'Arsene' },
|
||||||
|
],
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|
||||||
activeCall: overrideProps.activeCall || defaultCall,
|
|
||||||
getGroupCallVideoFrameSource: fakeGetGroupCallVideoFrameSource,
|
|
||||||
hangUpActiveCall: action('hang-up-active-call'),
|
|
||||||
hasLocalVideo: boolean('hasLocalVideo', overrideProps.hasLocalVideo || false),
|
|
||||||
i18n,
|
|
||||||
setGroupCallVideoRequest: action('set-group-call-video-request'),
|
|
||||||
setLocalPreview: action('set-local-preview'),
|
|
||||||
setRendererCanvas: action('set-renderer-canvas'),
|
|
||||||
switchFromPresentationView: action('switch-to-presentation-view'),
|
|
||||||
switchToPresentationView: action('switch-to-presentation-view'),
|
|
||||||
togglePip: action('toggle-pip'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CallingPip',
|
title: 'Components/CallingPip',
|
||||||
};
|
argTypes: {
|
||||||
|
hasLocalVideo: { control: { type: 'boolean' } },
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
activeCall: getDefaultCall({}),
|
||||||
|
getGroupCallVideoFrameSource: fakeGetGroupCallVideoFrameSource,
|
||||||
|
hangUpActiveCall: action('hang-up-active-call'),
|
||||||
|
hasLocalVideo: false,
|
||||||
|
i18n,
|
||||||
|
setGroupCallVideoRequest: action('set-group-call-video-request'),
|
||||||
|
setLocalPreview: action('set-local-preview'),
|
||||||
|
setRendererCanvas: action('set-renderer-canvas'),
|
||||||
|
switchFromPresentationView: action('switch-to-presentation-view'),
|
||||||
|
switchToPresentationView: action('switch-to-presentation-view'),
|
||||||
|
togglePip: action('toggle-pip'),
|
||||||
|
},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Default(): JSX.Element {
|
export function Default(args: PropsType): JSX.Element {
|
||||||
const props = createProps({});
|
return <CallingPip {...args} />;
|
||||||
return <CallingPip {...props} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ContactWithAvatarAndNoVideo(): JSX.Element {
|
export function ContactWithAvatarAndNoVideo(args: PropsType): JSX.Element {
|
||||||
const props = createProps({
|
return (
|
||||||
activeCall: {
|
<CallingPip
|
||||||
...defaultCall,
|
{...args}
|
||||||
conversation: {
|
activeCall={{
|
||||||
...conversation,
|
...getDefaultCall({}),
|
||||||
avatarPath: 'https://www.fillmurray.com/64/64',
|
conversation: {
|
||||||
},
|
...conversation,
|
||||||
remoteParticipants: [
|
avatarPath: 'https://www.fillmurray.com/64/64',
|
||||||
{ hasRemoteVideo: false, presenting: false, title: 'Julian' },
|
},
|
||||||
],
|
remoteParticipants: [
|
||||||
},
|
{ hasRemoteVideo: false, presenting: false, title: 'Julian' },
|
||||||
});
|
],
|
||||||
return <CallingPip {...props} />;
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactWithAvatarAndNoVideo.story = {
|
export function ContactNoColor(args: PropsType): JSX.Element {
|
||||||
name: 'Contact (with avatar and no video)',
|
return (
|
||||||
};
|
<CallingPip
|
||||||
|
{...args}
|
||||||
export function ContactNoColor(): JSX.Element {
|
activeCall={{
|
||||||
const props = createProps({
|
...getDefaultCall({}),
|
||||||
activeCall: {
|
conversation: {
|
||||||
...defaultCall,
|
...conversation,
|
||||||
conversation: {
|
color: undefined,
|
||||||
...conversation,
|
},
|
||||||
color: undefined,
|
}}
|
||||||
},
|
/>
|
||||||
},
|
);
|
||||||
});
|
|
||||||
return <CallingPip {...props} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactNoColor.story = {
|
export function GroupCall(args: PropsType): JSX.Element {
|
||||||
name: 'Contact (no color)',
|
return (
|
||||||
};
|
<CallingPip
|
||||||
|
{...args}
|
||||||
export function GroupCall(): JSX.Element {
|
activeCall={{
|
||||||
const props = createProps({
|
...getCommonActiveCallData({}),
|
||||||
activeCall: {
|
callMode: CallMode.Group as CallMode.Group,
|
||||||
...getCommonActiveCallData(),
|
connectionState: GroupCallConnectionState.Connected,
|
||||||
callMode: CallMode.Group as CallMode.Group,
|
conversationsWithSafetyNumberChanges: [],
|
||||||
connectionState: GroupCallConnectionState.Connected,
|
groupMembers: times(3, () => getDefaultConversation()),
|
||||||
conversationsWithSafetyNumberChanges: [],
|
isConversationTooBigToRing: false,
|
||||||
groupMembers: times(3, () => getDefaultConversation()),
|
joinState: GroupCallJoinState.Joined,
|
||||||
isConversationTooBigToRing: false,
|
maxDevices: 5,
|
||||||
joinState: GroupCallJoinState.Joined,
|
deviceCount: 0,
|
||||||
maxDevices: 5,
|
peekedParticipants: [],
|
||||||
deviceCount: 0,
|
remoteParticipants: [],
|
||||||
peekedParticipants: [],
|
remoteAudioLevels: new Map<number, number>(),
|
||||||
remoteParticipants: [],
|
}}
|
||||||
remoteAudioLevels: new Map<number, number>(),
|
/>
|
||||||
},
|
);
|
||||||
});
|
|
||||||
return <CallingPip {...props} />;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,11 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { times } from 'lodash';
|
import { times } from 'lodash';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
|
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
|
||||||
|
import type { PropsType } from './CallingPreCallInfo';
|
||||||
import { CallingPreCallInfo, RingMode } from './CallingPreCallInfo';
|
import { CallingPreCallInfo, RingMode } from './CallingPreCallInfo';
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
@ -22,7 +23,7 @@ const otherMembers = times(6, () => getDefaultConversation());
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CallingPreCallInfo',
|
title: 'Components/CallingPreCallInfo',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function DirectConversation(): JSX.Element {
|
export function DirectConversation(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
@ -35,10 +36,6 @@ export function DirectConversation(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectConversation.story = {
|
|
||||||
name: 'Direct conversation',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Ring0(): JSX.Element {
|
export function Ring0(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingPreCallInfo
|
<CallingPreCallInfo
|
||||||
|
@ -52,10 +49,6 @@ export function Ring0(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ring0.story = {
|
|
||||||
name: 'Group call: Will ring 0 people',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Ring1(): JSX.Element {
|
export function Ring1(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingPreCallInfo
|
<CallingPreCallInfo
|
||||||
|
@ -69,10 +62,6 @@ export function Ring1(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ring1.story = {
|
|
||||||
name: 'Group call: Will ring 1 person',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Ring2(): JSX.Element {
|
export function Ring2(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingPreCallInfo
|
<CallingPreCallInfo
|
||||||
|
@ -86,10 +75,6 @@ export function Ring2(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ring2.story = {
|
|
||||||
name: 'Group call: Will ring 2 people',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Ring3(): JSX.Element {
|
export function Ring3(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingPreCallInfo
|
<CallingPreCallInfo
|
||||||
|
@ -103,10 +88,6 @@ export function Ring3(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ring3.story = {
|
|
||||||
name: 'Group call: Will ring 3 people',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Ring4(): JSX.Element {
|
export function Ring4(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingPreCallInfo
|
<CallingPreCallInfo
|
||||||
|
@ -120,10 +101,6 @@ export function Ring4(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ring3.story = {
|
|
||||||
name: 'Group call: Will ring 4 people',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Notify0(): JSX.Element {
|
export function Notify0(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingPreCallInfo
|
<CallingPreCallInfo
|
||||||
|
@ -137,10 +114,6 @@ export function Notify0(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Notify0.story = {
|
|
||||||
name: 'Group call: Will notify 0 people',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Notify1(): JSX.Element {
|
export function Notify1(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingPreCallInfo
|
<CallingPreCallInfo
|
||||||
|
@ -154,10 +127,6 @@ export function Notify1(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Notify1.story = {
|
|
||||||
name: 'Group call: Will notify 1 person',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Notify2(): JSX.Element {
|
export function Notify2(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingPreCallInfo
|
<CallingPreCallInfo
|
||||||
|
@ -171,10 +140,6 @@ export function Notify2(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Notify2.story = {
|
|
||||||
name: 'Group call: Will notify 2 people',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Notify3(): JSX.Element {
|
export function Notify3(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingPreCallInfo
|
<CallingPreCallInfo
|
||||||
|
@ -188,10 +153,6 @@ export function Notify3(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Notify3.story = {
|
|
||||||
name: 'Group call: Will notify 3 people',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Notify4(): JSX.Element {
|
export function Notify4(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingPreCallInfo
|
<CallingPreCallInfo
|
||||||
|
@ -205,10 +166,6 @@ export function Notify4(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Notify4.story = {
|
|
||||||
name: 'Group call: Will notify 4 people',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Peek1(): JSX.Element {
|
export function Peek1(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingPreCallInfo
|
<CallingPreCallInfo
|
||||||
|
@ -222,10 +179,6 @@ export function Peek1(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Peek1.story = {
|
|
||||||
name: 'Group call: 1 participant peeked',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Peek2(): JSX.Element {
|
export function Peek2(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingPreCallInfo
|
<CallingPreCallInfo
|
||||||
|
@ -239,10 +192,6 @@ export function Peek2(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Peek2.story = {
|
|
||||||
name: 'Group call: 2 participants peeked',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Peek3(): JSX.Element {
|
export function Peek3(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingPreCallInfo
|
<CallingPreCallInfo
|
||||||
|
@ -256,10 +205,6 @@ export function Peek3(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Peek3.story = {
|
|
||||||
name: 'Group call: 3 participants peeked',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Peek4(): JSX.Element {
|
export function Peek4(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingPreCallInfo
|
<CallingPreCallInfo
|
||||||
|
@ -273,10 +218,6 @@ export function Peek4(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Peek4.story = {
|
|
||||||
name: 'Group call: 4 participants peeked',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function GroupConversationYouOnAnOtherDevice(): JSX.Element {
|
export function GroupConversationYouOnAnOtherDevice(): JSX.Element {
|
||||||
const me = getDefaultConversation();
|
const me = getDefaultConversation();
|
||||||
return (
|
return (
|
||||||
|
@ -291,10 +232,6 @@ export function GroupConversationYouOnAnOtherDevice(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupConversationYouOnAnOtherDevice.story = {
|
|
||||||
name: 'Group conversation, you on an other device',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function GroupConversationCallIsFull(): JSX.Element {
|
export function GroupConversationCallIsFull(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CallingPreCallInfo
|
<CallingPreCallInfo
|
||||||
|
@ -308,7 +245,3 @@ export function GroupConversationCallIsFull(): JSX.Element {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupConversationCallIsFull.story = {
|
|
||||||
name: 'Group conversation, call is full',
|
|
||||||
};
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ export enum RingMode {
|
||||||
IsRinging,
|
IsRinging,
|
||||||
}
|
}
|
||||||
|
|
||||||
type PropsType = {
|
export type PropsType = {
|
||||||
conversation: Pick<
|
conversation: Pick<
|
||||||
ConversationType,
|
ConversationType,
|
||||||
| 'acceptedMessageRequest'
|
| 'acceptedMessageRequest'
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import type { PropsType } from './CallingScreenSharingController';
|
import type { PropsType } from './CallingScreenSharingController';
|
||||||
import { CallingScreenSharingController } from './CallingScreenSharingController';
|
import { CallingScreenSharingController } from './CallingScreenSharingController';
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CallingScreenSharingController',
|
title: 'Components/CallingScreenSharingController',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Controller(): JSX.Element {
|
export function Controller(): JSX.Element {
|
||||||
return <CallingScreenSharingController {...createProps()} />;
|
return <CallingScreenSharingController {...createProps()} />;
|
||||||
|
@ -37,7 +38,3 @@ export function ReallyLongAppName(): JSX.Element {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReallyLongAppName.story = {
|
|
||||||
name: 'Really long app name',
|
|
||||||
};
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import type { PropsType } from './CallingSelectPresentingSourcesModal';
|
import type { PropsType } from './CallingSelectPresentingSourcesModal';
|
||||||
import { CallingSelectPresentingSourcesModal } from './CallingSelectPresentingSourcesModal';
|
import { CallingSelectPresentingSourcesModal } from './CallingSelectPresentingSourcesModal';
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ const createProps = (): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CallingSelectPresentingSourcesModal',
|
title: 'Components/CallingSelectPresentingSourcesModal',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Modal(): JSX.Element {
|
export function Modal(): JSX.Element {
|
||||||
return <CallingSelectPresentingSourcesModal {...createProps()} />;
|
return <CallingSelectPresentingSourcesModal {...createProps()} />;
|
||||||
|
|
|
@ -3,36 +3,33 @@
|
||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import { boolean } from '@storybook/addon-knobs';
|
import type { Meta } from '@storybook/react';
|
||||||
|
import type { PropsType } from './CaptchaDialog';
|
||||||
import { CaptchaDialog } from './CaptchaDialog';
|
import { CaptchaDialog } from './CaptchaDialog';
|
||||||
import { Button } from './Button';
|
import { Button } from './Button';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
export default {
|
|
||||||
title: 'Components/CaptchaDialog',
|
|
||||||
};
|
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export const _CaptchaDialog = (): JSX.Element => {
|
export default {
|
||||||
|
title: 'Components/CaptchaDialog',
|
||||||
|
argTypes: {
|
||||||
|
isPending: { control: { type: 'boolean' } },
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
i18n,
|
||||||
|
isPending: false,
|
||||||
|
onContinue: action('onContinue'),
|
||||||
|
},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
|
export function Basic(args: PropsType): JSX.Element {
|
||||||
const [isSkipped, setIsSkipped] = useState(false);
|
const [isSkipped, setIsSkipped] = useState(false);
|
||||||
|
|
||||||
if (isSkipped) {
|
if (isSkipped) {
|
||||||
return <Button onClick={() => setIsSkipped(false)}>Show again</Button>;
|
return <Button onClick={() => setIsSkipped(false)}>Show again</Button>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return <CaptchaDialog {...args} onSkip={() => setIsSkipped(true)} />;
|
||||||
<CaptchaDialog
|
}
|
||||||
i18n={i18n}
|
|
||||||
isPending={boolean('isPending', false)}
|
|
||||||
onContinue={action('onContinue')}
|
|
||||||
onSkip={() => setIsSkipped(true)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
_CaptchaDialog.story = {
|
|
||||||
name: 'CaptchaDialog',
|
|
||||||
};
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { Button, ButtonVariant } from './Button';
|
||||||
import { Modal } from './Modal';
|
import { Modal } from './Modal';
|
||||||
import { Spinner } from './Spinner';
|
import { Spinner } from './Spinner';
|
||||||
|
|
||||||
type PropsType = {
|
export type PropsType = {
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
isPending: boolean;
|
isPending: boolean;
|
||||||
|
|
||||||
|
|
|
@ -2,21 +2,45 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import { select } from '@storybook/addon-knobs';
|
import type { Meta } from '@storybook/react';
|
||||||
|
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
import type { PropsType } from './ChatColorPicker';
|
import type { PropsType } from './ChatColorPicker';
|
||||||
import { ChatColorPicker } from './ChatColorPicker';
|
import { ChatColorPicker } from './ChatColorPicker';
|
||||||
import { ConversationColors } from '../types/Colors';
|
import { ConversationColors } from '../types/Colors';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
|
|
||||||
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/ChatColorPicker',
|
title: 'Components/ChatColorPicker',
|
||||||
};
|
argTypes: {
|
||||||
|
selectedColor: {
|
||||||
const i18n = setupI18n('en', enMessages);
|
control: {
|
||||||
|
type: 'select',
|
||||||
|
options: ConversationColors,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
addCustomColor: action('addCustomColor'),
|
||||||
|
colorSelected: action('colorSelected'),
|
||||||
|
editCustomColor: action('editCustomColor'),
|
||||||
|
getConversationsWithCustomColor: (_: string) => Promise.resolve([]),
|
||||||
|
i18n,
|
||||||
|
removeCustomColor: action('removeCustomColor'),
|
||||||
|
removeCustomColorOnConversations: action(
|
||||||
|
'removeCustomColorOnConversations'
|
||||||
|
),
|
||||||
|
resetAllChatColors: action('resetAllChatColors'),
|
||||||
|
resetDefaultChatColor: action('resetDefaultChatColor'),
|
||||||
|
selectedColor: 'basil',
|
||||||
|
selectedCustomColor: {},
|
||||||
|
setGlobalDefaultConversationColor: action(
|
||||||
|
'setGlobalDefaultConversationColor'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
const SAMPLE_CUSTOM_COLOR = {
|
const SAMPLE_CUSTOM_COLOR = {
|
||||||
deg: 90,
|
deg: 90,
|
||||||
|
@ -24,25 +48,8 @@ const SAMPLE_CUSTOM_COLOR = {
|
||||||
start: { hue: 315, saturation: 78 },
|
start: { hue: 315, saturation: 78 },
|
||||||
};
|
};
|
||||||
|
|
||||||
const createProps = (): PropsType => ({
|
export function Default(args: PropsType): JSX.Element {
|
||||||
addCustomColor: action('addCustomColor'),
|
return <ChatColorPicker {...args} />;
|
||||||
colorSelected: action('colorSelected'),
|
|
||||||
editCustomColor: action('editCustomColor'),
|
|
||||||
getConversationsWithCustomColor: (_: string) => Promise.resolve([]),
|
|
||||||
i18n,
|
|
||||||
removeCustomColor: action('removeCustomColor'),
|
|
||||||
removeCustomColorOnConversations: action('removeCustomColorOnConversations'),
|
|
||||||
resetAllChatColors: action('resetAllChatColors'),
|
|
||||||
resetDefaultChatColor: action('resetDefaultChatColor'),
|
|
||||||
selectedColor: select('selectedColor', ConversationColors, 'basil' as const),
|
|
||||||
selectedCustomColor: {},
|
|
||||||
setGlobalDefaultConversationColor: action(
|
|
||||||
'setGlobalDefaultConversationColor'
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
export function Default(): JSX.Element {
|
|
||||||
return <ChatColorPicker {...createProps()} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const CUSTOM_COLORS = {
|
const CUSTOM_COLORS = {
|
||||||
|
@ -62,10 +69,10 @@ const CUSTOM_COLORS = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export function CustomColors(): JSX.Element {
|
export function CustomColors(args: PropsType): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<ChatColorPicker
|
<ChatColorPicker
|
||||||
{...createProps()}
|
{...args}
|
||||||
customColors={CUSTOM_COLORS}
|
customColors={CUSTOM_COLORS}
|
||||||
selectedColor="custom"
|
selectedColor="custom"
|
||||||
selectedCustomColor={{
|
selectedCustomColor={{
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import type { PropsType } from './Checkbox';
|
import type { PropsType } from './Checkbox';
|
||||||
import { Checkbox } from './Checkbox';
|
import { Checkbox } from './Checkbox';
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ const createProps = (): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/Checkbox',
|
title: 'Components/Checkbox',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Normal(): JSX.Element {
|
export function Normal(): JSX.Element {
|
||||||
return <Checkbox {...createProps()} />;
|
return <Checkbox {...createProps()} />;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import type { Props } from './CircleCheckbox';
|
import type { Props } from './CircleCheckbox';
|
||||||
import { CircleCheckbox, Variant } from './CircleCheckbox';
|
import { CircleCheckbox, Variant } from './CircleCheckbox';
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ const createProps = (): Props => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CircleCheckbox',
|
title: 'Components/CircleCheckbox',
|
||||||
};
|
} satisfies Meta<Props>;
|
||||||
|
|
||||||
export function Normal(): JSX.Element {
|
export function Normal(): JSX.Element {
|
||||||
return <CircleCheckbox {...createProps()} />;
|
return <CircleCheckbox {...createProps()} />;
|
||||||
|
|
|
@ -2,23 +2,19 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
import type { PropsType } from './ClearingData';
|
||||||
import { ClearingData } from './ClearingData';
|
import { ClearingData } from './ClearingData';
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/ClearingData',
|
title: 'Components/ClearingData',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export const _ClearingData = (): JSX.Element => (
|
export function Basic(): JSX.Element {
|
||||||
<ClearingData deleteAllData={action('deleteAllData')} i18n={i18n} />
|
return <ClearingData deleteAllData={action('deleteAllData')} i18n={i18n} />;
|
||||||
);
|
}
|
||||||
|
|
||||||
_ClearingData.story = {
|
|
||||||
name: 'Clearing data',
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
// Copyright 2020 Signal Messenger, LLC
|
// Copyright 2020 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { DecoratorFunction } from '@storybook/addons';
|
import React, { useContext } from 'react';
|
||||||
import * as React from 'react';
|
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import { boolean, select } from '@storybook/addon-knobs';
|
import type { Meta } from '@storybook/react';
|
||||||
|
|
||||||
import { IMAGE_JPEG } from '../types/MIME';
|
import { IMAGE_JPEG } from '../types/MIME';
|
||||||
import type { Props } from './CompositionArea';
|
import type { Props } from './CompositionArea';
|
||||||
import { CompositionArea } from './CompositionArea';
|
import { CompositionArea } from './CompositionArea';
|
||||||
|
@ -28,287 +25,256 @@ export default {
|
||||||
decorators: [
|
decorators: [
|
||||||
// necessary for the add attachment button to render properly
|
// necessary for the add attachment button to render properly
|
||||||
storyFn => <div className="file-input">{storyFn()}</div>,
|
storyFn => <div className="file-input">{storyFn()}</div>,
|
||||||
] as Array<DecoratorFunction<JSX.Element>>,
|
],
|
||||||
};
|
argTypes: {
|
||||||
|
recordingState: {
|
||||||
|
control: { type: 'select' },
|
||||||
|
options: Object.keys(RecordingState),
|
||||||
|
mappings: RecordingState,
|
||||||
|
},
|
||||||
|
messageRequestsEnabled: { control: { type: 'boolean' } },
|
||||||
|
announcementsOnly: { control: { type: 'boolean' } },
|
||||||
|
areWePendingApproval: { control: { type: 'boolean' } },
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
addAttachment: action('addAttachment'),
|
||||||
|
conversationId: '123',
|
||||||
|
convertDraftBodyRangesIntoHydrated: () => undefined,
|
||||||
|
discardEditMessage: action('discardEditMessage'),
|
||||||
|
focusCounter: 0,
|
||||||
|
sendCounter: 0,
|
||||||
|
i18n,
|
||||||
|
isDisabled: false,
|
||||||
|
isFormattingFlagEnabled: true,
|
||||||
|
isFormattingSpoilersFlagEnabled: true,
|
||||||
|
isFormattingEnabled: true,
|
||||||
|
messageCompositionId: '456',
|
||||||
|
sendEditedMessage: action('sendEditedMessage'),
|
||||||
|
sendMultiMediaMessage: action('sendMultiMediaMessage'),
|
||||||
|
platform: 'darwin',
|
||||||
|
processAttachments: action('processAttachments'),
|
||||||
|
removeAttachment: action('removeAttachment'),
|
||||||
|
setComposerFocus: action('setComposerFocus'),
|
||||||
|
setMessageToEdit: action('setMessageToEdit'),
|
||||||
|
setQuoteByMessageId: action('setQuoteByMessageId'),
|
||||||
|
showToast: action('showToast'),
|
||||||
|
|
||||||
const useProps = (overrideProps: Partial<Props> = {}): Props => ({
|
// AttachmentList
|
||||||
addAttachment: action('addAttachment'),
|
draftAttachments: [],
|
||||||
conversationId: '123',
|
onClearAttachments: action('onClearAttachments'),
|
||||||
convertDraftBodyRangesIntoHydrated: () => undefined,
|
// AudioCapture
|
||||||
discardEditMessage: action('discardEditMessage'),
|
cancelRecording: action('cancelRecording'),
|
||||||
focusCounter: 0,
|
completeRecording: action('completeRecording'),
|
||||||
sendCounter: 0,
|
errorRecording: action('errorRecording'),
|
||||||
i18n,
|
recordingState: RecordingState.Idle,
|
||||||
isDisabled: false,
|
startRecording: action('startRecording'),
|
||||||
isFormattingFlagEnabled:
|
// StagedLinkPreview
|
||||||
overrideProps.isFormattingFlagEnabled === false
|
linkPreviewLoading: false,
|
||||||
? overrideProps.isFormattingFlagEnabled
|
linkPreviewResult: undefined,
|
||||||
: true,
|
onCloseLinkPreview: action('onCloseLinkPreview'),
|
||||||
isFormattingSpoilersFlagEnabled:
|
// Quote
|
||||||
overrideProps.isFormattingSpoilersFlagEnabled === false
|
quotedMessageProps: undefined,
|
||||||
? overrideProps.isFormattingSpoilersFlagEnabled
|
scrollToMessage: action('scrollToMessage'),
|
||||||
: true,
|
// MediaEditor
|
||||||
isFormattingEnabled:
|
imageToBlurHash: async () => 'LDA,FDBnm+I=p{tkIUI;~UkpELV]',
|
||||||
overrideProps.isFormattingEnabled === false
|
// MediaQualitySelector
|
||||||
? overrideProps.isFormattingEnabled
|
setMediaQualitySetting: action('setMediaQualitySetting'),
|
||||||
: true,
|
shouldSendHighQualityAttachments: false,
|
||||||
messageCompositionId: '456',
|
// CompositionInput
|
||||||
sendEditedMessage: action('sendEditedMessage'),
|
onEditorStateChange: action('onEditorStateChange'),
|
||||||
sendMultiMediaMessage: action('sendMultiMediaMessage'),
|
onTextTooLong: action('onTextTooLong'),
|
||||||
platform: 'darwin',
|
draftText: undefined,
|
||||||
processAttachments: action('processAttachments'),
|
clearQuotedMessage: action('clearQuotedMessage'),
|
||||||
removeAttachment: action('removeAttachment'),
|
getPreferredBadge: () => undefined,
|
||||||
theme: React.useContext(StorybookThemeContext),
|
getQuotedMessage: action('getQuotedMessage'),
|
||||||
setComposerFocus: action('setComposerFocus'),
|
sortedGroupMembers: [],
|
||||||
setMessageToEdit: action('setMessageToEdit'),
|
// EmojiButton
|
||||||
setQuoteByMessageId: action('setQuoteByMessageId'),
|
onPickEmoji: action('onPickEmoji'),
|
||||||
showToast: action('showToast'),
|
onSetSkinTone: action('onSetSkinTone'),
|
||||||
|
recentEmojis: [],
|
||||||
|
skinTone: 1,
|
||||||
|
// StickerButton
|
||||||
|
knownPacks: [],
|
||||||
|
receivedPacks: [],
|
||||||
|
installedPacks: [],
|
||||||
|
blessedPacks: [],
|
||||||
|
recentStickers: [],
|
||||||
|
clearInstalledStickerPack: action('clearInstalledStickerPack'),
|
||||||
|
pushPanelForConversation: action('pushPanelForConversation'),
|
||||||
|
sendStickerMessage: action('sendStickerMessage'),
|
||||||
|
clearShowIntroduction: action('clearShowIntroduction'),
|
||||||
|
showPickerHint: false,
|
||||||
|
clearShowPickerHint: action('clearShowPickerHint'),
|
||||||
|
// Message Requests
|
||||||
|
conversationType: 'direct',
|
||||||
|
acceptConversation: action('acceptConversation'),
|
||||||
|
blockConversation: action('blockConversation'),
|
||||||
|
blockAndReportSpam: action('blockAndReportSpam'),
|
||||||
|
deleteConversation: action('deleteConversation'),
|
||||||
|
messageRequestsEnabled: false,
|
||||||
|
title: '',
|
||||||
|
// GroupV1 Disabled Actions
|
||||||
|
showGV2MigrationDialog: action('showGV2MigrationDialog'),
|
||||||
|
// GroupV2
|
||||||
|
announcementsOnly: false,
|
||||||
|
areWeAdmin: false,
|
||||||
|
areWePendingApproval: false,
|
||||||
|
groupAdmins: [],
|
||||||
|
cancelJoinRequest: action('cancelJoinRequest'),
|
||||||
|
showConversation: action('showConversation'),
|
||||||
|
// SMS-only
|
||||||
|
isSMSOnly: false,
|
||||||
|
isFetchingUUID: false,
|
||||||
|
renderSmartCompositionRecording: _ => <div>RECORDING</div>,
|
||||||
|
renderSmartCompositionRecordingDraft: _ => <div>RECORDING DRAFT</div>,
|
||||||
|
// Select mode
|
||||||
|
selectedMessageIds: undefined,
|
||||||
|
toggleSelectMode: action('toggleSelectMode'),
|
||||||
|
toggleForwardMessagesModal: action('toggleForwardMessagesModal'),
|
||||||
|
},
|
||||||
|
} satisfies Meta<Props>;
|
||||||
|
|
||||||
// AttachmentList
|
export function Default(args: Props): JSX.Element {
|
||||||
draftAttachments: overrideProps.draftAttachments || [],
|
const theme = useContext(StorybookThemeContext);
|
||||||
onClearAttachments: action('onClearAttachments'),
|
return <CompositionArea {...args} theme={theme} />;
|
||||||
// AudioCapture
|
|
||||||
cancelRecording: action('cancelRecording'),
|
|
||||||
completeRecording: action('completeRecording'),
|
|
||||||
errorRecording: action('errorRecording'),
|
|
||||||
recordingState: select(
|
|
||||||
'recordingState',
|
|
||||||
RecordingState,
|
|
||||||
overrideProps.recordingState || RecordingState.Idle
|
|
||||||
),
|
|
||||||
startRecording: action('startRecording'),
|
|
||||||
// StagedLinkPreview
|
|
||||||
linkPreviewLoading: Boolean(overrideProps.linkPreviewLoading),
|
|
||||||
linkPreviewResult: overrideProps.linkPreviewResult,
|
|
||||||
onCloseLinkPreview: action('onCloseLinkPreview'),
|
|
||||||
// Quote
|
|
||||||
quotedMessageProps: overrideProps.quotedMessageProps,
|
|
||||||
scrollToMessage: action('scrollToMessage'),
|
|
||||||
// MediaEditor
|
|
||||||
imageToBlurHash: async () => 'LDA,FDBnm+I=p{tkIUI;~UkpELV]',
|
|
||||||
// MediaQualitySelector
|
|
||||||
setMediaQualitySetting: action('setMediaQualitySetting'),
|
|
||||||
shouldSendHighQualityAttachments: Boolean(
|
|
||||||
overrideProps.shouldSendHighQualityAttachments
|
|
||||||
),
|
|
||||||
// CompositionInput
|
|
||||||
onEditorStateChange: action('onEditorStateChange'),
|
|
||||||
onTextTooLong: action('onTextTooLong'),
|
|
||||||
draftText: overrideProps.draftText || undefined,
|
|
||||||
clearQuotedMessage: action('clearQuotedMessage'),
|
|
||||||
getPreferredBadge: () => undefined,
|
|
||||||
getQuotedMessage: action('getQuotedMessage'),
|
|
||||||
sortedGroupMembers: [],
|
|
||||||
// EmojiButton
|
|
||||||
onPickEmoji: action('onPickEmoji'),
|
|
||||||
onSetSkinTone: action('onSetSkinTone'),
|
|
||||||
recentEmojis: [],
|
|
||||||
skinTone: 1,
|
|
||||||
// StickerButton
|
|
||||||
knownPacks: overrideProps.knownPacks || [],
|
|
||||||
receivedPacks: [],
|
|
||||||
installedPacks: [],
|
|
||||||
blessedPacks: [],
|
|
||||||
recentStickers: [],
|
|
||||||
clearInstalledStickerPack: action('clearInstalledStickerPack'),
|
|
||||||
pushPanelForConversation: action('pushPanelForConversation'),
|
|
||||||
sendStickerMessage: action('sendStickerMessage'),
|
|
||||||
clearShowIntroduction: action('clearShowIntroduction'),
|
|
||||||
showPickerHint: false,
|
|
||||||
clearShowPickerHint: action('clearShowPickerHint'),
|
|
||||||
// Message Requests
|
|
||||||
conversationType: 'direct',
|
|
||||||
acceptConversation: action('acceptConversation'),
|
|
||||||
blockConversation: action('blockConversation'),
|
|
||||||
blockAndReportSpam: action('blockAndReportSpam'),
|
|
||||||
deleteConversation: action('deleteConversation'),
|
|
||||||
messageRequestsEnabled: boolean(
|
|
||||||
'messageRequestsEnabled',
|
|
||||||
overrideProps.messageRequestsEnabled || false
|
|
||||||
),
|
|
||||||
title: '',
|
|
||||||
// GroupV1 Disabled Actions
|
|
||||||
showGV2MigrationDialog: action('showGV2MigrationDialog'),
|
|
||||||
// GroupV2
|
|
||||||
announcementsOnly: boolean(
|
|
||||||
'announcementsOnly',
|
|
||||||
Boolean(overrideProps.announcementsOnly)
|
|
||||||
),
|
|
||||||
areWeAdmin: boolean('areWeAdmin', Boolean(overrideProps.areWeAdmin)),
|
|
||||||
areWePendingApproval: boolean(
|
|
||||||
'areWePendingApproval',
|
|
||||||
Boolean(overrideProps.areWePendingApproval)
|
|
||||||
),
|
|
||||||
groupAdmins: [],
|
|
||||||
cancelJoinRequest: action('cancelJoinRequest'),
|
|
||||||
showConversation: action('showConversation'),
|
|
||||||
// SMS-only
|
|
||||||
isSMSOnly: overrideProps.isSMSOnly || false,
|
|
||||||
isFetchingUUID: overrideProps.isFetchingUUID || false,
|
|
||||||
renderSmartCompositionRecording: _ => <div>RECORDING</div>,
|
|
||||||
renderSmartCompositionRecordingDraft: _ => <div>RECORDING DRAFT</div>,
|
|
||||||
// Select mode
|
|
||||||
selectedMessageIds: undefined,
|
|
||||||
toggleSelectMode: action('toggleSelectMode'),
|
|
||||||
toggleForwardMessagesModal: action('toggleForwardMessagesModal'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export function Default(): JSX.Element {
|
|
||||||
const props = useProps();
|
|
||||||
|
|
||||||
return <CompositionArea {...props} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function StartingText(): JSX.Element {
|
export function StartingText(args: Props): JSX.Element {
|
||||||
const props = useProps({
|
const theme = useContext(StorybookThemeContext);
|
||||||
draftText: "here's some starting text",
|
|
||||||
});
|
|
||||||
|
|
||||||
return <CompositionArea {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function StickerButton(): JSX.Element {
|
|
||||||
const props = useProps({
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
knownPacks: [{} as any],
|
|
||||||
});
|
|
||||||
|
|
||||||
return <CompositionArea {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function MessageRequest(): JSX.Element {
|
|
||||||
const props = useProps({
|
|
||||||
messageRequestsEnabled: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
return <CompositionArea {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function SmsOnlyFetchingUuid(): JSX.Element {
|
|
||||||
const props = useProps({
|
|
||||||
isSMSOnly: true,
|
|
||||||
isFetchingUUID: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
return <CompositionArea {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
SmsOnlyFetchingUuid.story = {
|
|
||||||
name: 'SMS-only fetching UUID',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function SmsOnly(): JSX.Element {
|
|
||||||
const props = useProps({
|
|
||||||
isSMSOnly: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
return <CompositionArea {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
SmsOnly.story = {
|
|
||||||
name: 'SMS-only',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Attachments(): JSX.Element {
|
|
||||||
const props = useProps({
|
|
||||||
draftAttachments: [
|
|
||||||
fakeDraftAttachment({
|
|
||||||
contentType: IMAGE_JPEG,
|
|
||||||
url: landscapeGreenUrl,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
return <CompositionArea {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function PendingApproval(): JSX.Element {
|
|
||||||
return (
|
return (
|
||||||
<CompositionArea
|
<CompositionArea
|
||||||
{...useProps({
|
{...args}
|
||||||
areWePendingApproval: true,
|
theme={theme}
|
||||||
})}
|
draftText="here's some starting text"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
AnnouncementsOnlyGroup.story = {
|
export function StickerButton(args: Props): JSX.Element {
|
||||||
name: 'Announcements Only group',
|
const theme = useContext(StorybookThemeContext);
|
||||||
};
|
|
||||||
|
|
||||||
export function AnnouncementsOnlyGroup(): JSX.Element {
|
|
||||||
return (
|
return (
|
||||||
<CompositionArea
|
<CompositionArea
|
||||||
{...useProps({
|
{...args}
|
||||||
announcementsOnly: true,
|
theme={theme}
|
||||||
areWeAdmin: false,
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
})}
|
knownPacks={[{} as any]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
AnnouncementsOnlyGroup.story = {
|
export function MessageRequest(args: Props): JSX.Element {
|
||||||
name: 'Announcements Only group',
|
const theme = useContext(StorybookThemeContext);
|
||||||
};
|
return <CompositionArea {...args} theme={theme} messageRequestsEnabled />;
|
||||||
|
}
|
||||||
|
|
||||||
export function Quote(): JSX.Element {
|
export function SmsOnlyFetchingUuid(args: Props): JSX.Element {
|
||||||
|
const theme = useContext(StorybookThemeContext);
|
||||||
|
return <CompositionArea {...args} theme={theme} isSMSOnly isFetchingUUID />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SmsOnly(args: Props): JSX.Element {
|
||||||
|
const theme = useContext(StorybookThemeContext);
|
||||||
|
return <CompositionArea {...args} theme={theme} isSMSOnly />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Attachments(args: Props): JSX.Element {
|
||||||
|
const theme = useContext(StorybookThemeContext);
|
||||||
return (
|
return (
|
||||||
<CompositionArea
|
<CompositionArea
|
||||||
{...useProps({
|
{...args}
|
||||||
quotedMessageProps: {
|
theme={theme}
|
||||||
text: 'something',
|
draftAttachments={[
|
||||||
conversationColor: ConversationColors[10],
|
fakeDraftAttachment({
|
||||||
conversationTitle: getDefaultConversation().title,
|
contentType: IMAGE_JPEG,
|
||||||
isGiftBadge: false,
|
url: landscapeGreenUrl,
|
||||||
isViewOnce: false,
|
}),
|
||||||
referencedMessageNotFound: false,
|
]}
|
||||||
authorTitle: 'Someone',
|
/>
|
||||||
isFromMe: false,
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PendingApproval(args: Props): JSX.Element {
|
||||||
|
const theme = useContext(StorybookThemeContext);
|
||||||
|
return <CompositionArea {...args} theme={theme} areWePendingApproval />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AnnouncementsOnlyGroup(args: Props): JSX.Element {
|
||||||
|
const theme = useContext(StorybookThemeContext);
|
||||||
|
return (
|
||||||
|
<CompositionArea
|
||||||
|
{...args}
|
||||||
|
theme={theme}
|
||||||
|
announcementsOnly
|
||||||
|
areWeAdmin={false}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Quote(args: Props): JSX.Element {
|
||||||
|
const theme = useContext(StorybookThemeContext);
|
||||||
|
return (
|
||||||
|
<CompositionArea
|
||||||
|
{...args}
|
||||||
|
theme={theme}
|
||||||
|
quotedMessageProps={{
|
||||||
|
text: 'something',
|
||||||
|
conversationColor: ConversationColors[10],
|
||||||
|
conversationTitle: getDefaultConversation().title,
|
||||||
|
isGiftBadge: false,
|
||||||
|
isViewOnce: false,
|
||||||
|
referencedMessageNotFound: false,
|
||||||
|
authorTitle: 'Someone',
|
||||||
|
isFromMe: false,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function QuoteWithPayment(args: Props): JSX.Element {
|
||||||
|
const theme = useContext(StorybookThemeContext);
|
||||||
|
return (
|
||||||
|
<CompositionArea
|
||||||
|
{...args}
|
||||||
|
theme={theme}
|
||||||
|
quotedMessageProps={{
|
||||||
|
text: '',
|
||||||
|
conversationColor: ConversationColors[10],
|
||||||
|
conversationTitle: getDefaultConversation().title,
|
||||||
|
isGiftBadge: false,
|
||||||
|
isViewOnce: false,
|
||||||
|
referencedMessageNotFound: false,
|
||||||
|
authorTitle: 'Someone',
|
||||||
|
isFromMe: false,
|
||||||
|
payment: {
|
||||||
|
kind: PaymentEventKind.Notification,
|
||||||
|
note: 'Thanks',
|
||||||
},
|
},
|
||||||
})}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function QuoteWithPayment(): JSX.Element {
|
export function NoFormattingMenu(args: Props): JSX.Element {
|
||||||
|
const theme = useContext(StorybookThemeContext);
|
||||||
|
return (
|
||||||
|
<CompositionArea {...args} theme={theme} isFormattingEnabled={false} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NoFormattingFlag(args: Props): JSX.Element {
|
||||||
|
const theme = useContext(StorybookThemeContext);
|
||||||
|
return (
|
||||||
|
<CompositionArea {...args} theme={theme} isFormattingFlagEnabled={false} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NoSpoilerFormattingFlag(args: Props): JSX.Element {
|
||||||
|
const theme = useContext(StorybookThemeContext);
|
||||||
return (
|
return (
|
||||||
<CompositionArea
|
<CompositionArea
|
||||||
{...useProps({
|
{...args}
|
||||||
quotedMessageProps: {
|
theme={theme}
|
||||||
text: '',
|
isFormattingSpoilersFlagEnabled={false}
|
||||||
conversationColor: ConversationColors[10],
|
|
||||||
conversationTitle: getDefaultConversation().title,
|
|
||||||
isGiftBadge: false,
|
|
||||||
isViewOnce: false,
|
|
||||||
referencedMessageNotFound: false,
|
|
||||||
authorTitle: 'Someone',
|
|
||||||
isFromMe: false,
|
|
||||||
payment: {
|
|
||||||
kind: PaymentEventKind.Notification,
|
|
||||||
note: 'Thanks',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
QuoteWithPayment.story = {
|
|
||||||
name: 'Quote with payment',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function NoFormattingMenu(): JSX.Element {
|
|
||||||
return <CompositionArea {...useProps({ isFormattingEnabled: false })} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function NoFormattingFlag(): JSX.Element {
|
|
||||||
return <CompositionArea {...useProps({ isFormattingFlagEnabled: false })} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function NoSpoilerFormattingFlag(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<CompositionArea
|
|
||||||
{...useProps({ isFormattingSpoilersFlagEnabled: false })}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,9 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import 'react-quill/dist/quill.core.css';
|
import 'react-quill/dist/quill.core.css';
|
||||||
import { boolean, select } from '@storybook/addon-knobs';
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
|
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
|
||||||
import type { Props } from './CompositionInput';
|
import type { Props } from './CompositionInput';
|
||||||
import { CompositionInput } from './CompositionInput';
|
import { CompositionInput } from './CompositionInput';
|
||||||
|
@ -19,11 +17,13 @@ const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CompositionInput',
|
title: 'Components/CompositionInput',
|
||||||
};
|
argTypes: {},
|
||||||
|
args: {},
|
||||||
|
} satisfies Meta<Props>;
|
||||||
|
|
||||||
const useProps = (overrideProps: Partial<Props> = {}): Props => ({
|
const useProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||||
i18n,
|
i18n,
|
||||||
disabled: boolean('disabled', overrideProps.disabled || false),
|
disabled: overrideProps.disabled ?? false,
|
||||||
draftText: overrideProps.draftText || undefined,
|
draftText: overrideProps.draftText || undefined,
|
||||||
draftBodyRanges: overrideProps.draftBodyRanges || [],
|
draftBodyRanges: overrideProps.draftBodyRanges || [],
|
||||||
clearQuotedMessage: action('clearQuotedMessage'),
|
clearQuotedMessage: action('clearQuotedMessage'),
|
||||||
|
@ -41,7 +41,7 @@ const useProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||||
overrideProps.isFormattingEnabled === false
|
overrideProps.isFormattingEnabled === false
|
||||||
? overrideProps.isFormattingEnabled
|
? overrideProps.isFormattingEnabled
|
||||||
: true,
|
: true,
|
||||||
large: boolean('large', overrideProps.large || false),
|
large: overrideProps.large ?? false,
|
||||||
onCloseLinkPreview: action('onCloseLinkPreview'),
|
onCloseLinkPreview: action('onCloseLinkPreview'),
|
||||||
onEditorStateChange: action('onEditorStateChange'),
|
onEditorStateChange: action('onEditorStateChange'),
|
||||||
onPickEmoji: action('onPickEmoji'),
|
onPickEmoji: action('onPickEmoji'),
|
||||||
|
@ -49,19 +49,8 @@ const useProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||||
onTextTooLong: action('onTextTooLong'),
|
onTextTooLong: action('onTextTooLong'),
|
||||||
platform: 'darwin',
|
platform: 'darwin',
|
||||||
sendCounter: 0,
|
sendCounter: 0,
|
||||||
sortedGroupMembers: overrideProps.sortedGroupMembers || [],
|
sortedGroupMembers: overrideProps.sortedGroupMembers ?? [],
|
||||||
skinTone: select(
|
skinTone: overrideProps.skinTone ?? undefined,
|
||||||
'skinTone',
|
|
||||||
{
|
|
||||||
skinTone0: 0,
|
|
||||||
skinTone1: 1,
|
|
||||||
skinTone2: 2,
|
|
||||||
skinTone3: 3,
|
|
||||||
skinTone4: 4,
|
|
||||||
skinTone5: 5,
|
|
||||||
},
|
|
||||||
overrideProps.skinTone || undefined
|
|
||||||
),
|
|
||||||
theme: React.useContext(StorybookThemeContext),
|
theme: React.useContext(StorybookThemeContext),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
|
import type { Props } from './CompositionRecording';
|
||||||
import { CompositionRecording } from './CompositionRecording';
|
import { CompositionRecording } from './CompositionRecording';
|
||||||
|
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
|
@ -13,7 +14,7 @@ const i18n = setupI18n('en', enMessages);
|
||||||
export default {
|
export default {
|
||||||
title: 'components/CompositionRecording',
|
title: 'components/CompositionRecording',
|
||||||
component: CompositionRecording,
|
component: CompositionRecording,
|
||||||
};
|
} satisfies Meta<Props>;
|
||||||
|
|
||||||
export function Default(): JSX.Element {
|
export function Default(): JSX.Element {
|
||||||
const [active, setActive] = useState(false);
|
const [active, setActive] = useState(false);
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
|
import type { Props } from './CompositionRecordingDraft';
|
||||||
import { CompositionRecordingDraft } from './CompositionRecordingDraft';
|
import { CompositionRecordingDraft } from './CompositionRecordingDraft';
|
||||||
|
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
|
@ -13,7 +14,7 @@ const i18n = setupI18n('en', enMessages);
|
||||||
export default {
|
export default {
|
||||||
title: 'components/CompositionRecordingDraft',
|
title: 'components/CompositionRecordingDraft',
|
||||||
component: CompositionRecordingDraft,
|
component: CompositionRecordingDraft,
|
||||||
};
|
} satisfies Meta<Props>;
|
||||||
|
|
||||||
export function Default(): JSX.Element {
|
export function Default(): JSX.Element {
|
||||||
const [isPlaying, setIsPlaying] = useState(false);
|
const [isPlaying, setIsPlaying] = useState(false);
|
||||||
|
|
|
@ -11,7 +11,7 @@ import * as log from '../logging/log';
|
||||||
import type { Size } from '../hooks/useSizeObserver';
|
import type { Size } from '../hooks/useSizeObserver';
|
||||||
import { SizeObserver } from '../hooks/useSizeObserver';
|
import { SizeObserver } from '../hooks/useSizeObserver';
|
||||||
|
|
||||||
type Props = {
|
export type Props = {
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
audioUrl: string | undefined;
|
audioUrl: string | undefined;
|
||||||
active:
|
active:
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ const createProps = (): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/ConfirmDiscardDialog',
|
title: 'Components/ConfirmDiscardDialog',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Default(): JSX.Element {
|
export function Default(): JSX.Element {
|
||||||
return <ConfirmDiscardDialog {...createProps()} />;
|
return <ConfirmDiscardDialog {...createProps()} />;
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
|
import type { Props } from './ConfirmationDialog';
|
||||||
import { ConfirmationDialog } from './ConfirmationDialog';
|
import { ConfirmationDialog } from './ConfirmationDialog';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
@ -12,9 +14,9 @@ const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/ConfirmationDialog',
|
title: 'Components/ConfirmationDialog',
|
||||||
};
|
} satisfies Meta<Props>;
|
||||||
|
|
||||||
export const _ConfirmationDialog = (): JSX.Element => {
|
export function Basic(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<ConfirmationDialog
|
<ConfirmationDialog
|
||||||
dialogName="test"
|
dialogName="test"
|
||||||
|
@ -37,11 +39,7 @@ export const _ConfirmationDialog = (): JSX.Element => {
|
||||||
asdf blip
|
asdf blip
|
||||||
</ConfirmationDialog>
|
</ConfirmationDialog>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
_ConfirmationDialog.story = {
|
|
||||||
name: 'ConfirmationDialog',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function CustomCancelText(): JSX.Element {
|
export function CustomCancelText(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
@ -64,10 +62,6 @@ export function CustomCancelText(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomCancelText.story = {
|
|
||||||
name: 'Custom cancel text',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function NoDefaultCancel(): JSX.Element {
|
export function NoDefaultCancel(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<ConfirmationDialog
|
<ConfirmationDialog
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { times } from 'lodash';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
import { ContactPills } from './ContactPills';
|
import { ContactPills } from './ContactPills';
|
||||||
|
@ -18,7 +19,7 @@ const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/Contact Pills',
|
title: 'Components/Contact Pills',
|
||||||
};
|
} satisfies Meta<ContactPillPropsType>;
|
||||||
|
|
||||||
type ContactType = Omit<ContactPillPropsType, 'i18n' | 'onClickRemove'>;
|
type ContactType = Omit<ContactPillPropsType, 'i18n' | 'onClickRemove'>;
|
||||||
|
|
||||||
|
@ -54,10 +55,6 @@ export function EmptyList(): JSX.Element {
|
||||||
return <ContactPills />;
|
return <ContactPills />;
|
||||||
}
|
}
|
||||||
|
|
||||||
EmptyList.story = {
|
|
||||||
name: 'Empty list',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function OneContact(): JSX.Element {
|
export function OneContact(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<ContactPills>
|
<ContactPills>
|
||||||
|
@ -66,10 +63,6 @@ export function OneContact(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
OneContact.story = {
|
|
||||||
name: 'One contact',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ThreeContacts(): JSX.Element {
|
export function ThreeContacts(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<ContactPills>
|
<ContactPills>
|
||||||
|
@ -80,10 +73,6 @@ export function ThreeContacts(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreeContacts.story = {
|
|
||||||
name: 'Three contacts',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function FourContactsOneWithALongName(): JSX.Element {
|
export function FourContactsOneWithALongName(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<ContactPills>
|
<ContactPills>
|
||||||
|
@ -101,10 +90,6 @@ export function FourContactsOneWithALongName(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
FourContactsOneWithALongName.story = {
|
|
||||||
name: 'Four contacts, one with a long name',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function FiftyContacts(): JSX.Element {
|
export function FiftyContacts(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<ContactPills>
|
<ContactPills>
|
||||||
|
@ -114,7 +99,3 @@ export function FiftyContacts(): JSX.Element {
|
||||||
</ContactPills>
|
</ContactPills>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
FiftyContacts.story = {
|
|
||||||
name: 'Fifty contacts',
|
|
||||||
};
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import type { PropsType } from './ContextMenu';
|
import type { PropsType } from './ContextMenu';
|
||||||
import { ContextMenu } from './ContextMenu';
|
import { ContextMenu } from './ContextMenu';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
@ -13,7 +14,7 @@ const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/ContextMenu',
|
title: 'Components/ContextMenu',
|
||||||
};
|
} satisfies Meta<PropsType<unknown>>;
|
||||||
|
|
||||||
const getDefaultProps = (): PropsType<number> => ({
|
const getDefaultProps = (): PropsType<number> => ({
|
||||||
i18n,
|
i18n,
|
||||||
|
|
|
@ -4,11 +4,9 @@
|
||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
import { times, omit } from 'lodash';
|
import { times, omit } from 'lodash';
|
||||||
import { v4 as generateUuid } from 'uuid';
|
import { v4 as generateUuid } from 'uuid';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import { boolean, date, select, text } from '@storybook/addon-knobs';
|
import type { Meta } from '@storybook/react';
|
||||||
|
import type { Row, PropsType } from './ConversationList';
|
||||||
import type { Row } from './ConversationList';
|
|
||||||
import { ConversationList, RowType } from './ConversationList';
|
import { ConversationList, RowType } from './ConversationList';
|
||||||
import { MessageSearchResult } from './conversationList/MessageSearchResult';
|
import { MessageSearchResult } from './conversationList/MessageSearchResult';
|
||||||
import type { PropsData as ConversationListItemPropsType } from './conversationList/ConversationListItem';
|
import type { PropsData as ConversationListItemPropsType } from './conversationList/ConversationListItem';
|
||||||
|
@ -25,7 +23,9 @@ const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/ConversationList',
|
title: 'Components/ConversationList',
|
||||||
};
|
argTypes: {},
|
||||||
|
args: {},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
const defaultConversations: Array<ConversationListItemPropsType> = [
|
const defaultConversations: Array<ConversationListItemPropsType> = [
|
||||||
getDefaultConversation({
|
getDefaultConversation({
|
||||||
|
@ -105,15 +105,13 @@ function Wrapper({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const _ArchiveButton = (): JSX.Element => (
|
export function ArchiveButton(): JSX.Element {
|
||||||
<Wrapper
|
return (
|
||||||
rows={[{ type: RowType.ArchiveButton, archivedConversationsCount: 123 }]}
|
<Wrapper
|
||||||
/>
|
rows={[{ type: RowType.ArchiveButton, archivedConversationsCount: 123 }]}
|
||||||
);
|
/>
|
||||||
|
);
|
||||||
_ArchiveButton.story = {
|
}
|
||||||
name: 'Archive button',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ContactNoteToSelf(): JSX.Element {
|
export function ContactNoteToSelf(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
@ -132,10 +130,6 @@ export function ContactNoteToSelf(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactNoteToSelf.story = {
|
|
||||||
name: 'Contact: note to self',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ContactDirect(): JSX.Element {
|
export function ContactDirect(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
|
@ -144,10 +138,6 @@ export function ContactDirect(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactDirect.story = {
|
|
||||||
name: 'Contact: direct',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ContactDirectWithContextMenu(): JSX.Element {
|
export function ContactDirectWithContextMenu(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
|
@ -162,10 +152,6 @@ export function ContactDirectWithContextMenu(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactDirectWithContextMenu.story = {
|
|
||||||
name: 'Contact: context menu',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ContactDirectWithShortAbout(): JSX.Element {
|
export function ContactDirectWithShortAbout(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
|
@ -179,10 +165,6 @@ export function ContactDirectWithShortAbout(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactDirectWithShortAbout.story = {
|
|
||||||
name: 'Contact: direct with short about',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ContactDirectWithLongAbout(): JSX.Element {
|
export function ContactDirectWithLongAbout(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
|
@ -200,10 +182,6 @@ export function ContactDirectWithLongAbout(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactDirectWithLongAbout.story = {
|
|
||||||
name: 'Contact: direct with long about',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ContactGroup(): JSX.Element {
|
export function ContactGroup(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
|
@ -217,10 +195,6 @@ export function ContactGroup(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactGroup.story = {
|
|
||||||
name: 'Contact: group',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ContactCheckboxes(): JSX.Element {
|
export function ContactCheckboxes(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
|
@ -248,10 +222,6 @@ export function ContactCheckboxes(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactCheckboxes.story = {
|
|
||||||
name: 'Contact checkboxes',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ContactCheckboxesDisabled(): JSX.Element {
|
export function ContactCheckboxesDisabled(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
|
@ -279,42 +249,29 @@ export function ContactCheckboxesDisabled(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactCheckboxesDisabled.story = {
|
|
||||||
name: 'Contact checkboxes: disabled',
|
|
||||||
};
|
|
||||||
|
|
||||||
const createConversation = (
|
const createConversation = (
|
||||||
overrideProps: Partial<ConversationListItemPropsType> = {}
|
overrideProps: Partial<ConversationListItemPropsType> = {}
|
||||||
): ConversationListItemPropsType => ({
|
): ConversationListItemPropsType => ({
|
||||||
...overrideProps,
|
...overrideProps,
|
||||||
acceptedMessageRequest: boolean(
|
acceptedMessageRequest:
|
||||||
'acceptedMessageRequest',
|
|
||||||
overrideProps.acceptedMessageRequest !== undefined
|
overrideProps.acceptedMessageRequest !== undefined
|
||||||
? overrideProps.acceptedMessageRequest
|
? overrideProps.acceptedMessageRequest
|
||||||
: true
|
: true,
|
||||||
),
|
|
||||||
badges: [],
|
badges: [],
|
||||||
isMe: boolean('isMe', overrideProps.isMe || false),
|
isMe: overrideProps.isMe ?? false,
|
||||||
avatarPath: text('avatarPath', overrideProps.avatarPath || ''),
|
avatarPath: overrideProps.avatarPath ?? '',
|
||||||
id: overrideProps.id || '',
|
id: overrideProps.id || '',
|
||||||
isSelected: boolean('isSelected', overrideProps.isSelected || false),
|
isSelected: overrideProps.isSelected ?? false,
|
||||||
title: text('title', overrideProps.title || 'Some Person'),
|
title: overrideProps.title ?? 'Some Person',
|
||||||
profileName: overrideProps.profileName || 'Some Person',
|
profileName: overrideProps.profileName || 'Some Person',
|
||||||
type: overrideProps.type || 'direct',
|
type: overrideProps.type || 'direct',
|
||||||
markedUnread: boolean('markedUnread', overrideProps.markedUnread || false),
|
markedUnread: overrideProps.markedUnread ?? false,
|
||||||
lastMessage: overrideProps.lastMessage || {
|
lastMessage: overrideProps.lastMessage || {
|
||||||
text: text('lastMessage.text', 'Hi there!'),
|
text: 'Hi there!',
|
||||||
status: select(
|
status: 'read',
|
||||||
'status',
|
|
||||||
MessageStatuses.reduce((m, s) => ({ ...m, [s]: s }), {}),
|
|
||||||
'read'
|
|
||||||
),
|
|
||||||
deletedForEveryone: false,
|
deletedForEveryone: false,
|
||||||
},
|
},
|
||||||
lastUpdated: date(
|
lastUpdated: overrideProps.lastUpdated ?? Date.now() - 5 * 60 * 1000,
|
||||||
'lastUpdated',
|
|
||||||
new Date(overrideProps.lastUpdated || Date.now() - 5 * 60 * 1000)
|
|
||||||
),
|
|
||||||
sharedGroupNames: [],
|
sharedGroupNames: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -333,19 +290,11 @@ const renderConversation = (
|
||||||
|
|
||||||
export const ConversationName = (): JSX.Element => renderConversation();
|
export const ConversationName = (): JSX.Element => renderConversation();
|
||||||
|
|
||||||
ConversationName.story = {
|
|
||||||
name: 'Conversation: name',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConversationNameAndAvatar = (): JSX.Element =>
|
export const ConversationNameAndAvatar = (): JSX.Element =>
|
||||||
renderConversation({
|
renderConversation({
|
||||||
avatarPath: '/fixtures/kitten-1-64-64.jpg',
|
avatarPath: '/fixtures/kitten-1-64-64.jpg',
|
||||||
});
|
});
|
||||||
|
|
||||||
ConversationNameAndAvatar.story = {
|
|
||||||
name: 'Conversation: name and avatar',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConversationWithYourself = (): JSX.Element =>
|
export const ConversationWithYourself = (): JSX.Element =>
|
||||||
renderConversation({
|
renderConversation({
|
||||||
lastMessage: {
|
lastMessage: {
|
||||||
|
@ -358,10 +307,6 @@ export const ConversationWithYourself = (): JSX.Element =>
|
||||||
isMe: true,
|
isMe: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
ConversationWithYourself.story = {
|
|
||||||
name: 'Conversation: with yourself',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ConversationsMessageStatuses(): JSX.Element {
|
export function ConversationsMessageStatuses(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
|
@ -375,21 +320,13 @@ export function ConversationsMessageStatuses(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConversationsMessageStatuses.story = {
|
|
||||||
name: 'Conversations: Message Statuses',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConversationTypingStatus = (): JSX.Element =>
|
export const ConversationTypingStatus = (): JSX.Element =>
|
||||||
renderConversation({
|
renderConversation({
|
||||||
typingContactIdTimestamps: {
|
typingContactIdTimestamps: {
|
||||||
[generateUuid()]: date('timestamp', new Date()),
|
[generateUuid()]: Date.now(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
ConversationTypingStatus.story = {
|
|
||||||
name: 'Conversation: Typing Status',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConversationWithDraft = (): JSX.Element =>
|
export const ConversationWithDraft = (): JSX.Element =>
|
||||||
renderConversation({
|
renderConversation({
|
||||||
shouldShowDraft: true,
|
shouldShowDraft: true,
|
||||||
|
@ -400,19 +337,11 @@ export const ConversationWithDraft = (): JSX.Element =>
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
ConversationWithDraft.story = {
|
|
||||||
name: 'Conversation: With draft',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConversationDeletedForEveryone = (): JSX.Element =>
|
export const ConversationDeletedForEveryone = (): JSX.Element =>
|
||||||
renderConversation({
|
renderConversation({
|
||||||
lastMessage: { deletedForEveryone: true },
|
lastMessage: { deletedForEveryone: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
ConversationDeletedForEveryone.story = {
|
|
||||||
name: 'Conversation: Deleted for everyone',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConversationMessageRequest = (): JSX.Element =>
|
export const ConversationMessageRequest = (): JSX.Element =>
|
||||||
renderConversation({
|
renderConversation({
|
||||||
acceptedMessageRequest: false,
|
acceptedMessageRequest: false,
|
||||||
|
@ -423,10 +352,6 @@ export const ConversationMessageRequest = (): JSX.Element =>
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
ConversationMessageRequest.story = {
|
|
||||||
name: 'Conversation: Message Request',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ConversationsUnreadCount(): JSX.Element {
|
export function ConversationsUnreadCount(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
|
@ -445,17 +370,9 @@ export function ConversationsUnreadCount(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConversationsUnreadCount.story = {
|
|
||||||
name: 'Conversations: unread count',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConversationMarkedUnread = (): JSX.Element =>
|
export const ConversationMarkedUnread = (): JSX.Element =>
|
||||||
renderConversation({ markedUnread: true });
|
renderConversation({ markedUnread: true });
|
||||||
|
|
||||||
ConversationMarkedUnread.story = {
|
|
||||||
name: 'Conversation: marked unread',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConversationSelected = (): JSX.Element =>
|
export const ConversationSelected = (): JSX.Element =>
|
||||||
renderConversation({
|
renderConversation({
|
||||||
lastMessage: {
|
lastMessage: {
|
||||||
|
@ -466,10 +383,6 @@ export const ConversationSelected = (): JSX.Element =>
|
||||||
isSelected: true,
|
isSelected: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
ConversationSelected.story = {
|
|
||||||
name: 'Conversation: Selected',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConversationEmojiInMessage = (): JSX.Element =>
|
export const ConversationEmojiInMessage = (): JSX.Element =>
|
||||||
renderConversation({
|
renderConversation({
|
||||||
lastMessage: {
|
lastMessage: {
|
||||||
|
@ -479,10 +392,6 @@ export const ConversationEmojiInMessage = (): JSX.Element =>
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
ConversationEmojiInMessage.story = {
|
|
||||||
name: 'Conversation: Emoji in Message',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConversationLinkInMessage = (): JSX.Element =>
|
export const ConversationLinkInMessage = (): JSX.Element =>
|
||||||
renderConversation({
|
renderConversation({
|
||||||
lastMessage: {
|
lastMessage: {
|
||||||
|
@ -492,10 +401,6 @@ export const ConversationLinkInMessage = (): JSX.Element =>
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
ConversationLinkInMessage.story = {
|
|
||||||
name: 'Conversation: Link in Message',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConversationLongName = (): JSX.Element => {
|
export const ConversationLongName = (): JSX.Element => {
|
||||||
const name =
|
const name =
|
||||||
'Long contact name. Esquire. The third. And stuff. And more! And more!';
|
'Long contact name. Esquire. The third. And stuff. And more! And more!';
|
||||||
|
@ -505,10 +410,6 @@ export const ConversationLongName = (): JSX.Element => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
ConversationLongName.story = {
|
|
||||||
name: 'Conversation: long name',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ConversationLongMessage(): JSX.Element {
|
export function ConversationLongMessage(): JSX.Element {
|
||||||
const messages = [
|
const messages = [
|
||||||
"Long line. This is a really really really long line. Really really long. Because that's just how it is",
|
"Long line. This is a really really really long line. Really really long. Because that's just how it is",
|
||||||
|
@ -534,10 +435,6 @@ Line 4, well.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConversationLongMessage.story = {
|
|
||||||
name: 'Conversation: Long Message',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ConversationsVariousTimes(): JSX.Element {
|
export function ConversationsVariousTimes(): JSX.Element {
|
||||||
const pairs: Array<[number, string]> = [
|
const pairs: Array<[number, string]> = [
|
||||||
[Date.now() - 5 * 60 * 60 * 1000, 'Five hours ago'],
|
[Date.now() - 5 * 60 * 60 * 1000, 'Five hours ago'],
|
||||||
|
@ -563,10 +460,6 @@ export function ConversationsVariousTimes(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConversationsVariousTimes.story = {
|
|
||||||
name: 'Conversations: Various Times',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ConversationMissingDate(): JSX.Element {
|
export function ConversationMissingDate(): JSX.Element {
|
||||||
const row = {
|
const row = {
|
||||||
type: RowType.Conversation as const,
|
type: RowType.Conversation as const,
|
||||||
|
@ -576,10 +469,6 @@ export function ConversationMissingDate(): JSX.Element {
|
||||||
return <Wrapper rows={[row]} />;
|
return <Wrapper rows={[row]} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConversationMissingDate.story = {
|
|
||||||
name: 'Conversation: Missing Date',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ConversationMissingMessage(): JSX.Element {
|
export function ConversationMissingMessage(): JSX.Element {
|
||||||
const row = {
|
const row = {
|
||||||
type: RowType.Conversation as const,
|
type: RowType.Conversation as const,
|
||||||
|
@ -589,10 +478,6 @@ export function ConversationMissingMessage(): JSX.Element {
|
||||||
return <Wrapper rows={[row]} />;
|
return <Wrapper rows={[row]} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConversationMissingMessage.story = {
|
|
||||||
name: 'Conversation: Missing Message',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConversationMissingText = (): JSX.Element =>
|
export const ConversationMissingText = (): JSX.Element =>
|
||||||
renderConversation({
|
renderConversation({
|
||||||
lastMessage: {
|
lastMessage: {
|
||||||
|
@ -602,19 +487,11 @@ export const ConversationMissingText = (): JSX.Element =>
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
ConversationMissingText.story = {
|
|
||||||
name: 'Conversation: Missing Text',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConversationMutedConversation = (): JSX.Element =>
|
export const ConversationMutedConversation = (): JSX.Element =>
|
||||||
renderConversation({
|
renderConversation({
|
||||||
muteExpiresAt: Date.now() + 1000 * 60 * 60,
|
muteExpiresAt: Date.now() + 1000 * 60 * 60,
|
||||||
});
|
});
|
||||||
|
|
||||||
ConversationMutedConversation.story = {
|
|
||||||
name: 'Conversation: Muted Conversation',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConversationAtMention = (): JSX.Element =>
|
export const ConversationAtMention = (): JSX.Element =>
|
||||||
renderConversation({
|
renderConversation({
|
||||||
title: 'The Rebellion',
|
title: 'The Rebellion',
|
||||||
|
@ -626,10 +503,6 @@ export const ConversationAtMention = (): JSX.Element =>
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
ConversationAtMention.story = {
|
|
||||||
name: 'Conversation: At Mention',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Headers(): JSX.Element {
|
export function Headers(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
|
@ -700,10 +573,6 @@ export function FindByPhoneNumber(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
FindByPhoneNumber.story = {
|
|
||||||
name: 'Find by phone number',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function FindByUsername(): JSX.Element {
|
export function FindByUsername(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
|
@ -728,10 +597,6 @@ export function FindByUsername(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
FindByUsername.story = {
|
|
||||||
name: 'Find by username',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function SearchResultsLoadingSkeleton(): JSX.Element {
|
export function SearchResultsLoadingSkeleton(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
|
@ -746,10 +611,6 @@ export function SearchResultsLoadingSkeleton(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchResultsLoadingSkeleton.story = {
|
|
||||||
name: 'Search results loading skeleton',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function KitchenSink(): JSX.Element {
|
export function KitchenSink(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
|
@ -821,7 +682,3 @@ export function KitchenSink(): JSX.Element {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
KitchenSink.story = {
|
|
||||||
name: 'Kitchen sink',
|
|
||||||
};
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
|
import type { PropsType } from './CrashReportDialog';
|
||||||
import { CrashReportDialog } from './CrashReportDialog';
|
import { CrashReportDialog } from './CrashReportDialog';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import { sleep } from '../util/sleep';
|
import { sleep } from '../util/sleep';
|
||||||
|
@ -11,11 +13,11 @@ import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CrashReportDialog',
|
title: 'Components/CrashReportDialog',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export const _CrashReportDialog = (): JSX.Element => {
|
export function Basic(): JSX.Element {
|
||||||
const [isPending, setIsPending] = useState(false);
|
const [isPending, setIsPending] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -31,8 +33,4 @@ export const _CrashReportDialog = (): JSX.Element => {
|
||||||
eraseCrashReports={action('eraseCrashReports')}
|
eraseCrashReports={action('eraseCrashReports')}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
_CrashReportDialog.story = {
|
|
||||||
name: 'CrashReportDialog',
|
|
||||||
};
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ type PropsActionsType = {
|
||||||
eraseCrashReports: () => void;
|
eraseCrashReports: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
type PropsType = {
|
export type PropsType = {
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
isPending: boolean;
|
isPending: boolean;
|
||||||
} & PropsActionsType;
|
} & PropsActionsType;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
import type { PropsType } from './CustomColorEditor';
|
import type { PropsType } from './CustomColorEditor';
|
||||||
import { CustomColorEditor } from './CustomColorEditor';
|
import { CustomColorEditor } from './CustomColorEditor';
|
||||||
|
@ -12,7 +13,7 @@ import { setupI18n } from '../util/setupI18n';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CustomColorEditor',
|
title: 'Components/CustomColorEditor',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
|
|
|
@ -5,16 +5,18 @@ import type { ComponentProps } from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
|
import type { PropsType } from './CustomizingPreferredReactionsModal';
|
||||||
import { CustomizingPreferredReactionsModal } from './CustomizingPreferredReactionsModal';
|
import { CustomizingPreferredReactionsModal } from './CustomizingPreferredReactionsModal';
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/CustomizingPreferredReactionsModal',
|
title: 'Components/CustomizingPreferredReactionsModal',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
const defaultProps: ComponentProps<typeof CustomizingPreferredReactionsModal> =
|
const defaultProps: ComponentProps<typeof CustomizingPreferredReactionsModal> =
|
||||||
{
|
{
|
||||||
|
@ -50,10 +52,6 @@ export function DraftEmojiSelected(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
DraftEmojiSelected.story = {
|
|
||||||
name: 'Draft emoji selected',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Saving(): JSX.Element {
|
export function Saving(): JSX.Element {
|
||||||
return <CustomizingPreferredReactionsModal {...defaultProps} isSaving />;
|
return <CustomizingPreferredReactionsModal {...defaultProps} isSaving />;
|
||||||
}
|
}
|
||||||
|
@ -61,7 +59,3 @@ export function Saving(): JSX.Element {
|
||||||
export function HadError(): JSX.Element {
|
export function HadError(): JSX.Element {
|
||||||
return <CustomizingPreferredReactionsModal {...defaultProps} hadSaveError />;
|
return <CustomizingPreferredReactionsModal {...defaultProps} hadSaveError />;
|
||||||
}
|
}
|
||||||
|
|
||||||
HadError.story = {
|
|
||||||
name: 'Had error',
|
|
||||||
};
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ import { convertShortName } from './emoji/lib';
|
||||||
import { offsetDistanceModifier } from '../util/popperUtil';
|
import { offsetDistanceModifier } from '../util/popperUtil';
|
||||||
import { handleOutsideClick } from '../util/handleOutsideClick';
|
import { handleOutsideClick } from '../util/handleOutsideClick';
|
||||||
|
|
||||||
type PropsType = {
|
export type PropsType = {
|
||||||
draftPreferredReactions: ReadonlyArray<string>;
|
draftPreferredReactions: ReadonlyArray<string>;
|
||||||
hadSaveError: boolean;
|
hadSaveError: boolean;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
import type { PropsType } from './DebugLogWindow';
|
import type { PropsType } from './DebugLogWindow';
|
||||||
import { DebugLogWindow } from './DebugLogWindow';
|
import { DebugLogWindow } from './DebugLogWindow';
|
||||||
|
@ -31,12 +32,8 @@ const createProps = (): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/DebugLogWindow',
|
title: 'Components/DebugLogWindow',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export const _DebugLogWindow = (): JSX.Element => (
|
export function Basic(): JSX.Element {
|
||||||
<DebugLogWindow {...createProps()} />
|
return <DebugLogWindow {...createProps()} />;
|
||||||
);
|
}
|
||||||
|
|
||||||
_DebugLogWindow.story = {
|
|
||||||
name: 'DebugLogWindow',
|
|
||||||
};
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { select } from '@storybook/addon-knobs';
|
import type { Meta } from '@storybook/react';
|
||||||
|
import type { PropsType } from './DialogExpiredBuild';
|
||||||
import { DialogExpiredBuild } from './DialogExpiredBuild';
|
import { DialogExpiredBuild } from './DialogExpiredBuild';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
@ -14,14 +14,12 @@ const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/DialogExpiredBuild',
|
title: 'Components/DialogExpiredBuild',
|
||||||
};
|
argTypes: {},
|
||||||
|
args: {},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export const _DialogExpiredBuild = (): JSX.Element => {
|
export function Basic(): JSX.Element {
|
||||||
const containerWidthBreakpoint = select(
|
const containerWidthBreakpoint = WidthBreakpoint.Wide;
|
||||||
'containerWidthBreakpoint',
|
|
||||||
WidthBreakpoint,
|
|
||||||
WidthBreakpoint.Wide
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={containerWidthBreakpoint}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={containerWidthBreakpoint}>
|
||||||
|
@ -31,8 +29,4 @@ export const _DialogExpiredBuild = (): JSX.Element => {
|
||||||
/>
|
/>
|
||||||
</FakeLeftPaneContainer>
|
</FakeLeftPaneContainer>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
_DialogExpiredBuild.story = {
|
|
||||||
name: 'DialogExpiredBuild',
|
|
||||||
};
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import type { PropsType } from './DialogNetworkStatus';
|
import type { PropsType } from './DialogNetworkStatus';
|
||||||
import { DialogNetworkStatus } from './DialogNetworkStatus';
|
import { DialogNetworkStatus } from './DialogNetworkStatus';
|
||||||
import { SocketStatus } from '../types/SocketStatus';
|
import { SocketStatus } from '../types/SocketStatus';
|
||||||
|
@ -27,7 +28,7 @@ const defaultProps = {
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/DialogNetworkStatus',
|
title: 'Components/DialogNetworkStatus',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function KnobsPlayground(args: PropsType): JSX.Element {
|
export function KnobsPlayground(args: PropsType): JSX.Element {
|
||||||
/*
|
/*
|
||||||
|
@ -68,10 +69,6 @@ export function ConnectingWide(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectingWide.story = {
|
|
||||||
name: 'Connecting Wide',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ClosingWide(): JSX.Element {
|
export function ClosingWide(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||||
|
@ -84,10 +81,6 @@ export function ClosingWide(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClosingWide.story = {
|
|
||||||
name: 'Closing Wide',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ClosedWide(): JSX.Element {
|
export function ClosedWide(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||||
|
@ -100,10 +93,6 @@ export function ClosedWide(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClosedWide.story = {
|
|
||||||
name: 'Closed Wide',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function OfflineWide(): JSX.Element {
|
export function OfflineWide(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||||
|
@ -116,10 +105,6 @@ export function OfflineWide(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
OfflineWide.story = {
|
|
||||||
name: 'Offline Wide',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ConnectingNarrow(): JSX.Element {
|
export function ConnectingNarrow(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||||
|
@ -132,10 +117,6 @@ export function ConnectingNarrow(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectingNarrow.story = {
|
|
||||||
name: 'Connecting Narrow',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ClosingNarrow(): JSX.Element {
|
export function ClosingNarrow(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||||
|
@ -148,10 +129,6 @@ export function ClosingNarrow(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClosingNarrow.story = {
|
|
||||||
name: 'Closing Narrow',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ClosedNarrow(): JSX.Element {
|
export function ClosedNarrow(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||||
|
@ -164,10 +141,6 @@ export function ClosedNarrow(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClosedNarrow.story = {
|
|
||||||
name: 'Closed Narrow',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function OfflineNarrow(): JSX.Element {
|
export function OfflineNarrow(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||||
|
@ -179,7 +152,3 @@ export function OfflineNarrow(): JSX.Element {
|
||||||
</FakeLeftPaneContainer>
|
</FakeLeftPaneContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
OfflineNarrow.story = {
|
|
||||||
name: 'Offline Narrow',
|
|
||||||
};
|
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
|
import type { PropsType } from './DialogRelink';
|
||||||
import { DialogRelink } from './DialogRelink';
|
import { DialogRelink } from './DialogRelink';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
@ -35,7 +36,7 @@ const permutations = [
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/DialogRelink',
|
title: 'Components/DialogRelink',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Iterations(): JSX.Element {
|
export function Iterations(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { select } from '@storybook/addon-knobs';
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
|
import type { PropsType } from './DialogUpdate';
|
||||||
import { DialogUpdate } from './DialogUpdate';
|
import { DialogUpdate } from './DialogUpdate';
|
||||||
import { DialogType } from '../types/Dialogs';
|
import { DialogType } from '../types/Dialogs';
|
||||||
import { WidthBreakpoint } from './_util';
|
import { WidthBreakpoint } from './_util';
|
||||||
|
@ -29,15 +30,13 @@ const defaultProps = {
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/DialogUpdate',
|
title: 'Components/DialogUpdate',
|
||||||
};
|
argTypes: {},
|
||||||
|
args: {},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function KnobsPlayground(): JSX.Element {
|
export function KnobsPlayground(): JSX.Element {
|
||||||
const containerWidthBreakpoint = select(
|
const containerWidthBreakpoint = WidthBreakpoint.Wide;
|
||||||
'containerWidthBreakpoint',
|
const dialogType = DialogType.AutoUpdate;
|
||||||
WidthBreakpoint,
|
|
||||||
WidthBreakpoint.Wide
|
|
||||||
);
|
|
||||||
const dialogType = select('dialogType', DialogType, DialogType.AutoUpdate);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={containerWidthBreakpoint}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={containerWidthBreakpoint}>
|
||||||
|
@ -64,10 +63,6 @@ export function UpdateWide(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateWide.story = {
|
|
||||||
name: 'Update (Wide)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function DownloadedWide(): JSX.Element {
|
export function DownloadedWide(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||||
|
@ -81,10 +76,6 @@ export function DownloadedWide(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadedWide.story = {
|
|
||||||
name: 'Downloaded (Wide)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function DownloadReadyWide(): JSX.Element {
|
export function DownloadReadyWide(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||||
|
@ -99,10 +90,6 @@ export function DownloadReadyWide(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadReadyWide.story = {
|
|
||||||
name: 'DownloadReady (Wide)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function FullDownloadReadyWide(): JSX.Element {
|
export function FullDownloadReadyWide(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||||
|
@ -117,10 +104,6 @@ export function FullDownloadReadyWide(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
FullDownloadReadyWide.story = {
|
|
||||||
name: 'FullDownloadReady (Wide)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function DownloadingWide(): JSX.Element {
|
export function DownloadingWide(): JSX.Element {
|
||||||
const [downloadedSize, setDownloadedSize] = React.useState(0);
|
const [downloadedSize, setDownloadedSize] = React.useState(0);
|
||||||
|
|
||||||
|
@ -153,10 +136,6 @@ export function DownloadingWide(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadingWide.story = {
|
|
||||||
name: 'Downloading (Wide)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function CannotUpdateWide(): JSX.Element {
|
export function CannotUpdateWide(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||||
|
@ -170,10 +149,6 @@ export function CannotUpdateWide(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
CannotUpdateWide.story = {
|
|
||||||
name: 'Cannot_Update (Wide)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function CannotUpdateBetaWide(): JSX.Element {
|
export function CannotUpdateBetaWide(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||||
|
@ -187,10 +162,6 @@ export function CannotUpdateBetaWide(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
CannotUpdateBetaWide.story = {
|
|
||||||
name: 'Cannot_Update_Beta (Wide)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function CannotUpdateRequireManualWide(): JSX.Element {
|
export function CannotUpdateRequireManualWide(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||||
|
@ -204,10 +175,6 @@ export function CannotUpdateRequireManualWide(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
CannotUpdateRequireManualWide.story = {
|
|
||||||
name: 'Cannot_Update_Require_Manual (Wide)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function CannotUpdateRequireManualBetaWide(): JSX.Element {
|
export function CannotUpdateRequireManualBetaWide(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||||
|
@ -221,10 +188,6 @@ export function CannotUpdateRequireManualBetaWide(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
CannotUpdateRequireManualBetaWide.story = {
|
|
||||||
name: 'Cannot_Update_Require_Manual_Beta (Wide)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function MacOSReadOnlyWide(): JSX.Element {
|
export function MacOSReadOnlyWide(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||||
|
@ -238,10 +201,6 @@ export function MacOSReadOnlyWide(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacOSReadOnlyWide.story = {
|
|
||||||
name: 'MacOS_Read_Only (Wide)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function UnsupportedOSWide(): JSX.Element {
|
export function UnsupportedOSWide(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||||
|
@ -255,10 +214,6 @@ export function UnsupportedOSWide(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnsupportedOSWide.story = {
|
|
||||||
name: 'UnsupportedOS (Wide)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function UpdateNarrow(): JSX.Element {
|
export function UpdateNarrow(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||||
|
@ -272,10 +227,6 @@ export function UpdateNarrow(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateNarrow.story = {
|
|
||||||
name: 'Update (Narrow)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function DownloadedNarrow(): JSX.Element {
|
export function DownloadedNarrow(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||||
|
@ -289,10 +240,6 @@ export function DownloadedNarrow(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadedNarrow.story = {
|
|
||||||
name: 'Downloaded (Narrow)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function DownloadReadyNarrow(): JSX.Element {
|
export function DownloadReadyNarrow(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||||
|
@ -307,10 +254,6 @@ export function DownloadReadyNarrow(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadReadyNarrow.story = {
|
|
||||||
name: 'DownloadReady (Narrow)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function FullDownloadReadyNarrow(): JSX.Element {
|
export function FullDownloadReadyNarrow(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||||
|
@ -325,10 +268,6 @@ export function FullDownloadReadyNarrow(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
FullDownloadReadyNarrow.story = {
|
|
||||||
name: 'FullDownloadReady (Narrow)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function DownloadingNarrow(): JSX.Element {
|
export function DownloadingNarrow(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||||
|
@ -342,10 +281,6 @@ export function DownloadingNarrow(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadingNarrow.story = {
|
|
||||||
name: 'Downloading (Narrow)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function CannotUpdateNarrow(): JSX.Element {
|
export function CannotUpdateNarrow(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||||
|
@ -359,10 +294,6 @@ export function CannotUpdateNarrow(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
CannotUpdateNarrow.story = {
|
|
||||||
name: 'Cannot Update (Narrow)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function CannotUpdateBetaNarrow(): JSX.Element {
|
export function CannotUpdateBetaNarrow(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||||
|
@ -376,10 +307,6 @@ export function CannotUpdateBetaNarrow(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
CannotUpdateBetaNarrow.story = {
|
|
||||||
name: 'Cannot Update Beta (Narrow)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function CannotUpdateRequireManualNarrow(): JSX.Element {
|
export function CannotUpdateRequireManualNarrow(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||||
|
@ -393,10 +320,6 @@ export function CannotUpdateRequireManualNarrow(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
CannotUpdateRequireManualNarrow.story = {
|
|
||||||
name: 'Cannot_Update_Require_Manual (Narrow)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function CannotUpdateRequireManualBetaNarrow(): JSX.Element {
|
export function CannotUpdateRequireManualBetaNarrow(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||||
|
@ -410,10 +333,6 @@ export function CannotUpdateRequireManualBetaNarrow(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
CannotUpdateRequireManualBetaNarrow.story = {
|
|
||||||
name: 'Cannot_Update_Require_Manual_Beta (Narrow)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function MacOSReadOnlyNarrow(): JSX.Element {
|
export function MacOSReadOnlyNarrow(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||||
|
@ -427,10 +346,6 @@ export function MacOSReadOnlyNarrow(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacOSReadOnlyNarrow.story = {
|
|
||||||
name: 'MacOS_Read_Only (Narrow)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function UnsupportedOSNarrow(): JSX.Element {
|
export function UnsupportedOSNarrow(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||||
|
@ -443,7 +358,3 @@ export function UnsupportedOSNarrow(): JSX.Element {
|
||||||
</FakeLeftPaneContainer>
|
</FakeLeftPaneContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnsupportedOSNarrow.story = {
|
|
||||||
name: 'UnsupportedOS (Narrow)',
|
|
||||||
};
|
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
|
import type { PropsType } from './DisappearingTimeDialog';
|
||||||
import { DisappearingTimeDialog } from './DisappearingTimeDialog';
|
import { DisappearingTimeDialog } from './DisappearingTimeDialog';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
@ -12,7 +13,7 @@ import { EXPIRE_TIMERS } from '../test-both/util/expireTimers';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/DisappearingTimeDialog',
|
title: 'Components/DisappearingTimeDialog',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
|
import type { Props } from './DisappearingTimerSelect';
|
||||||
import { DisappearingTimerSelect } from './DisappearingTimerSelect';
|
import { DisappearingTimerSelect } from './DisappearingTimerSelect';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import { DurationInSeconds } from '../util/durations';
|
import { DurationInSeconds } from '../util/durations';
|
||||||
|
@ -10,15 +11,15 @@ import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/DisappearingTimerSelect',
|
title: 'Components/DisappearingTimerSelect',
|
||||||
};
|
} satisfies Meta<Props>;
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
type Props = {
|
type Args = {
|
||||||
initialValue: number;
|
initialValue: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
function TimerSelectWrap({ initialValue }: Props): JSX.Element {
|
function TimerSelectWrap({ initialValue }: Args): JSX.Element {
|
||||||
const [value, setValue] = useState(initialValue);
|
const [value, setValue] = useState(initialValue);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -34,14 +35,6 @@ export function InitialValue1Day(): JSX.Element {
|
||||||
return <TimerSelectWrap initialValue={24 * 3600} />;
|
return <TimerSelectWrap initialValue={24 * 3600} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
InitialValue1Day.story = {
|
|
||||||
name: 'Initial value: 1 day',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function InitialValue3DaysCustomTime(): JSX.Element {
|
export function InitialValue3DaysCustomTime(): JSX.Element {
|
||||||
return <TimerSelectWrap initialValue={3 * 24 * 3600} />;
|
return <TimerSelectWrap initialValue={3 * 24 * 3600} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
InitialValue3DaysCustomTime.story = {
|
|
||||||
name: 'Initial value 3 days (Custom time)',
|
|
||||||
};
|
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { Meta, Story } from '@storybook/react';
|
import type { Meta, StoryFn } from '@storybook/react';
|
||||||
|
|
||||||
|
import { action } from '@storybook/addon-actions';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import type { UsernameReservationType } from '../types/Username';
|
import type { UsernameReservationType } from '../types/Username';
|
||||||
|
@ -29,11 +30,9 @@ export default {
|
||||||
argTypes: {
|
argTypes: {
|
||||||
currentUsername: {
|
currentUsername: {
|
||||||
type: { name: 'string', required: false },
|
type: { name: 'string', required: false },
|
||||||
defaultValue: undefined,
|
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
control: { type: 'radio' },
|
control: { type: 'radio' },
|
||||||
defaultValue: State.Open,
|
|
||||||
options: {
|
options: {
|
||||||
Open: State.Open,
|
Open: State.Open,
|
||||||
Closed: State.Closed,
|
Closed: State.Closed,
|
||||||
|
@ -43,7 +42,6 @@ export default {
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
control: { type: 'radio' },
|
control: { type: 'radio' },
|
||||||
defaultValue: undefined,
|
|
||||||
options: {
|
options: {
|
||||||
None: undefined,
|
None: undefined,
|
||||||
NotEnoughCharacters: UsernameReservationError.NotEnoughCharacters,
|
NotEnoughCharacters: UsernameReservationError.NotEnoughCharacters,
|
||||||
|
@ -54,26 +52,24 @@ export default {
|
||||||
General: UsernameReservationError.General,
|
General: UsernameReservationError.General,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
maxUsername: {
|
reservation: {
|
||||||
defaultValue: 20,
|
|
||||||
},
|
|
||||||
minUsername: {
|
|
||||||
defaultValue: 3,
|
|
||||||
},
|
|
||||||
discriminator: {
|
|
||||||
type: { name: 'string', required: false },
|
type: { name: 'string', required: false },
|
||||||
defaultValue: undefined,
|
|
||||||
},
|
},
|
||||||
i18n: {
|
|
||||||
defaultValue: i18n,
|
|
||||||
},
|
|
||||||
onClose: { action: true },
|
|
||||||
onError: { action: true },
|
|
||||||
setUsernameReservationError: { action: true },
|
|
||||||
reserveUsername: { action: true },
|
|
||||||
confirmUsername: { action: true },
|
|
||||||
},
|
},
|
||||||
} as Meta;
|
args: {
|
||||||
|
currentUsername: undefined,
|
||||||
|
state: State.Open,
|
||||||
|
error: undefined,
|
||||||
|
maxNickname: 20,
|
||||||
|
minNickname: 3,
|
||||||
|
reservation: undefined,
|
||||||
|
i18n,
|
||||||
|
onClose: action('onClose'),
|
||||||
|
setUsernameReservationError: action('setUsernameReservationError'),
|
||||||
|
reserveUsername: action('reserveUsername'),
|
||||||
|
confirmUsername: action('confirmUsername'),
|
||||||
|
},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
type ArgsType = PropsType & {
|
type ArgsType = PropsType & {
|
||||||
discriminator?: string;
|
discriminator?: string;
|
||||||
|
@ -81,7 +77,7 @@ type ArgsType = PropsType & {
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line react/function-component-definition
|
// eslint-disable-next-line react/function-component-definition
|
||||||
const Template: Story<ArgsType> = args => {
|
const Template: StoryFn<ArgsType> = args => {
|
||||||
let { reservation } = args;
|
let { reservation } = args;
|
||||||
if (!reservation && args.discriminator) {
|
if (!reservation && args.discriminator) {
|
||||||
reservation = {
|
reservation = {
|
||||||
|
@ -95,27 +91,16 @@ const Template: Story<ArgsType> = args => {
|
||||||
|
|
||||||
export const WithoutUsername = Template.bind({});
|
export const WithoutUsername = Template.bind({});
|
||||||
WithoutUsername.args = {};
|
WithoutUsername.args = {};
|
||||||
WithoutUsername.story = {
|
|
||||||
name: 'without current username',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const WithUsername = Template.bind({});
|
export const WithUsername = Template.bind({});
|
||||||
WithUsername.args = {};
|
WithUsername.args = {
|
||||||
WithUsername.story = {
|
currentUsername: 'signaluser.12',
|
||||||
name: 'with current username',
|
|
||||||
args: {
|
|
||||||
currentUsername: 'signaluser.12',
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const WithReservation = Template.bind({});
|
export const WithReservation = Template.bind({});
|
||||||
WithReservation.args = {};
|
WithReservation.args = {
|
||||||
WithReservation.story = {
|
currentUsername: 'reserved',
|
||||||
name: 'with reservation',
|
reservation: DEFAULT_RESERVATION,
|
||||||
args: {
|
|
||||||
currentUsername: 'reserved',
|
|
||||||
reservation: DEFAULT_RESERVATION,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const UsernameEditingConfirming = Template.bind({});
|
export const UsernameEditingConfirming = Template.bind({});
|
||||||
|
@ -123,9 +108,6 @@ UsernameEditingConfirming.args = {
|
||||||
state: State.Confirming,
|
state: State.Confirming,
|
||||||
currentUsername: 'signaluser.12',
|
currentUsername: 'signaluser.12',
|
||||||
};
|
};
|
||||||
UsernameEditingConfirming.story = {
|
|
||||||
name: 'Username editing, Confirming',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const UsernameEditingUsernameTaken = Template.bind({});
|
export const UsernameEditingUsernameTaken = Template.bind({});
|
||||||
UsernameEditingUsernameTaken.args = {
|
UsernameEditingUsernameTaken.args = {
|
||||||
|
@ -133,9 +115,6 @@ UsernameEditingUsernameTaken.args = {
|
||||||
error: UsernameReservationError.UsernameNotAvailable,
|
error: UsernameReservationError.UsernameNotAvailable,
|
||||||
currentUsername: 'signaluser.12',
|
currentUsername: 'signaluser.12',
|
||||||
};
|
};
|
||||||
UsernameEditingUsernameTaken.story = {
|
|
||||||
name: 'Username editing, username taken',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const UsernameEditingUsernameWrongCharacters = Template.bind({});
|
export const UsernameEditingUsernameWrongCharacters = Template.bind({});
|
||||||
UsernameEditingUsernameWrongCharacters.args = {
|
UsernameEditingUsernameWrongCharacters.args = {
|
||||||
|
@ -143,9 +122,6 @@ UsernameEditingUsernameWrongCharacters.args = {
|
||||||
error: UsernameReservationError.CheckCharacters,
|
error: UsernameReservationError.CheckCharacters,
|
||||||
currentUsername: 'signaluser.12',
|
currentUsername: 'signaluser.12',
|
||||||
};
|
};
|
||||||
UsernameEditingUsernameWrongCharacters.story = {
|
|
||||||
name: 'Username editing, Wrong Characters',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const UsernameEditingUsernameTooShort = Template.bind({});
|
export const UsernameEditingUsernameTooShort = Template.bind({});
|
||||||
UsernameEditingUsernameTooShort.args = {
|
UsernameEditingUsernameTooShort.args = {
|
||||||
|
@ -153,9 +129,6 @@ UsernameEditingUsernameTooShort.args = {
|
||||||
error: UsernameReservationError.NotEnoughCharacters,
|
error: UsernameReservationError.NotEnoughCharacters,
|
||||||
currentUsername: 'sig',
|
currentUsername: 'sig',
|
||||||
};
|
};
|
||||||
UsernameEditingUsernameTooShort.story = {
|
|
||||||
name: 'Username editing, username too short',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const UsernameEditingGeneralError = Template.bind({});
|
export const UsernameEditingGeneralError = Template.bind({});
|
||||||
UsernameEditingGeneralError.args = {
|
UsernameEditingGeneralError.args = {
|
||||||
|
@ -163,6 +136,3 @@ UsernameEditingGeneralError.args = {
|
||||||
error: UsernameReservationError.General,
|
error: UsernameReservationError.General,
|
||||||
currentUsername: 'signaluser.12',
|
currentUsername: 'signaluser.12',
|
||||||
};
|
};
|
||||||
UsernameEditingGeneralError.story = {
|
|
||||||
name: 'Username editing, general error',
|
|
||||||
};
|
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { text } from '@storybook/addon-knobs';
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import type { PropsType } from './ErrorModal';
|
import type { PropsType } from './ErrorModal';
|
||||||
import { ErrorModal } from './ErrorModal';
|
import { ErrorModal } from './ErrorModal';
|
||||||
|
|
||||||
|
@ -14,15 +14,17 @@ import enMessages from '../../_locales/en/messages.json';
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
title: text('title', overrideProps.title || ''),
|
title: overrideProps.title ?? '',
|
||||||
description: text('description', overrideProps.description || ''),
|
description: overrideProps.description ?? '',
|
||||||
i18n,
|
i18n,
|
||||||
onClose: action('onClick'),
|
onClose: action('onClick'),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/ErrorModal',
|
title: 'Components/ErrorModal',
|
||||||
};
|
argTypes: {},
|
||||||
|
args: {},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Normal(): JSX.Element {
|
export function Normal(): JSX.Element {
|
||||||
return <ErrorModal {...createProps()} />;
|
return <ErrorModal {...createProps()} />;
|
||||||
|
|
|
@ -2,10 +2,8 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import { text } from '@storybook/addon-knobs';
|
import type { Meta } from '@storybook/react';
|
||||||
|
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
import type { AttachmentType } from '../types/Attachment';
|
import type { AttachmentType } from '../types/Attachment';
|
||||||
import type { PropsType } from './ForwardMessagesModal';
|
import type { PropsType } from './ForwardMessagesModal';
|
||||||
|
@ -15,25 +13,25 @@ import { getDefaultConversation } from '../test-both/helpers/getDefaultConversat
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import { StorybookThemeContext } from '../../.storybook/StorybookThemeContext';
|
import { StorybookThemeContext } from '../../.storybook/StorybookThemeContext';
|
||||||
import { CompositionTextArea } from './CompositionTextArea';
|
import { CompositionTextArea } from './CompositionTextArea';
|
||||||
import type { MessageForwardDraft } from '../util/maybeForwardMessages';
|
import type { MessageForwardDraft } from '../types/ForwardDraft';
|
||||||
|
|
||||||
const createAttachment = (
|
const createAttachment = (
|
||||||
props: Partial<AttachmentType> = {}
|
props: Partial<AttachmentType> = {}
|
||||||
): AttachmentType => ({
|
): AttachmentType => ({
|
||||||
pending: false,
|
pending: false,
|
||||||
path: 'fileName.jpg',
|
path: 'fileName.jpg',
|
||||||
contentType: stringToMIMEType(
|
contentType: stringToMIMEType(props.contentType ?? ''),
|
||||||
text('attachment contentType', props.contentType || '')
|
fileName: props.fileName ?? '',
|
||||||
),
|
|
||||||
fileName: text('attachment fileName', props.fileName || ''),
|
|
||||||
screenshotPath: props.pending === false ? props.screenshotPath : undefined,
|
screenshotPath: props.pending === false ? props.screenshotPath : undefined,
|
||||||
url: text('attachment url', props.pending === false ? props.url || '' : ''),
|
url: props.pending === false ? props.url ?? '' : '',
|
||||||
size: 3433,
|
size: 3433,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/ForwardMessageModal',
|
title: 'Components/ForwardMessageModal',
|
||||||
};
|
argTypes: {},
|
||||||
|
args: {},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
|
@ -82,7 +80,7 @@ function getMessageForwardDraft(
|
||||||
attachments: overrideProps.attachments,
|
attachments: overrideProps.attachments,
|
||||||
hasContact: Boolean(overrideProps.hasContact),
|
hasContact: Boolean(overrideProps.hasContact),
|
||||||
isSticker: Boolean(overrideProps.isSticker),
|
isSticker: Boolean(overrideProps.isSticker),
|
||||||
messageBody: text('messageBody', overrideProps.messageBody || ''),
|
messageBody: overrideProps.messageBody ?? '',
|
||||||
originalMessageId: '123',
|
originalMessageId: '123',
|
||||||
previews: overrideProps.previews ?? [],
|
previews: overrideProps.previews ?? [],
|
||||||
};
|
};
|
||||||
|
@ -102,10 +100,6 @@ export function WithText(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
WithText.story = {
|
|
||||||
name: 'with text',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ASticker(): JSX.Element {
|
export function ASticker(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<ForwardMessagesModal
|
<ForwardMessagesModal
|
||||||
|
@ -116,10 +110,6 @@ export function ASticker(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASticker.story = {
|
|
||||||
name: 'a sticker',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function WithAContact(): JSX.Element {
|
export function WithAContact(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<ForwardMessagesModal
|
<ForwardMessagesModal
|
||||||
|
@ -130,10 +120,6 @@ export function WithAContact(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
WithAContact.story = {
|
|
||||||
name: 'with a contact',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function LinkPreview(): JSX.Element {
|
export function LinkPreview(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<ForwardMessagesModal
|
<ForwardMessagesModal
|
||||||
|
@ -162,10 +148,6 @@ export function LinkPreview(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkPreview.story = {
|
|
||||||
name: 'link preview',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function MediaAttachments(): JSX.Element {
|
export function MediaAttachments(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<ForwardMessagesModal
|
<ForwardMessagesModal
|
||||||
|
@ -196,10 +178,6 @@ export function MediaAttachments(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaAttachments.story = {
|
|
||||||
name: 'media attachments',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function AnnouncementOnlyGroupsNonAdmin(): JSX.Element {
|
export function AnnouncementOnlyGroupsNonAdmin(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<ForwardMessagesModal
|
<ForwardMessagesModal
|
||||||
|
@ -213,7 +191,3 @@ export function AnnouncementOnlyGroupsNonAdmin(): JSX.Element {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
AnnouncementOnlyGroupsNonAdmin.story = {
|
|
||||||
name: 'announcement only groups non-admin',
|
|
||||||
};
|
|
||||||
|
|
|
@ -27,11 +27,6 @@ import {
|
||||||
shouldNeverBeCalled,
|
shouldNeverBeCalled,
|
||||||
asyncShouldNeverBeCalled,
|
asyncShouldNeverBeCalled,
|
||||||
} from '../util/shouldNeverBeCalled';
|
} from '../util/shouldNeverBeCalled';
|
||||||
import type { MessageForwardDraft } from '../util/maybeForwardMessages';
|
|
||||||
import {
|
|
||||||
isDraftEditable,
|
|
||||||
isDraftForwardable,
|
|
||||||
} from '../util/maybeForwardMessages';
|
|
||||||
import type { LinkPreviewType } from '../types/message/LinkPreviews';
|
import type { LinkPreviewType } from '../types/message/LinkPreviews';
|
||||||
import { LinkPreviewSourceType } from '../types/LinkPreview';
|
import { LinkPreviewSourceType } from '../types/LinkPreview';
|
||||||
import { ToastType } from '../types/Toast';
|
import { ToastType } from '../types/Toast';
|
||||||
|
@ -41,6 +36,11 @@ import { BodyRange } from '../types/BodyRange';
|
||||||
import { UserText } from './UserText';
|
import { UserText } from './UserText';
|
||||||
import { Modal } from './Modal';
|
import { Modal } from './Modal';
|
||||||
import { SizeObserver } from '../hooks/useSizeObserver';
|
import { SizeObserver } from '../hooks/useSizeObserver';
|
||||||
|
import {
|
||||||
|
isDraftEditable,
|
||||||
|
isDraftForwardable,
|
||||||
|
type MessageForwardDraft,
|
||||||
|
} from '../types/ForwardDraft';
|
||||||
|
|
||||||
export type DataPropsType = {
|
export type DataPropsType = {
|
||||||
candidateConversations: ReadonlyArray<ConversationType>;
|
candidateConversations: ReadonlyArray<ConversationType>;
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { memoize, times } from 'lodash';
|
import { memoize, times } from 'lodash';
|
||||||
import { number } from '@storybook/addon-knobs';
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
|
import type { PropsType } from './GroupCallOverflowArea';
|
||||||
import { GroupCallOverflowArea } from './GroupCallOverflowArea';
|
import { GroupCallOverflowArea } from './GroupCallOverflowArea';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import { getDefaultConversationWithServiceId } from '../test-both/helpers/getDefaultConversation';
|
import { getDefaultConversationWithServiceId } from '../test-both/helpers/getDefaultConversation';
|
||||||
|
@ -34,7 +34,9 @@ const allRemoteParticipants = times(MAX_PARTICIPANTS).map(index => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/GroupCallOverflowArea',
|
title: 'Components/GroupCallOverflowArea',
|
||||||
};
|
argTypes: {},
|
||||||
|
args: {},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
getFrameBuffer: memoize(() => Buffer.alloc(FRAME_BUFFER_SIZE)),
|
getFrameBuffer: memoize(() => Buffer.alloc(FRAME_BUFFER_SIZE)),
|
||||||
|
@ -68,10 +70,6 @@ export function NoOverflowedParticipants(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
NoOverflowedParticipants.story = {
|
|
||||||
name: 'No overflowed participants',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function OneOverflowedParticipant(): JSX.Element {
|
export function OneOverflowedParticipant(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
|
@ -83,10 +81,6 @@ export function OneOverflowedParticipant(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
OneOverflowedParticipant.story = {
|
|
||||||
name: 'One overflowed participant',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ThreeOverflowedParticipants(): JSX.Element {
|
export function ThreeOverflowedParticipants(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
|
@ -98,10 +92,6 @@ export function ThreeOverflowedParticipants(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreeOverflowedParticipants.story = {
|
|
||||||
name: 'Three overflowed participants',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ManyOverflowedParticipants(): JSX.Element {
|
export function ManyOverflowedParticipants(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
|
@ -109,18 +99,9 @@ export function ManyOverflowedParticipants(): JSX.Element {
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
overflowedParticipants={allRemoteParticipants.slice(
|
overflowedParticipants={allRemoteParticipants.slice(
|
||||||
0,
|
0,
|
||||||
number('Participant count', MAX_PARTICIPANTS, {
|
MAX_PARTICIPANTS
|
||||||
range: true,
|
|
||||||
min: 0,
|
|
||||||
max: MAX_PARTICIPANTS,
|
|
||||||
step: 1,
|
|
||||||
})
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ManyOverflowedParticipants.story = {
|
|
||||||
name: 'Many overflowed participants',
|
|
||||||
};
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ const OVERFLOW_SCROLL_BUTTON_RATIO = 0.75;
|
||||||
// This should be an integer, as sub-pixel widths can cause performance issues.
|
// This should be an integer, as sub-pixel widths can cause performance issues.
|
||||||
export const OVERFLOW_PARTICIPANT_WIDTH = 140;
|
export const OVERFLOW_PARTICIPANT_WIDTH = 140;
|
||||||
|
|
||||||
type PropsType = {
|
export type PropsType = {
|
||||||
getFrameBuffer: () => Buffer;
|
getFrameBuffer: () => Buffer;
|
||||||
getGroupCallVideoFrameSource: (demuxId: number) => VideoFrameSource;
|
getGroupCallVideoFrameSource: (demuxId: number) => VideoFrameSource;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { memoize, noop } from 'lodash';
|
import { memoize } from 'lodash';
|
||||||
import { select } from '@storybook/addon-knobs';
|
import type { Meta } from '@storybook/react';
|
||||||
|
|
||||||
import type { PropsType } from './GroupCallRemoteParticipant';
|
import type { PropsType } from './GroupCallRemoteParticipant';
|
||||||
import { GroupCallRemoteParticipant } from './GroupCallRemoteParticipant';
|
import { GroupCallRemoteParticipant } from './GroupCallRemoteParticipant';
|
||||||
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
|
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
|
||||||
|
@ -46,8 +45,9 @@ const createProps = (
|
||||||
} = {}
|
} = {}
|
||||||
): PropsType => ({
|
): PropsType => ({
|
||||||
getFrameBuffer,
|
getFrameBuffer,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
getGroupCallVideoFrameSource: () => {
|
||||||
getGroupCallVideoFrameSource: noop as any,
|
return { receiveVideoFrame: () => undefined };
|
||||||
|
},
|
||||||
i18n,
|
i18n,
|
||||||
audioLevel: 0,
|
audioLevel: 0,
|
||||||
remoteParticipant: {
|
remoteParticipant: {
|
||||||
|
@ -72,7 +72,9 @@ const createProps = (
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/GroupCallRemoteParticipant',
|
title: 'Components/GroupCallRemoteParticipant',
|
||||||
};
|
argTypes: {},
|
||||||
|
args: {},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Default(): JSX.Element {
|
export function Default(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
@ -101,7 +103,7 @@ export function Speaking(): JSX.Element {
|
||||||
left: (120 + 10) * index,
|
left: (120 + 10) * index,
|
||||||
top: 0,
|
top: 0,
|
||||||
width: 120,
|
width: 120,
|
||||||
audioLevel: select('audioLevel', [0, 0.5, 1], 0.5),
|
audioLevel: 0.5,
|
||||||
remoteParticipantsCount,
|
remoteParticipantsCount,
|
||||||
},
|
},
|
||||||
{ hasRemoteAudio: true, presenting }
|
{ hasRemoteAudio: true, presenting }
|
||||||
|
@ -126,10 +128,6 @@ export function IsInPip(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
IsInPip.story = {
|
|
||||||
name: 'isInPip',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Blocked(): JSX.Element {
|
export function Blocked(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<GroupCallRemoteParticipant
|
<GroupCallRemoteParticipant
|
||||||
|
|
|
@ -2,17 +2,17 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
import type { PropsType } from './GroupDescriptionInput';
|
||||||
import { GroupDescriptionInput } from './GroupDescriptionInput';
|
import { GroupDescriptionInput } from './GroupDescriptionInput';
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/GroupDescriptionInput',
|
title: 'Components/GroupDescriptionInput',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
function Wrapper({
|
function Wrapper({
|
||||||
disabled,
|
disabled,
|
||||||
|
|
|
@ -6,7 +6,7 @@ import React, { forwardRef } from 'react';
|
||||||
import { Input } from './Input';
|
import { Input } from './Input';
|
||||||
import type { LocalizerType } from '../types/Util';
|
import type { LocalizerType } from '../types/Util';
|
||||||
|
|
||||||
type PropsType = {
|
export type PropsType = {
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
onChangeValue: (value: string) => void;
|
onChangeValue: (value: string) => void;
|
||||||
|
|
|
@ -2,17 +2,17 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
import type { PropsType } from './GroupTitleInput';
|
||||||
import { GroupTitleInput } from './GroupTitleInput';
|
import { GroupTitleInput } from './GroupTitleInput';
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/GroupTitleInput',
|
title: 'Components/GroupTitleInput',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
function Wrapper({
|
function Wrapper({
|
||||||
disabled,
|
disabled,
|
||||||
|
|
|
@ -6,7 +6,7 @@ import React, { forwardRef } from 'react';
|
||||||
import { Input } from './Input';
|
import { Input } from './Input';
|
||||||
import type { LocalizerType } from '../types/Util';
|
import type { LocalizerType } from '../types/Util';
|
||||||
|
|
||||||
type PropsType = {
|
export type PropsType = {
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
onChangeValue: (value: string) => void;
|
onChangeValue: (value: string) => void;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import * as React from 'react';
|
||||||
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import type { PropsType } from './GroupV1MigrationDialog';
|
import type { PropsType } from './GroupV1MigrationDialog';
|
||||||
import { GroupV1MigrationDialog } from './GroupV1MigrationDialog';
|
import { GroupV1MigrationDialog } from './GroupV1MigrationDialog';
|
||||||
import type { ConversationType } from '../state/ducks/conversations';
|
import type { ConversationType } from '../state/ducks/conversations';
|
||||||
|
@ -48,16 +49,12 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/GroupV1MigrationDialog',
|
title: 'Components/GroupV1MigrationDialog',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function NotYetMigratedBasic(): JSX.Element {
|
export function NotYetMigratedBasic(): JSX.Element {
|
||||||
return <GroupV1MigrationDialog {...createProps()} />;
|
return <GroupV1MigrationDialog {...createProps()} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
NotYetMigratedBasic.story = {
|
|
||||||
name: 'Not yet migrated, basic',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function MigratedBasic(): JSX.Element {
|
export function MigratedBasic(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<GroupV1MigrationDialog
|
<GroupV1MigrationDialog
|
||||||
|
@ -68,10 +65,6 @@ export function MigratedBasic(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
MigratedBasic.story = {
|
|
||||||
name: 'Migrated, basic',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function MigratedYouAreInvited(): JSX.Element {
|
export function MigratedYouAreInvited(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<GroupV1MigrationDialog
|
<GroupV1MigrationDialog
|
||||||
|
@ -83,10 +76,6 @@ export function MigratedYouAreInvited(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
MigratedYouAreInvited.story = {
|
|
||||||
name: 'Migrated, you are invited',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function NotYetMigratedMultipleDroppedAndInvitedMembers(): JSX.Element {
|
export function NotYetMigratedMultipleDroppedAndInvitedMembers(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<GroupV1MigrationDialog
|
<GroupV1MigrationDialog
|
||||||
|
@ -98,10 +87,6 @@ export function NotYetMigratedMultipleDroppedAndInvitedMembers(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
NotYetMigratedMultipleDroppedAndInvitedMembers.story = {
|
|
||||||
name: 'Not yet migrated, multiple dropped and invited members',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function NotYetMigratedNoMembers(): JSX.Element {
|
export function NotYetMigratedNoMembers(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<GroupV1MigrationDialog
|
<GroupV1MigrationDialog
|
||||||
|
@ -113,10 +98,6 @@ export function NotYetMigratedNoMembers(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
NotYetMigratedNoMembers.story = {
|
|
||||||
name: 'Not yet migrated, no members',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function NotYetMigratedJustDroppedMember(): JSX.Element {
|
export function NotYetMigratedJustDroppedMember(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<GroupV1MigrationDialog
|
<GroupV1MigrationDialog
|
||||||
|
@ -126,7 +107,3 @@ export function NotYetMigratedJustDroppedMember(): JSX.Element {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
NotYetMigratedJustDroppedMember.story = {
|
|
||||||
name: 'Not yet migrated, just dropped member',
|
|
||||||
};
|
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { boolean, number, text } from '@storybook/addon-knobs';
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import type { PropsType } from './GroupV2JoinDialog';
|
import type { PropsType } from './GroupV2JoinDialog';
|
||||||
import { GroupV2JoinDialog } from './GroupV2JoinDialog';
|
import { GroupV2JoinDialog } from './GroupV2JoinDialog';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
|
@ -13,13 +12,10 @@ import enMessages from '../../_locales/en/messages.json';
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
memberCount: number('memberCount', overrideProps.memberCount || 12),
|
memberCount: overrideProps.memberCount ?? 12,
|
||||||
avatar: overrideProps.avatar,
|
avatar: overrideProps.avatar,
|
||||||
title: text('title', overrideProps.title || 'Random Group!'),
|
title: overrideProps.title ?? 'Random Group!',
|
||||||
approvalRequired: boolean(
|
approvalRequired: overrideProps.approvalRequired ?? false,
|
||||||
'approvalRequired',
|
|
||||||
overrideProps.approvalRequired || false
|
|
||||||
),
|
|
||||||
groupDescription: overrideProps.groupDescription,
|
groupDescription: overrideProps.groupDescription,
|
||||||
join: action('join'),
|
join: action('join'),
|
||||||
onClose: action('onClose'),
|
onClose: action('onClose'),
|
||||||
|
@ -28,7 +24,9 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/GroupV2JoinDialog',
|
title: 'Components/GroupV2JoinDialog',
|
||||||
};
|
argTypes: {},
|
||||||
|
args: {},
|
||||||
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Basic(): JSX.Element {
|
export function Basic(): JSX.Element {
|
||||||
return <GroupV2JoinDialog {...createProps()} />;
|
return <GroupV2JoinDialog {...createProps()} />;
|
||||||
|
@ -45,10 +43,6 @@ export function ApprovalRequired(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ApprovalRequired.story = {
|
|
||||||
name: 'Approval required',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function WithAvatar(): JSX.Element {
|
export function WithAvatar(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<GroupV2JoinDialog
|
<GroupV2JoinDialog
|
||||||
|
@ -62,10 +56,6 @@ export function WithAvatar(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
WithAvatar.story = {
|
|
||||||
name: 'With avatar',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function WithOneMember(): JSX.Element {
|
export function WithOneMember(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<GroupV2JoinDialog
|
<GroupV2JoinDialog
|
||||||
|
@ -77,10 +67,6 @@ export function WithOneMember(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
WithOneMember.story = {
|
|
||||||
name: 'With one member',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function AvatarLoadingState(): JSX.Element {
|
export function AvatarLoadingState(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<GroupV2JoinDialog
|
<GroupV2JoinDialog
|
||||||
|
@ -94,10 +80,6 @@ export function AvatarLoadingState(): JSX.Element {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
AvatarLoadingState.story = {
|
|
||||||
name: 'Avatar loading state',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Full(): JSX.Element {
|
export function Full(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<GroupV2JoinDialog
|
<GroupV2JoinDialog
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { IdenticonSVGForContact, IdenticonSVGForGroup } from './IdenticonSVG';
|
import { IdenticonSVGForContact, IdenticonSVGForGroup } from './IdenticonSVG';
|
||||||
import { AvatarColorMap } from '../types/Colors';
|
import { AvatarColorMap } from '../types/Colors';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/IdenticonSVG',
|
title: 'Components/IdenticonSVG',
|
||||||
};
|
} satisfies Meta;
|
||||||
|
|
||||||
export function AllColorsForContact(): JSX.Element {
|
export function AllColorsForContact(): JSX.Element {
|
||||||
const stories: Array<JSX.Element> = [];
|
const stories: Array<JSX.Element> = [];
|
||||||
|
|
|
@ -2,16 +2,17 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import type { Meta } from '@storybook/react';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
import { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
import type { PropsType } from './InContactsIcon';
|
||||||
import { InContactsIcon } from './InContactsIcon';
|
import { InContactsIcon } from './InContactsIcon';
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/InContactsIcon',
|
title: 'Components/InContactsIcon',
|
||||||
};
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
export function Default(): JSX.Element {
|
export function Default(): JSX.Element {
|
||||||
return <InContactsIcon i18n={i18n} />;
|
return <InContactsIcon i18n={i18n} />;
|
||||||
|
|
|
@ -7,7 +7,7 @@ import classNames from 'classnames';
|
||||||
import { Tooltip } from './Tooltip';
|
import { Tooltip } from './Tooltip';
|
||||||
import type { LocalizerType } from '../types/Util';
|
import type { LocalizerType } from '../types/Util';
|
||||||
|
|
||||||
type PropsType = {
|
export type PropsType = {
|
||||||
className?: string;
|
className?: string;
|
||||||
tooltipContainerRef?: React.RefObject<HTMLElement>;
|
tooltipContainerRef?: React.RefObject<HTMLElement>;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React, { useState, useEffect, useMemo } from 'react';
|
import React, { useState, useEffect, useMemo } from 'react';
|
||||||
import type { Meta, Story } from '@storybook/react';
|
import type { Meta, StoryFn } from '@storybook/react';
|
||||||
import { noop } from 'lodash';
|
import { noop } from 'lodash';
|
||||||
|
|
||||||
import { Inbox } from './Inbox';
|
import { Inbox } from './Inbox';
|
||||||
|
@ -16,41 +16,15 @@ const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/Inbox',
|
title: 'Components/Inbox',
|
||||||
argTypes: {
|
args: {
|
||||||
i18n: {
|
i18n,
|
||||||
defaultValue: i18n,
|
hasInitialLoadCompleted: false,
|
||||||
},
|
isCustomizingPreferredReactions: false,
|
||||||
hasInitialLoadCompleted: {
|
|
||||||
defaultValue: false,
|
|
||||||
},
|
|
||||||
daysAgo: {
|
|
||||||
control: 'select',
|
|
||||||
defaultValue: undefined,
|
|
||||||
options: [undefined, 1, 2, 3, 7, 14, 21],
|
|
||||||
},
|
|
||||||
isCustomizingPreferredReactions: {
|
|
||||||
defaultValue: false,
|
|
||||||
},
|
|
||||||
onConversationClosed: {
|
|
||||||
action: true,
|
|
||||||
},
|
|
||||||
onConversationOpened: {
|
|
||||||
action: true,
|
|
||||||
},
|
|
||||||
scrollToMessage: {
|
|
||||||
action: true,
|
|
||||||
},
|
|
||||||
showConversation: {
|
|
||||||
action: true,
|
|
||||||
},
|
|
||||||
showWhatsNewModal: {
|
|
||||||
action: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
} as Meta;
|
} satisfies Meta<PropsType>;
|
||||||
|
|
||||||
// eslint-disable-next-line react/function-component-definition
|
// eslint-disable-next-line react/function-component-definition
|
||||||
const Template: Story<PropsType & { daysAgo?: number }> = ({
|
const Template: StoryFn<PropsType & { daysAgo?: number }> = ({
|
||||||
daysAgo,
|
daysAgo,
|
||||||
...args
|
...args
|
||||||
}) => {
|
}) => {
|
||||||
|
@ -90,6 +64,3 @@ const Template: Story<PropsType & { daysAgo?: number }> = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Default = Template.bind({});
|
export const Default = Template.bind({});
|
||||||
Default.story = {
|
|
||||||
name: 'Default',
|
|
||||||
};
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue