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
|
||||
test/test.js
|
||||
ts/protobuf/compiled.d.ts
|
||||
storybook-static/**
|
||||
|
||||
# Third-party files
|
||||
js/Mp3LameEncoder.min.js
|
||||
|
|
|
@ -300,6 +300,12 @@ module.exports = {
|
|||
'local-rules/type-alias-readonlydeep': 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['ts/**/*_test.{ts,tsx}'],
|
||||
rules: {
|
||||
'func-names': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
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
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import '../ts/window.d.ts';
|
||||
|
||||
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 messages from '../_locales/en/messages.json';
|
||||
import { ClassyProvider } from '../ts/components/PopperRootContext';
|
||||
import { StorybookThemeContext } from './StorybookThemeContext';
|
||||
import { ThemeType } from '../ts/types/Util';
|
||||
import { setupI18n } from '../ts/util/setupI18n';
|
||||
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 = {
|
||||
mode: {
|
||||
|
@ -38,8 +50,73 @@ export const globalTypes = {
|
|||
},
|
||||
};
|
||||
|
||||
window.i18n = setupI18n('en', messages);
|
||||
window.getHourCyclePreference = () => HourCyclePreference.UnknownPreference;
|
||||
const mockStore: Store<StateType> = createStore(
|
||||
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 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 = {
|
||||
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
|
||||
!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",
|
||||
"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",
|
||||
"dev": "run-p --print-label dev:*",
|
||||
"dev:transpile": "run-p \"check:types --watch\" dev:esbuild",
|
||||
"dev:esbuild": "node scripts/esbuild.js --watch",
|
||||
"dev:storybook": "cross-env SIGNAL_ENV=storybook start-storybook -p 6006 -s ./",
|
||||
"dev:sass": "yarn sass --watch",
|
||||
"dev": "yarn build-protobuf && cross-env SIGNAL_ENV=storybook storybook dev --port 6006",
|
||||
"build:storybook": "yarn build-protobuf && cross-env SIGNAL_ENV=storybook storybook build",
|
||||
"test:storybook": "yarn build:storybook && run-p --race test:storybook:*",
|
||||
"test:storybook:serve": "http-server storybook-static --port 6006 --silent",
|
||||
"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-linux": "yarn generate && yarn build:esbuild:prod && yarn build:release -- --publish=never",
|
||||
"build:acknowledgments": "node scripts/generate-acknowledgments.js",
|
||||
|
@ -184,33 +184,33 @@
|
|||
"zod": "3.21.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.14.3",
|
||||
"@babel/plugin-proposal-class-properties": "7.17.12",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "7.17.12",
|
||||
"@babel/plugin-proposal-optional-chaining": "7.17.12",
|
||||
"@babel/plugin-transform-runtime": "7.18.2",
|
||||
"@babel/plugin-transform-typescript": "7.18.4",
|
||||
"@babel/preset-react": "7.17.12",
|
||||
"@babel/preset-typescript": "7.17.12",
|
||||
"@babel/core": "7.23.0",
|
||||
"@babel/plugin-proposal-class-properties": "7.18.6",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6",
|
||||
"@babel/plugin-proposal-optional-chaining": "7.21.0",
|
||||
"@babel/plugin-transform-runtime": "7.22.15",
|
||||
"@babel/plugin-transform-typescript": "7.22.15",
|
||||
"@babel/preset-react": "7.22.15",
|
||||
"@babel/preset-typescript": "7.23.0",
|
||||
"@electron/fuses": "1.5.0",
|
||||
"@formatjs/intl": "2.6.7",
|
||||
"@mixer/parallel-prettier": "2.0.3",
|
||||
"@signalapp/mock-server": "4.1.2",
|
||||
"@storybook/addon-a11y": "6.5.6",
|
||||
"@storybook/addon-actions": "6.5.6",
|
||||
"@storybook/addon-controls": "6.5.6",
|
||||
"@storybook/addon-interactions": "6.5.9",
|
||||
"@storybook/addon-knobs": "6.4.0",
|
||||
"@storybook/addon-measure": "6.5.6",
|
||||
"@storybook/addon-toolbars": "6.5.6",
|
||||
"@storybook/addon-viewport": "6.5.6",
|
||||
"@storybook/addons": "6.5.6",
|
||||
"@storybook/builder-webpack5": "6.5.15",
|
||||
"@storybook/jest": "0.0.10",
|
||||
"@storybook/manager-webpack5": "6.5.15",
|
||||
"@storybook/react": "6.5.6",
|
||||
"@storybook/testing-library": "0.0.13",
|
||||
"@types/backbone": "1.4.5",
|
||||
"@storybook/addon-a11y": "7.4.5",
|
||||
"@storybook/addon-actions": "7.4.5",
|
||||
"@storybook/addon-controls": "7.4.5",
|
||||
"@storybook/addon-interactions": "7.4.5",
|
||||
"@storybook/addon-jest": "7.4.5",
|
||||
"@storybook/addon-measure": "7.4.5",
|
||||
"@storybook/addon-toolbars": "7.4.5",
|
||||
"@storybook/addon-viewport": "7.4.5",
|
||||
"@storybook/addons": "7.4.5",
|
||||
"@storybook/jest": "0.2.2",
|
||||
"@storybook/react": "7.4.5",
|
||||
"@storybook/react-webpack5": "7.4.5",
|
||||
"@storybook/test-runner": "0.13.0",
|
||||
"@storybook/testing-library": "0.2.2",
|
||||
"@types/backbone": "1.4.16",
|
||||
"@types/blueimp-load-image": "5.14.1",
|
||||
"@types/chai": "4.2.18",
|
||||
"@types/chai-as-promised": "7.1.4",
|
||||
|
@ -258,7 +258,7 @@
|
|||
"asar": "3.1.0",
|
||||
"axe-core": "4.1.4",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
"babel-loader": "8.0.6",
|
||||
"babel-loader": "9.1.3",
|
||||
"babel-plugin-lodash": "3.3.4",
|
||||
"casual": "1.6.2",
|
||||
"chai": "4.3.4",
|
||||
|
@ -285,19 +285,23 @@
|
|||
"eslint-plugin-react": "7.31.10",
|
||||
"execa": "5.1.1",
|
||||
"html-webpack-plugin": "5.3.1",
|
||||
"http-server": "14.1.1",
|
||||
"json-to-ast": "2.1.0",
|
||||
"mini-css-extract-plugin": "2.7.6",
|
||||
"mocha": "9.1.3",
|
||||
"node-gyp": "9.0.0",
|
||||
"npm-run-all": "4.1.5",
|
||||
"nyc": "11.4.1",
|
||||
"p-limit": "3.1.0",
|
||||
"patch-package": "6.4.7",
|
||||
"patch-package": "8.0.0",
|
||||
"playwright": "1.33.0",
|
||||
"prettier": "2.8.0",
|
||||
"protobufjs-cli": "1.1.1",
|
||||
"resolve-url-loader": "5.0.0",
|
||||
"sass": "1.49.7",
|
||||
"sass-loader": "10.2.0",
|
||||
"sinon": "11.1.1",
|
||||
"storybook": "7.4.5",
|
||||
"style-loader": "1.0.0",
|
||||
"stylelint": "15.4.0",
|
||||
"stylelint-config-css-modules": "4.2.0",
|
||||
|
@ -309,7 +313,8 @@
|
|||
"ts-node": "8.3.0",
|
||||
"typed-scss-modules": "4.1.1",
|
||||
"typescript": "5.1.3",
|
||||
"webpack": "5.76.0",
|
||||
"wait-on": "7.0.1",
|
||||
"webpack": "5.88.2",
|
||||
"webpack-cli": "4.9.2",
|
||||
"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
|
||||
index 272822a..87ebd1f 100755
|
||||
index b37b188..1908c0c 100755
|
||||
--- a/node_modules/@types/jest/index.d.ts
|
||||
+++ b/node_modules/@types/jest/index.d.ts
|
||||
@@ -30,18 +30,18 @@
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// Minimum TypeScript Version: 3.8
|
||||
// Minimum TypeScript Version: 4.3
|
||||
|
||||
-declare var beforeAll: jest.Lifecycle;
|
||||
-declare var beforeEach: jest.Lifecycle;
|
|
@ -13,8 +13,6 @@ import { getBytesSubarray } from './util/uuidToBytes';
|
|||
|
||||
export { HashType, CipherType };
|
||||
|
||||
export const UUID_BYTE_SIZE = 16;
|
||||
|
||||
const PROFILE_IV_LENGTH = 12; // bytes
|
||||
const PROFILE_KEY_LENGTH = 32; // bytes
|
||||
|
||||
|
|
|
@ -3288,13 +3288,14 @@ export async function startApp(): Promise<void> {
|
|||
'onDeliveryReceipt: missing valid sourceServiceId'
|
||||
);
|
||||
strictAssert(sourceDevice, 'onDeliveryReceipt: missing sourceDevice');
|
||||
strictAssert(sourceConversation, 'onDeliveryReceipt: missing conversation');
|
||||
|
||||
const attributes: MessageReceiptAttributesType = {
|
||||
envelopeId: ev.deliveryReceipt.envelopeId,
|
||||
removeFromMessageReceiverCache: ev.confirm,
|
||||
messageSentAt: timestamp,
|
||||
receiptTimestamp: envelopeTimestamp,
|
||||
sourceConversationId: sourceConversation?.id,
|
||||
sourceConversationId: sourceConversation.id,
|
||||
sourceServiceId,
|
||||
sourceDevice,
|
||||
type: MessageReceipts.MessageReceiptType.Delivery,
|
||||
|
|
|
@ -5,8 +5,10 @@ import React from 'react';
|
|||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
import type { PropsType } from './AddGroupMemberErrorDialog';
|
||||
import {
|
||||
AddGroupMemberErrorDialog,
|
||||
AddGroupMemberErrorDialogMode,
|
||||
|
@ -16,24 +18,22 @@ const i18n = setupI18n('en', enMessages);
|
|||
|
||||
export default {
|
||||
title: 'Components/AddGroupMemberErrorDialog',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
const defaultProps = {
|
||||
i18n,
|
||||
onClose: action('onClose'),
|
||||
};
|
||||
|
||||
export const _MaximumGroupSize = (): JSX.Element => (
|
||||
<AddGroupMemberErrorDialog
|
||||
{...defaultProps}
|
||||
mode={AddGroupMemberErrorDialogMode.MaximumGroupSize}
|
||||
maximumNumberOfContacts={123}
|
||||
/>
|
||||
);
|
||||
|
||||
_MaximumGroupSize.story = {
|
||||
name: 'Maximum group size',
|
||||
};
|
||||
export function MaximumGroupSize(): JSX.Element {
|
||||
return (
|
||||
<AddGroupMemberErrorDialog
|
||||
{...defaultProps}
|
||||
mode={AddGroupMemberErrorDialogMode.MaximumGroupSize}
|
||||
maximumNumberOfContacts={123}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function MaximumRecommendedGroupSize(): JSX.Element {
|
||||
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;
|
||||
};
|
||||
|
||||
type PropsType = {
|
||||
export type PropsType = {
|
||||
i18n: LocalizerType;
|
||||
onClose: () => void;
|
||||
} & PropsDataType;
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React from 'react';
|
||||
import type { Meta, Story } from '@storybook/react';
|
||||
import React, { useContext } from 'react';
|
||||
import type { Meta, StoryFn } from '@storybook/react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Props } from './AddUserToAnotherGroupModal';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
@ -19,28 +20,25 @@ const i18n = setupI18n('en', enMessages);
|
|||
export default {
|
||||
title: 'Components/AddUserToAnotherGroupModal',
|
||||
component: AddUserToAnotherGroupModal,
|
||||
argTypes: {
|
||||
candidateConversations: {
|
||||
defaultValue: Array.from(Array(100), () => getDefaultGroup()),
|
||||
},
|
||||
contact: {
|
||||
defaultValue: getDefaultConversation(),
|
||||
},
|
||||
i18n: {
|
||||
defaultValue: i18n,
|
||||
},
|
||||
addMembersToGroup: { action: true },
|
||||
toggleAddUserToAnotherGroupModal: { action: true },
|
||||
args: {
|
||||
i18n,
|
||||
candidateConversations: Array.from(Array(100), () => getDefaultGroup()),
|
||||
contact: getDefaultConversation(),
|
||||
},
|
||||
} as Meta;
|
||||
} satisfies Meta<Props>;
|
||||
|
||||
// eslint-disable-next-line react/function-component-definition
|
||||
const Template: Story<Props> = args => (
|
||||
<AddUserToAnotherGroupModal
|
||||
{...args}
|
||||
theme={React.useContext(StorybookThemeContext)}
|
||||
/>
|
||||
);
|
||||
const Template: StoryFn<Props> = args => {
|
||||
return (
|
||||
<AddUserToAnotherGroupModal
|
||||
{...args}
|
||||
addMembersToGroup={action('addMembersToGroup')}
|
||||
toggleAddUserToAnotherGroupModal={action(
|
||||
'toggleAddUserToAnotherGroupModal'
|
||||
)}
|
||||
theme={useContext(StorybookThemeContext)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const Modal = Template.bind({});
|
||||
Modal.args = {};
|
||||
|
|
|
@ -2,18 +2,18 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
import type { PropsType } from './Alert';
|
||||
import { Alert } from './Alert';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
export default {
|
||||
title: 'Components/Alert',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
const defaultProps = {
|
||||
i18n,
|
||||
|
@ -33,10 +33,6 @@ export function TitleAndBodyAreStrings(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
TitleAndBodyAreStrings.story = {
|
||||
name: 'Title and body are strings',
|
||||
};
|
||||
|
||||
export function BodyIsAReactNode(): JSX.Element {
|
||||
return (
|
||||
<Alert
|
||||
|
@ -52,10 +48,6 @@ export function BodyIsAReactNode(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
BodyIsAReactNode.story = {
|
||||
name: 'Body is a ReactNode',
|
||||
};
|
||||
|
||||
export function LongBodyWithoutTitle(): JSX.Element {
|
||||
return (
|
||||
<Alert
|
||||
|
@ -72,10 +64,6 @@ export function LongBodyWithoutTitle(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
LongBodyWithoutTitle.story = {
|
||||
name: 'Long body (without title)',
|
||||
};
|
||||
|
||||
export function LongBodyWithTitle(): JSX.Element {
|
||||
return (
|
||||
<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 { Modal } from './Modal';
|
||||
|
||||
type PropsType = {
|
||||
export type PropsType = {
|
||||
body: ReactNode;
|
||||
i18n: LocalizerType;
|
||||
onClose: () => void;
|
||||
|
|
|
@ -4,12 +4,13 @@
|
|||
import React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './AnimatedEmojiGalore';
|
||||
import { AnimatedEmojiGalore } from './AnimatedEmojiGalore';
|
||||
|
||||
export default {
|
||||
title: 'Components/AnimatedEmojiGalore',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
function getDefaultProps(): PropsType {
|
||||
return {
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// 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 { action } from '@storybook/addon-actions';
|
||||
import { expect } from '@storybook/jest';
|
||||
import { expect, jest } from '@storybook/jest';
|
||||
import { isBoolean } from 'lodash';
|
||||
import { within, userEvent } from '@storybook/testing-library';
|
||||
|
||||
import type { AvatarColorType } from '../types/Colors';
|
||||
import type { Props } from './Avatar';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
@ -42,7 +41,6 @@ export default {
|
|||
},
|
||||
blur: {
|
||||
control: { type: 'radio' },
|
||||
defaultValue: undefined,
|
||||
options: {
|
||||
Undefined: undefined,
|
||||
NoBlur: AvatarBlur.NoBlur,
|
||||
|
@ -51,14 +49,12 @@ export default {
|
|||
},
|
||||
},
|
||||
color: {
|
||||
defaultValue: AvatarColors[0],
|
||||
options: colorMap,
|
||||
},
|
||||
conversationType: {
|
||||
control: { type: 'radio' },
|
||||
options: conversationTypeMap,
|
||||
},
|
||||
onClick: { action: true },
|
||||
size: {
|
||||
control: false,
|
||||
},
|
||||
|
@ -68,11 +64,16 @@ export default {
|
|||
},
|
||||
theme: {
|
||||
control: { type: 'radio' },
|
||||
defaultValue: ThemeType.light,
|
||||
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 => ({
|
||||
acceptedMessageRequest: isBoolean(overrideProps.acceptedMessageRequest)
|
||||
|
@ -87,7 +88,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
|||
isMe: false,
|
||||
loading: Boolean(overrideProps.loading),
|
||||
noteToSelf: Boolean(overrideProps.noteToSelf),
|
||||
onClick: action('onClick'),
|
||||
onClick: jest.fn(action('onClick')),
|
||||
onClickBadge: action('onClickBadge'),
|
||||
phoneNumber: overrideProps.phoneNumber || '',
|
||||
searchResult: Boolean(overrideProps.searchResult),
|
||||
|
@ -103,16 +104,18 @@ const sizes = Object.values(AvatarSize).filter(
|
|||
) as Array<AvatarSize>;
|
||||
|
||||
// eslint-disable-next-line react/function-component-definition
|
||||
const Template: Story<Props> = args => (
|
||||
<>
|
||||
{sizes.map(size => (
|
||||
<Avatar key={size} {...args} size={size} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
const Template: StoryFn<Props> = (args: Props) => {
|
||||
return (
|
||||
<>
|
||||
{sizes.map(size => (
|
||||
<Avatar key={size} {...args} size={size} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line react/function-component-definition
|
||||
const TemplateSingle: Story<Props> = args => (
|
||||
const TemplateSingle: StoryFn<Props> = (args: Props) => (
|
||||
<Avatar {...args} size={AvatarSize.EIGHTY} />
|
||||
);
|
||||
|
||||
|
@ -120,72 +123,50 @@ export const Default = Template.bind({});
|
|||
Default.args = createProps({
|
||||
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 [avatar] = canvas.getAllByRole('button');
|
||||
await userEvent.click(avatar);
|
||||
await expect(args.onClick).toHaveBeenCalled();
|
||||
};
|
||||
Default.story = {
|
||||
name: 'Avatar',
|
||||
};
|
||||
|
||||
export const WithBadge = Template.bind({});
|
||||
WithBadge.args = createProps({
|
||||
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
||||
badge: getFakeBadge(),
|
||||
});
|
||||
WithBadge.story = {
|
||||
name: 'With badge',
|
||||
};
|
||||
|
||||
export const WideImage = Template.bind({});
|
||||
WideImage.args = createProps({
|
||||
avatarPath: '/fixtures/wide.jpg',
|
||||
});
|
||||
WideImage.story = {
|
||||
name: 'Wide image',
|
||||
};
|
||||
|
||||
export const OneWordName = Template.bind({});
|
||||
OneWordName.args = createProps({
|
||||
title: 'John',
|
||||
});
|
||||
OneWordName.story = {
|
||||
name: 'One-word Name',
|
||||
};
|
||||
|
||||
export const TwoWordName = Template.bind({});
|
||||
TwoWordName.args = createProps({
|
||||
title: 'John Smith',
|
||||
});
|
||||
TwoWordName.story = {
|
||||
name: 'Two-word Name',
|
||||
};
|
||||
|
||||
export const WideInitials = Template.bind({});
|
||||
WideInitials.args = createProps({
|
||||
title: 'Walter White',
|
||||
});
|
||||
WideInitials.story = {
|
||||
name: 'Wide initials',
|
||||
};
|
||||
|
||||
export const ThreeWordName = Template.bind({});
|
||||
ThreeWordName.args = createProps({
|
||||
title: 'Walter H. White',
|
||||
});
|
||||
ThreeWordName.story = {
|
||||
name: 'Three-word name',
|
||||
};
|
||||
|
||||
export const NoteToSelf = Template.bind({});
|
||||
NoteToSelf.args = createProps({
|
||||
noteToSelf: true,
|
||||
});
|
||||
NoteToSelf.story = {
|
||||
name: 'Note to Self',
|
||||
};
|
||||
|
||||
export const ContactIcon = Template.bind({});
|
||||
ContactIcon.args = createProps();
|
||||
|
@ -227,9 +208,6 @@ BrokenAvatarForGroup.args = createProps({
|
|||
avatarPath: 'badimage.png',
|
||||
conversationType: 'group',
|
||||
});
|
||||
BrokenAvatarForGroup.story = {
|
||||
name: 'Broken Avatar for Group',
|
||||
};
|
||||
|
||||
export const Loading = Template.bind({});
|
||||
Loading.args = createProps({
|
||||
|
@ -242,42 +220,26 @@ BlurredBasedOnProps.args = createProps({
|
|||
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
||||
});
|
||||
|
||||
BlurredBasedOnProps.story = {
|
||||
name: 'Blurred based on props',
|
||||
};
|
||||
|
||||
export const ForceBlurred = TemplateSingle.bind({});
|
||||
ForceBlurred.args = createProps({
|
||||
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
||||
blur: AvatarBlur.BlurPicture,
|
||||
});
|
||||
ForceBlurred.story = {
|
||||
name: 'Force-blurred',
|
||||
};
|
||||
|
||||
export const BlurredWithClickToView = TemplateSingle.bind({});
|
||||
BlurredWithClickToView.args = createProps({
|
||||
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
||||
blur: AvatarBlur.BlurPictureWithClickToView,
|
||||
});
|
||||
BlurredWithClickToView.story = {
|
||||
name: 'Blurred with "click to view"',
|
||||
};
|
||||
|
||||
export const StoryUnread = TemplateSingle.bind({});
|
||||
StoryUnread.args = createProps({
|
||||
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
||||
storyRing: HasStories.Unread,
|
||||
});
|
||||
StoryUnread.story = {
|
||||
name: 'Story: unread',
|
||||
};
|
||||
|
||||
export const StoryRead = TemplateSingle.bind({});
|
||||
StoryRead.args = createProps({
|
||||
avatarPath: '/fixtures/kitten-3-64-64.jpg',
|
||||
storyRing: HasStories.Read,
|
||||
});
|
||||
StoryRead.story = {
|
||||
name: 'Story: read',
|
||||
};
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import React from 'react';
|
||||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
|
@ -21,7 +22,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/AvatarColorPicker',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function Default(): JSX.Element {
|
||||
return <AvatarColorPicker {...createProps()} />;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import React from 'react';
|
||||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
|
@ -80,7 +81,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/AvatarEditor',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function NoAvatarGroup(): JSX.Element {
|
||||
return (
|
||||
|
@ -93,20 +94,12 @@ export function NoAvatarGroup(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
NoAvatarGroup.story = {
|
||||
name: 'No Avatar (group)',
|
||||
};
|
||||
|
||||
export function NoAvatarMe(): JSX.Element {
|
||||
return (
|
||||
<AvatarEditor {...createProps({ userAvatarData: getDefaultAvatars() })} />
|
||||
);
|
||||
}
|
||||
|
||||
NoAvatarMe.story = {
|
||||
name: 'No Avatar (me)',
|
||||
};
|
||||
|
||||
export function HasAvatar(): JSX.Element {
|
||||
return (
|
||||
<AvatarEditor
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import React from 'react';
|
||||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
|
@ -23,7 +24,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/AvatarIconEditor',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function PersonalIcon(): JSX.Element {
|
||||
return (
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React from 'react';
|
||||
|
||||
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 { AvatarColors } from '../types/Colors';
|
||||
import type { PropsType } from './AvatarLightbox';
|
||||
|
@ -15,51 +13,37 @@ import { getDefaultConversation } from '../test-both/helpers/getDefaultConversat
|
|||
|
||||
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 {
|
||||
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 {
|
||||
return (
|
||||
<AvatarLightbox
|
||||
{...createProps({
|
||||
isGroup: true,
|
||||
})}
|
||||
/>
|
||||
);
|
||||
export function Group(args: PropsType): JSX.Element {
|
||||
return <AvatarLightbox {...args} isGroup />;
|
||||
}
|
||||
|
||||
export function Person(): JSX.Element {
|
||||
export function Person(args: PropsType): JSX.Element {
|
||||
const conversation = getDefaultConversation();
|
||||
return (
|
||||
<AvatarLightbox
|
||||
{...createProps({
|
||||
avatarColor: conversation.color,
|
||||
conversationTitle: conversation.title,
|
||||
})}
|
||||
{...args}
|
||||
avatarColor={conversation.color}
|
||||
conversationTitle={conversation.title}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function Photo(): JSX.Element {
|
||||
return (
|
||||
<AvatarLightbox
|
||||
{...createProps({
|
||||
avatarPath: '/fixtures/kitten-1-64-64.jpg',
|
||||
})}
|
||||
/>
|
||||
);
|
||||
export function Photo(args: PropsType): JSX.Element {
|
||||
return <AvatarLightbox {...args} avatarPath="/fixtures/kitten-1-64-64.jpg" />;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import React from 'react';
|
|||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
import type { PropsType } from './AvatarModalButtons';
|
||||
import { AvatarModalButtons } from './AvatarModalButtons';
|
||||
|
@ -21,7 +22,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/AvatarModalButtons',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function HasChanges(): JSX.Element {
|
||||
return (
|
||||
|
@ -33,14 +34,6 @@ export function HasChanges(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
HasChanges.story = {
|
||||
name: 'Has changes',
|
||||
};
|
||||
|
||||
export function NoChanges(): JSX.Element {
|
||||
return <AvatarModalButtons {...createProps()} />;
|
||||
}
|
||||
|
||||
NoChanges.story = {
|
||||
name: 'No changes',
|
||||
};
|
||||
|
|
|
@ -6,6 +6,7 @@ import { chunk } from 'lodash';
|
|||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './AvatarPreview';
|
||||
import { AvatarPreview } from './AvatarPreview';
|
||||
import { AvatarColors } from '../types/Colors';
|
||||
|
@ -37,7 +38,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/AvatarPreview',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function NoStatePersonal(): JSX.Element {
|
||||
return (
|
||||
|
@ -50,10 +51,6 @@ export function NoStatePersonal(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
NoStatePersonal.story = {
|
||||
name: 'No state (personal)',
|
||||
};
|
||||
|
||||
export function NoStateGroup(): JSX.Element {
|
||||
return (
|
||||
<AvatarPreview
|
||||
|
@ -65,10 +62,6 @@ export function NoStateGroup(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
NoStateGroup.story = {
|
||||
name: 'No state (group)',
|
||||
};
|
||||
|
||||
export function NoStateGroupUploadMe(): JSX.Element {
|
||||
return (
|
||||
<AvatarPreview
|
||||
|
@ -81,18 +74,10 @@ export function NoStateGroupUploadMe(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
NoStateGroupUploadMe.story = {
|
||||
name: 'No state (group) + upload me',
|
||||
};
|
||||
|
||||
export function Value(): JSX.Element {
|
||||
return <AvatarPreview {...createProps({ avatarValue: TEST_IMAGE })} />;
|
||||
}
|
||||
|
||||
Value.story = {
|
||||
name: 'value',
|
||||
};
|
||||
|
||||
export function Path(): JSX.Element {
|
||||
return (
|
||||
<AvatarPreview
|
||||
|
@ -101,11 +86,7 @@ export function Path(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
Path.story = {
|
||||
name: 'path',
|
||||
};
|
||||
|
||||
export function ValuePath(): JSX.Element {
|
||||
export function ValueAndPath(): JSX.Element {
|
||||
return (
|
||||
<AvatarPreview
|
||||
{...createProps({
|
||||
|
@ -116,10 +97,6 @@ export function ValuePath(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ValuePath.story = {
|
||||
name: 'value & path',
|
||||
};
|
||||
|
||||
export function Style(): JSX.Element {
|
||||
return (
|
||||
<AvatarPreview
|
||||
|
@ -130,7 +107,3 @@ export function Style(): JSX.Element {
|
|||
/>
|
||||
);
|
||||
}
|
||||
|
||||
Style.story = {
|
||||
name: 'style',
|
||||
};
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import React from 'react';
|
||||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
|
@ -22,7 +23,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/AvatarTextEditor',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function Empty(): JSX.Element {
|
||||
return <AvatarTextEditor {...createProps()} />;
|
||||
|
@ -42,10 +43,6 @@ export function WithData(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
WithData.story = {
|
||||
name: 'with Data',
|
||||
};
|
||||
|
||||
export function WithWideCharacters(): JSX.Element {
|
||||
return (
|
||||
<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 { action } from '@storybook/addon-actions';
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
|
@ -20,7 +21,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/AvatarUploadButton',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function Default(): JSX.Element {
|
||||
return <AvatarUploadButton {...createProps()} />;
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { Props } from './BadgeDescription';
|
||||
import { BadgeDescription } from './BadgeDescription';
|
||||
|
||||
export default {
|
||||
title: 'Components/BadgeDescription',
|
||||
};
|
||||
} satisfies Meta<Props>;
|
||||
|
||||
export function NormalName(): JSX.Element {
|
||||
return (
|
||||
|
@ -19,11 +21,7 @@ export function NormalName(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
NormalName.story = {
|
||||
name: 'Normal name',
|
||||
};
|
||||
|
||||
export function NameWithRtlOverrides(): JSX.Element {
|
||||
export function NameWithRTLOverrides(): JSX.Element {
|
||||
return (
|
||||
<BadgeDescription
|
||||
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 { ContactName } from './conversation/ContactName';
|
||||
|
||||
export type Props = Readonly<{
|
||||
firstName?: string;
|
||||
template: string;
|
||||
title: string;
|
||||
}>;
|
||||
|
||||
export function BadgeDescription({
|
||||
firstName,
|
||||
template,
|
||||
title,
|
||||
}: Readonly<{
|
||||
firstName?: string;
|
||||
template: string;
|
||||
title: string;
|
||||
}>): ReactElement {
|
||||
}: Props): ReactElement {
|
||||
const result: Array<ReactChild> = [];
|
||||
|
||||
let lastIndex = 0;
|
||||
|
|
|
@ -5,18 +5,20 @@ import type { ComponentProps } from 'react';
|
|||
import React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
import { getFakeBadge, getFakeBadges } from '../test-both/helpers/getFakeBadge';
|
||||
import { repeat, zipObject } from '../util/iterables';
|
||||
import { BadgeImageTheme } from '../badges/BadgeImageTheme';
|
||||
import type { PropsType } from './BadgeDialog';
|
||||
import { BadgeDialog } from './BadgeDialog';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
export default {
|
||||
title: 'Components/BadgeDialog',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
const defaultProps: ComponentProps<typeof BadgeDialog> = {
|
||||
areWeASubscriber: false,
|
||||
|
@ -31,18 +33,10 @@ export function NoBadgesClosedImmediately(): JSX.Element {
|
|||
return <BadgeDialog {...defaultProps} badges={[]} />;
|
||||
}
|
||||
|
||||
NoBadgesClosedImmediately.story = {
|
||||
name: 'No badges (closed immediately)',
|
||||
};
|
||||
|
||||
export function OneBadge(): JSX.Element {
|
||||
return <BadgeDialog {...defaultProps} badges={getFakeBadges(1)} />;
|
||||
}
|
||||
|
||||
OneBadge.story = {
|
||||
name: 'One badge',
|
||||
};
|
||||
|
||||
export function BadgeWithNoImageShouldBeImpossible(): JSX.Element {
|
||||
return (
|
||||
<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 {
|
||||
return (
|
||||
<BadgeDialog
|
||||
|
@ -80,10 +70,6 @@ export function BadgeWithPendingImage(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
BadgeWithPendingImage.story = {
|
||||
name: 'Badge with pending image',
|
||||
};
|
||||
|
||||
export function BadgeWithOnlyOneLowDetailImage(): JSX.Element {
|
||||
return (
|
||||
<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 {
|
||||
return <BadgeDialog {...defaultProps} badges={getFakeBadges(5)} />;
|
||||
}
|
||||
|
||||
FiveBadges.story = {
|
||||
name: 'Five badges',
|
||||
};
|
||||
|
||||
export function ManyBadges(): JSX.Element {
|
||||
return <BadgeDialog {...defaultProps} badges={getFakeBadges(50)} />;
|
||||
}
|
||||
|
||||
ManyBadges.story = {
|
||||
name: 'Many badges',
|
||||
};
|
||||
|
||||
export function ManyBadgesUserIsASubscriber(): JSX.Element {
|
||||
return (
|
||||
<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 { BadgeSustainerInstructionsDialog } from './BadgeSustainerInstructionsDialog';
|
||||
|
||||
type PropsType = Readonly<{
|
||||
export type PropsType = Readonly<{
|
||||
areWeASubscriber: boolean;
|
||||
badges: ReadonlyArray<BadgeType>;
|
||||
firstName?: string;
|
||||
|
|
|
@ -5,6 +5,7 @@ import React from 'react';
|
|||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
import { AvatarColors } from '../types/Colors';
|
||||
import { GroupAvatarIcons, PersonalAvatarIcons } from '../types/Avatar';
|
||||
|
@ -28,7 +29,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/BetterAvatar',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function Text(): JSX.Element {
|
||||
return (
|
||||
|
|
|
@ -5,6 +5,7 @@ import React from 'react';
|
|||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
import { AvatarColors } from '../types/Colors';
|
||||
import type { PropsType } from './BetterAvatarBubble';
|
||||
|
@ -25,7 +26,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/BetterAvatarBubble',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function Children(): JSX.Element {
|
||||
return (
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
|
||||
import React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './Button';
|
||||
import { Button, ButtonSize, ButtonVariant } from './Button';
|
||||
|
||||
export default {
|
||||
title: 'Components/Button',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function KitchenSink(): JSX.Element {
|
||||
return (
|
||||
|
@ -44,10 +45,6 @@ export function KitchenSink(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
KitchenSink.story = {
|
||||
name: 'Kitchen sink',
|
||||
};
|
||||
|
||||
export function AriaLabel(): JSX.Element {
|
||||
return (
|
||||
<Button
|
||||
|
@ -58,10 +55,6 @@ export function AriaLabel(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
AriaLabel.story = {
|
||||
name: 'aria-label',
|
||||
};
|
||||
|
||||
export function CustomStyles(): JSX.Element {
|
||||
return (
|
||||
<Button onClick={action('onClick')} style={{ transform: 'rotate(5deg)' }}>
|
||||
|
@ -69,7 +62,3 @@ export function CustomStyles(): JSX.Element {
|
|||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
CustomStyles.story = {
|
||||
name: 'Custom styles',
|
||||
};
|
||||
|
|
|
@ -40,7 +40,7 @@ export enum ButtonIconType {
|
|||
video = 'video',
|
||||
}
|
||||
|
||||
type PropsType = {
|
||||
export type PropsType = {
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
icon?: ButtonIconType;
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
|
||||
import * as React from 'react';
|
||||
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 { CallManager } from './CallManager';
|
||||
import {
|
||||
|
@ -16,7 +15,6 @@ import {
|
|||
GroupCallJoinState,
|
||||
} from '../types/Calling';
|
||||
import type { ConversationTypeType } from '../state/ducks/conversations';
|
||||
import type { AvatarColorType } from '../types/Colors';
|
||||
import { AvatarColors } from '../types/Colors';
|
||||
import { generateAci } from '../types/ServiceId';
|
||||
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
|
||||
|
@ -33,13 +31,9 @@ const getConversation = () =>
|
|||
getDefaultConversation({
|
||||
id: '3051234567',
|
||||
avatarPath: undefined,
|
||||
color: select(
|
||||
'Callee color',
|
||||
AvatarColors,
|
||||
'ultramarine' as AvatarColorType
|
||||
),
|
||||
title: text('Callee Title', 'Rick Sanchez'),
|
||||
name: text('Callee Name', 'Rick Sanchez'),
|
||||
color: AvatarColors[0],
|
||||
title: 'Rick Sanchez',
|
||||
name: 'Rick Sanchez',
|
||||
phoneNumber: '3051234567',
|
||||
profileName: 'Rick Sanchez',
|
||||
markedUnread: false,
|
||||
|
@ -50,18 +44,14 @@ const getConversation = () =>
|
|||
const getCommonActiveCallData = () => ({
|
||||
conversation: getConversation(),
|
||||
joinedAt: Date.now(),
|
||||
hasLocalAudio: boolean('hasLocalAudio', true),
|
||||
hasLocalVideo: boolean('hasLocalVideo', false),
|
||||
localAudioLevel: select('localAudioLevel', [0, 0.5, 1], 0),
|
||||
viewMode: select(
|
||||
'viewMode',
|
||||
[CallViewMode.Grid, CallViewMode.Presentation, CallViewMode.Speaker],
|
||||
CallViewMode.Grid
|
||||
),
|
||||
outgoingRing: boolean('outgoingRing', true),
|
||||
pip: boolean('pip', false),
|
||||
settingsDialogOpen: boolean('settingsDialogOpen', false),
|
||||
showParticipantsList: boolean('showParticipantsList', false),
|
||||
hasLocalAudio: true,
|
||||
hasLocalVideo: false,
|
||||
localAudioLevel: 0,
|
||||
viewMode: CallViewMode.Grid,
|
||||
outgoingRing: true,
|
||||
pip: false,
|
||||
settingsDialogOpen: false,
|
||||
showParticipantsList: false,
|
||||
});
|
||||
|
||||
const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
|
||||
|
@ -83,12 +73,8 @@ const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
|
|||
keyChangeOk: action('key-change-ok'),
|
||||
me: {
|
||||
...getDefaultConversation({
|
||||
color: select(
|
||||
'Caller color',
|
||||
AvatarColors,
|
||||
'ultramarine' as AvatarColorType
|
||||
),
|
||||
title: text('Caller Title', 'Morty Smith'),
|
||||
color: AvatarColors[0],
|
||||
title: 'Morty Smith',
|
||||
}),
|
||||
serviceId: generateAci(),
|
||||
},
|
||||
|
@ -123,7 +109,9 @@ const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/CallManager',
|
||||
};
|
||||
argTypes: {},
|
||||
args: {},
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function NoCall(): JSX.Element {
|
||||
return <CallManager {...createProps()} />;
|
||||
|
@ -184,10 +172,6 @@ export function RingingDirectCall(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
RingingDirectCall.story = {
|
||||
name: 'Ringing (direct call)',
|
||||
};
|
||||
|
||||
export function RingingGroupCall(): JSX.Element {
|
||||
return (
|
||||
<CallManager
|
||||
|
@ -212,10 +196,6 @@ export function RingingGroupCall(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
RingingGroupCall.story = {
|
||||
name: 'Ringing (group call)',
|
||||
};
|
||||
|
||||
export function CallRequestNeeded(): JSX.Element {
|
||||
return (
|
||||
<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 { times } from 'lodash';
|
||||
import { boolean, select, number } from '@storybook/addon-knobs';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { GroupCallRemoteParticipantType } from '../types/Calling';
|
||||
import {
|
||||
CallMode,
|
||||
|
@ -60,6 +60,7 @@ type GroupCallOverrideProps = OverridePropsBase & {
|
|||
connectionState?: GroupCallConnectionState;
|
||||
peekedParticipants?: Array<ConversationType>;
|
||||
remoteParticipants?: Array<GroupCallRemoteParticipantType>;
|
||||
remoteAudioLevel?: number;
|
||||
};
|
||||
|
||||
const createActiveDirectCallProp = (
|
||||
|
@ -67,18 +68,11 @@ const createActiveDirectCallProp = (
|
|||
) => ({
|
||||
callMode: CallMode.Direct as CallMode.Direct,
|
||||
conversation,
|
||||
callState: select(
|
||||
'callState',
|
||||
CallState,
|
||||
overrideProps.callState || CallState.Accepted
|
||||
),
|
||||
callState: overrideProps.callState ?? CallState.Accepted,
|
||||
peekedParticipants: [] as [],
|
||||
remoteParticipants: [
|
||||
{
|
||||
hasRemoteVideo: boolean(
|
||||
'hasRemoteVideo',
|
||||
Boolean(overrideProps.hasRemoteVideo)
|
||||
),
|
||||
hasRemoteVideo: overrideProps.hasRemoteVideo ?? false,
|
||||
presenting: false,
|
||||
title: 'test',
|
||||
},
|
||||
|
@ -109,12 +103,7 @@ const createActiveGroupCallProp = (overrideProps: GroupCallOverrideProps) => ({
|
|||
remoteAudioLevels: new Map<number, number>(
|
||||
overrideProps.remoteParticipants?.map((_participant, index) => [
|
||||
index,
|
||||
number('remoteAudioLevel', 0, {
|
||||
range: true,
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.01,
|
||||
}),
|
||||
overrideProps.remoteAudioLevel ?? 0,
|
||||
])
|
||||
),
|
||||
});
|
||||
|
@ -125,24 +114,10 @@ const createActiveCallProp = (
|
|||
const baseResult = {
|
||||
joinedAt: Date.now(),
|
||||
conversation,
|
||||
hasLocalAudio: boolean(
|
||||
'hasLocalAudio',
|
||||
overrideProps.hasLocalAudio || false
|
||||
),
|
||||
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
|
||||
),
|
||||
hasLocalAudio: overrideProps.hasLocalAudio ?? false,
|
||||
hasLocalVideo: overrideProps.hasLocalVideo ?? false,
|
||||
localAudioLevel: overrideProps.localAudioLevel ?? 0,
|
||||
viewMode: overrideProps.viewMode ?? CallViewMode.Grid,
|
||||
outgoingRing: true,
|
||||
pip: false,
|
||||
settingsDialogOpen: false,
|
||||
|
@ -184,7 +159,7 @@ const createProps = (
|
|||
setLocalVideo: action('set-local-video'),
|
||||
setPresenting: action('toggle-presenting'),
|
||||
setRendererCanvas: action('set-renderer-canvas'),
|
||||
stickyControls: boolean('stickyControls', false),
|
||||
stickyControls: false,
|
||||
switchToPresentationView: action('switch-to-presentation-view'),
|
||||
switchFromPresentationView: action('switch-from-presentation-view'),
|
||||
toggleParticipants: action('toggle-participants'),
|
||||
|
@ -198,7 +173,9 @@ const createProps = (
|
|||
|
||||
export default {
|
||||
title: 'Components/CallScreen',
|
||||
};
|
||||
argTypes: {},
|
||||
args: {},
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function Default(): JSX.Element {
|
||||
return <CallScreen {...createProps()} />;
|
||||
|
@ -215,11 +192,7 @@ export function PreRing(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
PreRing.story = {
|
||||
name: 'Pre-Ring',
|
||||
};
|
||||
|
||||
export const _Ringing = (): JSX.Element => {
|
||||
export function Ringing(): JSX.Element {
|
||||
return (
|
||||
<CallScreen
|
||||
{...createProps({
|
||||
|
@ -228,9 +201,9 @@ export const _Ringing = (): JSX.Element => {
|
|||
})}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export const _Reconnecting = (): JSX.Element => {
|
||||
export function Reconnecting(): JSX.Element {
|
||||
return (
|
||||
<CallScreen
|
||||
{...createProps({
|
||||
|
@ -239,9 +212,9 @@ export const _Reconnecting = (): JSX.Element => {
|
|||
})}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export const _Ended = (): JSX.Element => {
|
||||
export function Ended(): JSX.Element {
|
||||
return (
|
||||
<CallScreen
|
||||
{...createProps({
|
||||
|
@ -250,7 +223,7 @@ export const _Ended = (): JSX.Element => {
|
|||
})}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export function HasLocalAudio(): JSX.Element {
|
||||
return (
|
||||
|
@ -263,10 +236,6 @@ export function HasLocalAudio(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
HasLocalAudio.story = {
|
||||
name: 'hasLocalAudio',
|
||||
};
|
||||
|
||||
export function HasLocalVideo(): JSX.Element {
|
||||
return (
|
||||
<CallScreen
|
||||
|
@ -278,10 +247,6 @@ export function HasLocalVideo(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
HasLocalVideo.story = {
|
||||
name: 'hasLocalVideo',
|
||||
};
|
||||
|
||||
export function HasRemoteVideo(): JSX.Element {
|
||||
return (
|
||||
<CallScreen
|
||||
|
@ -293,10 +258,6 @@ export function HasRemoteVideo(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
HasRemoteVideo.story = {
|
||||
name: 'hasRemoteVideo',
|
||||
};
|
||||
|
||||
export function GroupCall1(): JSX.Element {
|
||||
return (
|
||||
<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.
|
||||
const allRemoteParticipants = times(MAX_PARTICIPANTS).map(index => ({
|
||||
aci: generateAci(),
|
||||
|
@ -347,24 +304,12 @@ export function GroupCallMany(): JSX.Element {
|
|||
<CallScreen
|
||||
{...createProps({
|
||||
callMode: CallMode.Group,
|
||||
remoteParticipants: allRemoteParticipants.slice(
|
||||
0,
|
||||
number('Participant count', 40, {
|
||||
range: true,
|
||||
min: 0,
|
||||
max: MAX_PARTICIPANTS,
|
||||
step: 1,
|
||||
})
|
||||
),
|
||||
remoteParticipants: allRemoteParticipants.slice(0, 40),
|
||||
})}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
GroupCallMany.story = {
|
||||
name: 'Group call - Many',
|
||||
};
|
||||
|
||||
export function GroupCallReconnecting(): JSX.Element {
|
||||
return (
|
||||
<CallScreen
|
||||
|
@ -392,10 +337,6 @@ export function GroupCallReconnecting(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
GroupCallReconnecting.story = {
|
||||
name: 'Group call - reconnecting',
|
||||
};
|
||||
|
||||
export function GroupCall0(): JSX.Element {
|
||||
return (
|
||||
<CallScreen
|
||||
|
@ -407,10 +348,6 @@ export function GroupCall0(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
GroupCall0.story = {
|
||||
name: 'Group call - 0',
|
||||
};
|
||||
|
||||
export function GroupCallSomeoneIsSharingScreen(): JSX.Element {
|
||||
return (
|
||||
<CallScreen
|
||||
|
@ -428,10 +365,6 @@ export function GroupCallSomeoneIsSharingScreen(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
GroupCallSomeoneIsSharingScreen.story = {
|
||||
name: 'Group call - someone is sharing screen',
|
||||
};
|
||||
|
||||
export function GroupCallSomeoneIsSharingScreenAndYoureReconnecting(): JSX.Element {
|
||||
return (
|
||||
<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
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { boolean } from '@storybook/addon-knobs';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { Props } from './CallingAudioIndicator';
|
||||
import {
|
||||
CallingAudioIndicator,
|
||||
SPEAKING_LINGER_MS,
|
||||
|
@ -13,9 +13,18 @@ import { useValueAtFixedRate } from '../hooks/useValueAtFixedRate';
|
|||
|
||||
export default {
|
||||
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);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -32,14 +41,14 @@ export function Extreme(): JSX.Element {
|
|||
|
||||
return (
|
||||
<CallingAudioIndicator
|
||||
hasAudio={boolean('hasAudio', true)}
|
||||
hasAudio={args.hasAudio}
|
||||
audioLevel={audioLevel}
|
||||
shouldShowSpeaking={isSpeaking}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function Random(): JSX.Element {
|
||||
export function Random(args: Props): JSX.Element {
|
||||
const [audioLevel, setAudioLevel] = useState(1);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -56,7 +65,7 @@ export function Random(): JSX.Element {
|
|||
|
||||
return (
|
||||
<CallingAudioIndicator
|
||||
hasAudio={boolean('hasAudio', true)}
|
||||
hasAudio={args.hasAudio}
|
||||
audioLevel={audioLevel}
|
||||
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({
|
||||
hasAudio,
|
||||
audioLevel,
|
||||
shouldShowSpeaking,
|
||||
}: Readonly<{
|
||||
hasAudio: boolean;
|
||||
audioLevel: number;
|
||||
shouldShowSpeaking: boolean;
|
||||
}>): ReactElement {
|
||||
}: Props): ReactElement {
|
||||
if (!hasAudio) {
|
||||
return (
|
||||
<div
|
||||
|
|
|
@ -2,9 +2,8 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
import { select } from '@storybook/addon-knobs';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './CallingButton';
|
||||
import { CallingButton, CallingButtonType } from './CallingButton';
|
||||
import { TooltipPlacement } from './Tooltip';
|
||||
|
@ -13,101 +12,79 @@ import enMessages from '../../_locales/en/messages.json';
|
|||
|
||||
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 {
|
||||
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 (
|
||||
<>
|
||||
{Object.keys(CallingButtonType).map(buttonType => (
|
||||
<CallingButton
|
||||
key={buttonType}
|
||||
{...createProps({ buttonType: buttonType as CallingButtonType })}
|
||||
/>
|
||||
{Object.values(CallingButtonType).map(buttonType => (
|
||||
<CallingButton key={buttonType} {...args} buttonType={buttonType} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function AudioOn(): JSX.Element {
|
||||
const props = createProps({
|
||||
buttonType: CallingButtonType.AUDIO_ON,
|
||||
});
|
||||
return <CallingButton {...props} />;
|
||||
export function AudioOn(args: PropsType): JSX.Element {
|
||||
return <CallingButton {...args} buttonType={CallingButtonType.AUDIO_ON} />;
|
||||
}
|
||||
|
||||
export function AudioOff(): JSX.Element {
|
||||
const props = createProps({
|
||||
buttonType: CallingButtonType.AUDIO_OFF,
|
||||
});
|
||||
return <CallingButton {...props} />;
|
||||
export function AudioOff(args: PropsType): JSX.Element {
|
||||
return <CallingButton {...args} buttonType={CallingButtonType.AUDIO_OFF} />;
|
||||
}
|
||||
|
||||
export function AudioDisabled(): JSX.Element {
|
||||
const props = createProps({
|
||||
buttonType: CallingButtonType.AUDIO_DISABLED,
|
||||
});
|
||||
return <CallingButton {...props} />;
|
||||
export function AudioDisabled(args: PropsType): JSX.Element {
|
||||
return (
|
||||
<CallingButton {...args} buttonType={CallingButtonType.AUDIO_DISABLED} />
|
||||
);
|
||||
}
|
||||
|
||||
export function VideoOn(): JSX.Element {
|
||||
const props = createProps({
|
||||
buttonType: CallingButtonType.VIDEO_ON,
|
||||
});
|
||||
return <CallingButton {...props} />;
|
||||
export function VideoOn(args: PropsType): JSX.Element {
|
||||
return <CallingButton {...args} buttonType={CallingButtonType.VIDEO_ON} />;
|
||||
}
|
||||
|
||||
export function VideoOff(): JSX.Element {
|
||||
const props = createProps({
|
||||
buttonType: CallingButtonType.VIDEO_OFF,
|
||||
});
|
||||
return <CallingButton {...props} />;
|
||||
export function VideoOff(args: PropsType): JSX.Element {
|
||||
return <CallingButton {...args} buttonType={CallingButtonType.VIDEO_OFF} />;
|
||||
}
|
||||
|
||||
export function VideoDisabled(): JSX.Element {
|
||||
const props = createProps({
|
||||
buttonType: CallingButtonType.VIDEO_DISABLED,
|
||||
});
|
||||
return <CallingButton {...props} />;
|
||||
export function VideoDisabled(args: PropsType): JSX.Element {
|
||||
return (
|
||||
<CallingButton {...args} buttonType={CallingButtonType.VIDEO_DISABLED} />
|
||||
);
|
||||
}
|
||||
|
||||
export function TooltipRight(): JSX.Element {
|
||||
const props = createProps({
|
||||
tooltipDirection: TooltipPlacement.Right,
|
||||
});
|
||||
return <CallingButton {...props} />;
|
||||
export function TooltipRight(args: PropsType): JSX.Element {
|
||||
return <CallingButton {...args} tooltipDirection={TooltipPlacement.Right} />;
|
||||
}
|
||||
|
||||
TooltipRight.story = {
|
||||
name: 'Tooltip right',
|
||||
};
|
||||
|
||||
export function PresentingOn(): JSX.Element {
|
||||
const props = createProps({
|
||||
buttonType: CallingButtonType.PRESENTING_ON,
|
||||
});
|
||||
return <CallingButton {...props} />;
|
||||
export function PresentingOn(args: PropsType): JSX.Element {
|
||||
return (
|
||||
<CallingButton {...args} buttonType={CallingButtonType.PRESENTING_ON} />
|
||||
);
|
||||
}
|
||||
|
||||
export function PresentingOff(): JSX.Element {
|
||||
const props = createProps({
|
||||
buttonType: CallingButtonType.PRESENTING_OFF,
|
||||
});
|
||||
return <CallingButton {...props} />;
|
||||
export function PresentingOff(args: PropsType): JSX.Element {
|
||||
return (
|
||||
<CallingButton {...args} buttonType={CallingButtonType.PRESENTING_OFF} />
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import * as React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { Props } from './CallingDeviceSelection';
|
||||
import { CallingDeviceSelection } from './CallingDeviceSelection';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
|
@ -39,7 +40,7 @@ const createProps = ({
|
|||
|
||||
export default {
|
||||
title: 'Components/CallingDeviceSelection',
|
||||
};
|
||||
} satisfies Meta<Props>;
|
||||
|
||||
export function Default(): JSX.Element {
|
||||
return <CallingDeviceSelection {...createProps()} />;
|
||||
|
|
|
@ -2,9 +2,8 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
import { boolean, number } from '@storybook/addon-knobs';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './CallingHeader';
|
||||
import { CallingHeader } from './CallingHeader';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
|
@ -12,36 +11,35 @@ import enMessages from '../../_locales/en/messages.json';
|
|||
|
||||
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 {
|
||||
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 {
|
||||
return <CallingHeader {...createProps()} />;
|
||||
export function Default(args: PropsType): JSX.Element {
|
||||
return <CallingHeader {...args} />;
|
||||
}
|
||||
|
||||
export function LobbyStyle(): JSX.Element {
|
||||
export function LobbyStyle(args: PropsType): JSX.Element {
|
||||
return (
|
||||
<CallingHeader
|
||||
{...createProps()}
|
||||
{...args}
|
||||
title={undefined}
|
||||
togglePip={undefined}
|
||||
onCancel={action('onClose')}
|
||||
|
@ -49,59 +47,32 @@ export function LobbyStyle(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
LobbyStyle.story = {
|
||||
name: 'Lobby style',
|
||||
};
|
||||
export function WithParticipants(args: PropsType): JSX.Element {
|
||||
return <CallingHeader {...args} isGroupCall participantCount={10} />;
|
||||
}
|
||||
|
||||
export function WithParticipants(): JSX.Element {
|
||||
export function WithParticipantsShown(args: PropsType): JSX.Element {
|
||||
return (
|
||||
<CallingHeader
|
||||
{...createProps({
|
||||
isGroupCall: true,
|
||||
participantCount: 10,
|
||||
})}
|
||||
{...args}
|
||||
isGroupCall
|
||||
participantCount={10}
|
||||
showParticipantsList
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function WithParticipantsShown(): JSX.Element {
|
||||
export function LongTitle(args: PropsType): JSX.Element {
|
||||
return (
|
||||
<CallingHeader
|
||||
{...createProps({
|
||||
isGroupCall: true,
|
||||
participantCount: 10,
|
||||
showParticipantsList: true,
|
||||
})}
|
||||
{...args}
|
||||
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?"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
WithParticipantsShown.story = {
|
||||
name: 'With Participants (shown)',
|
||||
};
|
||||
|
||||
export function LongTitle(): JSX.Element {
|
||||
export function TitleWithMessage(args: PropsType): JSX.Element {
|
||||
return (
|
||||
<CallingHeader
|
||||
{...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?',
|
||||
})}
|
||||
/>
|
||||
<CallingHeader {...args} title="Hello world" message="Goodbye earth" />
|
||||
);
|
||||
}
|
||||
|
||||
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 { times } from 'lodash';
|
||||
import { boolean } from '@storybook/addon-knobs';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { v4 as generateUuid } from 'uuid';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { AvatarColors } from '../types/Colors';
|
||||
import type { ConversationType } from '../state/ducks/conversations';
|
||||
import type { PropsType } from './CallingLobby';
|
||||
|
@ -32,10 +32,7 @@ const camera = {
|
|||
};
|
||||
|
||||
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
||||
const isGroupCall = boolean(
|
||||
'isGroupCall',
|
||||
overrideProps.isGroupCall || false
|
||||
);
|
||||
const isGroupCall = overrideProps.isGroupCall ?? false;
|
||||
const conversation = isGroupCall
|
||||
? getDefaultConversation({
|
||||
title: 'Tahoe Trip',
|
||||
|
@ -49,19 +46,13 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
|||
groupMembers:
|
||||
overrideProps.groupMembers ||
|
||||
(isGroupCall ? times(3, () => getDefaultConversation()) : undefined),
|
||||
hasLocalAudio: boolean(
|
||||
'hasLocalAudio',
|
||||
overrideProps.hasLocalAudio ?? true
|
||||
),
|
||||
hasLocalVideo: boolean(
|
||||
'hasLocalVideo',
|
||||
overrideProps.hasLocalVideo ?? false
|
||||
),
|
||||
hasLocalAudio: overrideProps.hasLocalAudio ?? true,
|
||||
hasLocalVideo: overrideProps.hasLocalVideo ?? false,
|
||||
i18n,
|
||||
isGroupCall,
|
||||
isGroupCallOutboundRingEnabled: true,
|
||||
isConversationTooBigToRing: false,
|
||||
isCallFull: boolean('isCallFull', overrideProps.isCallFull || false),
|
||||
isCallFull: overrideProps.isCallFull ?? false,
|
||||
me:
|
||||
overrideProps.me ||
|
||||
getDefaultConversation({
|
||||
|
@ -71,16 +62,13 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
|||
}),
|
||||
onCallCanceled: action('on-call-canceled'),
|
||||
onJoinCall: action('on-join-call'),
|
||||
outgoingRing: boolean('outgoingRing', Boolean(overrideProps.outgoingRing)),
|
||||
outgoingRing: overrideProps.outgoingRing ?? false,
|
||||
peekedParticipants: overrideProps.peekedParticipants || [],
|
||||
setLocalAudio: action('set-local-audio'),
|
||||
setLocalPreview: action('set-local-preview'),
|
||||
setLocalVideo: action('set-local-video'),
|
||||
setOutgoingRing: action('set-outgoing-ring'),
|
||||
showParticipantsList: boolean(
|
||||
'showParticipantsList',
|
||||
Boolean(overrideProps.showParticipantsList)
|
||||
),
|
||||
showParticipantsList: overrideProps.showParticipantsList ?? false,
|
||||
toggleParticipants: action('toggle-participants'),
|
||||
toggleSettings: action('toggle-settings'),
|
||||
};
|
||||
|
@ -93,7 +81,9 @@ const fakePeekedParticipant = (conversationProps: Partial<ConversationType>) =>
|
|||
|
||||
export default {
|
||||
title: 'Components/CallingLobby',
|
||||
};
|
||||
argTypes: {},
|
||||
args: {},
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function Default(): JSX.Element {
|
||||
const props = createProps();
|
||||
|
@ -107,10 +97,6 @@ export function NoCameraNoAvatar(): JSX.Element {
|
|||
return <CallingLobby {...props} />;
|
||||
}
|
||||
|
||||
NoCameraNoAvatar.story = {
|
||||
name: 'No Camera, no avatar',
|
||||
};
|
||||
|
||||
export function NoCameraLocalAvatar(): JSX.Element {
|
||||
const props = createProps({
|
||||
availableCameras: [],
|
||||
|
@ -124,10 +110,6 @@ export function NoCameraLocalAvatar(): JSX.Element {
|
|||
return <CallingLobby {...props} />;
|
||||
}
|
||||
|
||||
NoCameraLocalAvatar.story = {
|
||||
name: 'No Camera, local avatar',
|
||||
};
|
||||
|
||||
export function LocalVideo(): JSX.Element {
|
||||
const props = createProps({
|
||||
hasLocalVideo: true,
|
||||
|
@ -142,20 +124,12 @@ export function InitiallyMuted(): JSX.Element {
|
|||
return <CallingLobby {...props} />;
|
||||
}
|
||||
|
||||
InitiallyMuted.story = {
|
||||
name: 'Initially muted',
|
||||
};
|
||||
|
||||
export function GroupCall0PeekedParticipants(): JSX.Element {
|
||||
export function GroupCallWithNoPeekedParticipants(): JSX.Element {
|
||||
const props = createProps({ isGroupCall: true, peekedParticipants: [] });
|
||||
return <CallingLobby {...props} />;
|
||||
}
|
||||
|
||||
GroupCall0PeekedParticipants.story = {
|
||||
name: 'Group Call - 0 peeked participants',
|
||||
};
|
||||
|
||||
export function GroupCall1PeekedParticipant(): JSX.Element {
|
||||
export function GroupCallWith1PeekedParticipant(): JSX.Element {
|
||||
const props = createProps({
|
||||
isGroupCall: true,
|
||||
peekedParticipants: [{ title: 'Sam' }].map(fakePeekedParticipant),
|
||||
|
@ -163,11 +137,7 @@ export function GroupCall1PeekedParticipant(): JSX.Element {
|
|||
return <CallingLobby {...props} />;
|
||||
}
|
||||
|
||||
GroupCall1PeekedParticipant.story = {
|
||||
name: 'Group Call - 1 peeked participant',
|
||||
};
|
||||
|
||||
export function GroupCall1PeekedParticipantSelf(): JSX.Element {
|
||||
export function GroupCallWith1PeekedParticipantSelf(): JSX.Element {
|
||||
const serviceId = generateAci();
|
||||
const props = createProps({
|
||||
isGroupCall: true,
|
||||
|
@ -180,11 +150,7 @@ export function GroupCall1PeekedParticipantSelf(): JSX.Element {
|
|||
return <CallingLobby {...props} />;
|
||||
}
|
||||
|
||||
GroupCall1PeekedParticipantSelf.story = {
|
||||
name: 'Group Call - 1 peeked participant (self)',
|
||||
};
|
||||
|
||||
export function GroupCall4PeekedParticipants(): JSX.Element {
|
||||
export function GroupCallWith4PeekedParticipants(): JSX.Element {
|
||||
const props = createProps({
|
||||
isGroupCall: true,
|
||||
peekedParticipants: ['Sam', 'Cayce', 'April', 'Logan', 'Carl'].map(title =>
|
||||
|
@ -194,11 +160,7 @@ export function GroupCall4PeekedParticipants(): JSX.Element {
|
|||
return <CallingLobby {...props} />;
|
||||
}
|
||||
|
||||
GroupCall4PeekedParticipants.story = {
|
||||
name: 'Group Call - 4 peeked participants',
|
||||
};
|
||||
|
||||
export function GroupCall4PeekedParticipantsParticipantsList(): JSX.Element {
|
||||
export function GroupCallWith4PeekedParticipantsParticipantsList(): JSX.Element {
|
||||
const props = createProps({
|
||||
isGroupCall: true,
|
||||
peekedParticipants: ['Sam', 'Cayce', 'April', 'Logan', 'Carl'].map(title =>
|
||||
|
@ -209,11 +171,7 @@ export function GroupCall4PeekedParticipantsParticipantsList(): JSX.Element {
|
|||
return <CallingLobby {...props} />;
|
||||
}
|
||||
|
||||
GroupCall4PeekedParticipantsParticipantsList.story = {
|
||||
name: 'Group Call - 4 peeked participants (participants list)',
|
||||
};
|
||||
|
||||
export function GroupCallCallFull(): JSX.Element {
|
||||
export function GroupCallWithCallFull(): JSX.Element {
|
||||
const props = createProps({
|
||||
isGroupCall: true,
|
||||
isCallFull: true,
|
||||
|
@ -224,18 +182,10 @@ export function GroupCallCallFull(): JSX.Element {
|
|||
return <CallingLobby {...props} />;
|
||||
}
|
||||
|
||||
GroupCallCallFull.story = {
|
||||
name: 'Group Call - call full',
|
||||
};
|
||||
|
||||
export function GroupCall0PeekedParticipantsBigGroup(): JSX.Element {
|
||||
export function GroupCallWith0PeekedParticipantsBigGroup(): JSX.Element {
|
||||
const props = createProps({
|
||||
isGroupCall: true,
|
||||
groupMembers: times(100, () => getDefaultConversation()),
|
||||
});
|
||||
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 { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './CallingParticipantsList';
|
||||
import { CallingParticipantsList } from './CallingParticipantsList';
|
||||
import { AvatarColors } from '../types/Colors';
|
||||
|
@ -47,17 +48,13 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/CallingParticipantsList',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function NoOne(): JSX.Element {
|
||||
const props = createProps();
|
||||
return <CallingParticipantsList {...props} />;
|
||||
}
|
||||
|
||||
NoOne.story = {
|
||||
name: 'No one',
|
||||
};
|
||||
|
||||
export function SoloCall(): JSX.Element {
|
||||
const props = createProps({
|
||||
participants: [
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
|
||||
import * as React from 'react';
|
||||
import { times } from 'lodash';
|
||||
import { boolean, select } from '@storybook/addon-knobs';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { AvatarColors } from '../types/Colors';
|
||||
import type { ConversationType } from '../state/ducks/conversations';
|
||||
import type { PropsType } from './CallingPip';
|
||||
|
@ -35,16 +34,19 @@ const conversation: ConversationType = getDefaultConversation({
|
|||
profileName: 'Rick Sanchez',
|
||||
});
|
||||
|
||||
const getCommonActiveCallData = () => ({
|
||||
type Overrides = {
|
||||
hasLocalAudio?: boolean;
|
||||
hasLocalVideo?: boolean;
|
||||
localAudioLevel?: number;
|
||||
viewMode?: CallViewMode;
|
||||
};
|
||||
|
||||
const getCommonActiveCallData = (overrides: Overrides) => ({
|
||||
conversation,
|
||||
hasLocalAudio: boolean('hasLocalAudio', true),
|
||||
hasLocalVideo: boolean('hasLocalVideo', false),
|
||||
localAudioLevel: select('localAudioLevel', [0, 0.5, 1], 0),
|
||||
viewMode: select(
|
||||
'viewMode',
|
||||
[CallViewMode.Grid, CallViewMode.Speaker, CallViewMode.Presentation],
|
||||
CallViewMode.Grid
|
||||
),
|
||||
hasLocalAudio: overrides.hasLocalAudio ?? true,
|
||||
hasLocalVideo: overrides.hasLocalVideo ?? false,
|
||||
localAudioLevel: overrides.localAudioLevel ?? 0,
|
||||
viewMode: overrides.viewMode ?? CallViewMode.Grid,
|
||||
joinedAt: Date.now(),
|
||||
outgoingRing: true,
|
||||
pip: true,
|
||||
|
@ -52,92 +54,93 @@ const getCommonActiveCallData = () => ({
|
|||
showParticipantsList: false,
|
||||
});
|
||||
|
||||
const defaultCall: ActiveDirectCallType = {
|
||||
...getCommonActiveCallData(),
|
||||
callMode: CallMode.Direct as CallMode.Direct,
|
||||
callState: CallState.Accepted,
|
||||
peekedParticipants: [],
|
||||
remoteParticipants: [
|
||||
{ hasRemoteVideo: true, presenting: false, title: 'Arsene' },
|
||||
],
|
||||
const getDefaultCall = (overrides: Overrides): ActiveDirectCallType => {
|
||||
return {
|
||||
...getCommonActiveCallData(overrides),
|
||||
callMode: CallMode.Direct as CallMode.Direct,
|
||||
callState: CallState.Accepted,
|
||||
peekedParticipants: [],
|
||||
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 {
|
||||
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 {
|
||||
const props = createProps({});
|
||||
return <CallingPip {...props} />;
|
||||
export function Default(args: PropsType): JSX.Element {
|
||||
return <CallingPip {...args} />;
|
||||
}
|
||||
|
||||
export function ContactWithAvatarAndNoVideo(): JSX.Element {
|
||||
const props = createProps({
|
||||
activeCall: {
|
||||
...defaultCall,
|
||||
conversation: {
|
||||
...conversation,
|
||||
avatarPath: 'https://www.fillmurray.com/64/64',
|
||||
},
|
||||
remoteParticipants: [
|
||||
{ hasRemoteVideo: false, presenting: false, title: 'Julian' },
|
||||
],
|
||||
},
|
||||
});
|
||||
return <CallingPip {...props} />;
|
||||
export function ContactWithAvatarAndNoVideo(args: PropsType): JSX.Element {
|
||||
return (
|
||||
<CallingPip
|
||||
{...args}
|
||||
activeCall={{
|
||||
...getDefaultCall({}),
|
||||
conversation: {
|
||||
...conversation,
|
||||
avatarPath: 'https://www.fillmurray.com/64/64',
|
||||
},
|
||||
remoteParticipants: [
|
||||
{ hasRemoteVideo: false, presenting: false, title: 'Julian' },
|
||||
],
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
ContactWithAvatarAndNoVideo.story = {
|
||||
name: 'Contact (with avatar and no video)',
|
||||
};
|
||||
|
||||
export function ContactNoColor(): JSX.Element {
|
||||
const props = createProps({
|
||||
activeCall: {
|
||||
...defaultCall,
|
||||
conversation: {
|
||||
...conversation,
|
||||
color: undefined,
|
||||
},
|
||||
},
|
||||
});
|
||||
return <CallingPip {...props} />;
|
||||
export function ContactNoColor(args: PropsType): JSX.Element {
|
||||
return (
|
||||
<CallingPip
|
||||
{...args}
|
||||
activeCall={{
|
||||
...getDefaultCall({}),
|
||||
conversation: {
|
||||
...conversation,
|
||||
color: undefined,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
ContactNoColor.story = {
|
||||
name: 'Contact (no color)',
|
||||
};
|
||||
|
||||
export function GroupCall(): JSX.Element {
|
||||
const props = createProps({
|
||||
activeCall: {
|
||||
...getCommonActiveCallData(),
|
||||
callMode: CallMode.Group as CallMode.Group,
|
||||
connectionState: GroupCallConnectionState.Connected,
|
||||
conversationsWithSafetyNumberChanges: [],
|
||||
groupMembers: times(3, () => getDefaultConversation()),
|
||||
isConversationTooBigToRing: false,
|
||||
joinState: GroupCallJoinState.Joined,
|
||||
maxDevices: 5,
|
||||
deviceCount: 0,
|
||||
peekedParticipants: [],
|
||||
remoteParticipants: [],
|
||||
remoteAudioLevels: new Map<number, number>(),
|
||||
},
|
||||
});
|
||||
return <CallingPip {...props} />;
|
||||
export function GroupCall(args: PropsType): JSX.Element {
|
||||
return (
|
||||
<CallingPip
|
||||
{...args}
|
||||
activeCall={{
|
||||
...getCommonActiveCallData({}),
|
||||
callMode: CallMode.Group as CallMode.Group,
|
||||
connectionState: GroupCallConnectionState.Connected,
|
||||
conversationsWithSafetyNumberChanges: [],
|
||||
groupMembers: times(3, () => getDefaultConversation()),
|
||||
isConversationTooBigToRing: false,
|
||||
joinState: GroupCallJoinState.Joined,
|
||||
maxDevices: 5,
|
||||
deviceCount: 0,
|
||||
peekedParticipants: [],
|
||||
remoteParticipants: [],
|
||||
remoteAudioLevels: new Map<number, number>(),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
|
||||
import React from 'react';
|
||||
import { times } from 'lodash';
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
|
||||
|
||||
import type { PropsType } from './CallingPreCallInfo';
|
||||
import { CallingPreCallInfo, RingMode } from './CallingPreCallInfo';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
@ -22,7 +23,7 @@ const otherMembers = times(6, () => getDefaultConversation());
|
|||
|
||||
export default {
|
||||
title: 'Components/CallingPreCallInfo',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function DirectConversation(): JSX.Element {
|
||||
return (
|
||||
|
@ -35,10 +36,6 @@ export function DirectConversation(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
DirectConversation.story = {
|
||||
name: 'Direct conversation',
|
||||
};
|
||||
|
||||
export function Ring0(): JSX.Element {
|
||||
return (
|
||||
<CallingPreCallInfo
|
||||
|
@ -52,10 +49,6 @@ export function Ring0(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
Ring0.story = {
|
||||
name: 'Group call: Will ring 0 people',
|
||||
};
|
||||
|
||||
export function Ring1(): JSX.Element {
|
||||
return (
|
||||
<CallingPreCallInfo
|
||||
|
@ -69,10 +62,6 @@ export function Ring1(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
Ring1.story = {
|
||||
name: 'Group call: Will ring 1 person',
|
||||
};
|
||||
|
||||
export function Ring2(): JSX.Element {
|
||||
return (
|
||||
<CallingPreCallInfo
|
||||
|
@ -86,10 +75,6 @@ export function Ring2(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
Ring2.story = {
|
||||
name: 'Group call: Will ring 2 people',
|
||||
};
|
||||
|
||||
export function Ring3(): JSX.Element {
|
||||
return (
|
||||
<CallingPreCallInfo
|
||||
|
@ -103,10 +88,6 @@ export function Ring3(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
Ring3.story = {
|
||||
name: 'Group call: Will ring 3 people',
|
||||
};
|
||||
|
||||
export function Ring4(): JSX.Element {
|
||||
return (
|
||||
<CallingPreCallInfo
|
||||
|
@ -120,10 +101,6 @@ export function Ring4(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
Ring3.story = {
|
||||
name: 'Group call: Will ring 4 people',
|
||||
};
|
||||
|
||||
export function Notify0(): JSX.Element {
|
||||
return (
|
||||
<CallingPreCallInfo
|
||||
|
@ -137,10 +114,6 @@ export function Notify0(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
Notify0.story = {
|
||||
name: 'Group call: Will notify 0 people',
|
||||
};
|
||||
|
||||
export function Notify1(): JSX.Element {
|
||||
return (
|
||||
<CallingPreCallInfo
|
||||
|
@ -154,10 +127,6 @@ export function Notify1(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
Notify1.story = {
|
||||
name: 'Group call: Will notify 1 person',
|
||||
};
|
||||
|
||||
export function Notify2(): JSX.Element {
|
||||
return (
|
||||
<CallingPreCallInfo
|
||||
|
@ -171,10 +140,6 @@ export function Notify2(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
Notify2.story = {
|
||||
name: 'Group call: Will notify 2 people',
|
||||
};
|
||||
|
||||
export function Notify3(): JSX.Element {
|
||||
return (
|
||||
<CallingPreCallInfo
|
||||
|
@ -188,10 +153,6 @@ export function Notify3(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
Notify3.story = {
|
||||
name: 'Group call: Will notify 3 people',
|
||||
};
|
||||
|
||||
export function Notify4(): JSX.Element {
|
||||
return (
|
||||
<CallingPreCallInfo
|
||||
|
@ -205,10 +166,6 @@ export function Notify4(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
Notify4.story = {
|
||||
name: 'Group call: Will notify 4 people',
|
||||
};
|
||||
|
||||
export function Peek1(): JSX.Element {
|
||||
return (
|
||||
<CallingPreCallInfo
|
||||
|
@ -222,10 +179,6 @@ export function Peek1(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
Peek1.story = {
|
||||
name: 'Group call: 1 participant peeked',
|
||||
};
|
||||
|
||||
export function Peek2(): JSX.Element {
|
||||
return (
|
||||
<CallingPreCallInfo
|
||||
|
@ -239,10 +192,6 @@ export function Peek2(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
Peek2.story = {
|
||||
name: 'Group call: 2 participants peeked',
|
||||
};
|
||||
|
||||
export function Peek3(): JSX.Element {
|
||||
return (
|
||||
<CallingPreCallInfo
|
||||
|
@ -256,10 +205,6 @@ export function Peek3(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
Peek3.story = {
|
||||
name: 'Group call: 3 participants peeked',
|
||||
};
|
||||
|
||||
export function Peek4(): JSX.Element {
|
||||
return (
|
||||
<CallingPreCallInfo
|
||||
|
@ -273,10 +218,6 @@ export function Peek4(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
Peek4.story = {
|
||||
name: 'Group call: 4 participants peeked',
|
||||
};
|
||||
|
||||
export function GroupConversationYouOnAnOtherDevice(): JSX.Element {
|
||||
const me = getDefaultConversation();
|
||||
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 {
|
||||
return (
|
||||
<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,
|
||||
}
|
||||
|
||||
type PropsType = {
|
||||
export type PropsType = {
|
||||
conversation: Pick<
|
||||
ConversationType,
|
||||
| 'acceptedMessageRequest'
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './CallingScreenSharingController';
|
||||
import { CallingScreenSharingController } from './CallingScreenSharingController';
|
||||
|
||||
|
@ -21,7 +22,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/CallingScreenSharingController',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function Controller(): JSX.Element {
|
||||
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 { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './CallingSelectPresentingSourcesModal';
|
||||
import { CallingSelectPresentingSourcesModal } from './CallingSelectPresentingSourcesModal';
|
||||
|
||||
|
@ -55,7 +56,7 @@ const createProps = (): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/CallingSelectPresentingSourcesModal',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function Modal(): JSX.Element {
|
||||
return <CallingSelectPresentingSourcesModal {...createProps()} />;
|
||||
|
|
|
@ -3,36 +3,33 @@
|
|||
|
||||
import React, { useState } from 'react';
|
||||
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 { Button } from './Button';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
export default {
|
||||
title: 'Components/CaptchaDialog',
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
if (isSkipped) {
|
||||
return <Button onClick={() => setIsSkipped(false)}>Show again</Button>;
|
||||
}
|
||||
|
||||
return (
|
||||
<CaptchaDialog
|
||||
i18n={i18n}
|
||||
isPending={boolean('isPending', false)}
|
||||
onContinue={action('onContinue')}
|
||||
onSkip={() => setIsSkipped(true)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
_CaptchaDialog.story = {
|
||||
name: 'CaptchaDialog',
|
||||
};
|
||||
return <CaptchaDialog {...args} onSkip={() => setIsSkipped(true)} />;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import { Button, ButtonVariant } from './Button';
|
|||
import { Modal } from './Modal';
|
||||
import { Spinner } from './Spinner';
|
||||
|
||||
type PropsType = {
|
||||
export type PropsType = {
|
||||
i18n: LocalizerType;
|
||||
isPending: boolean;
|
||||
|
||||
|
|
|
@ -2,21 +2,45 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React from 'react';
|
||||
|
||||
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 type { PropsType } from './ChatColorPicker';
|
||||
import { ChatColorPicker } from './ChatColorPicker';
|
||||
import { ConversationColors } from '../types/Colors';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
export default {
|
||||
title: 'Components/ChatColorPicker',
|
||||
};
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
argTypes: {
|
||||
selectedColor: {
|
||||
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 = {
|
||||
deg: 90,
|
||||
|
@ -24,25 +48,8 @@ const SAMPLE_CUSTOM_COLOR = {
|
|||
start: { hue: 315, saturation: 78 },
|
||||
};
|
||||
|
||||
const createProps = (): PropsType => ({
|
||||
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: select('selectedColor', ConversationColors, 'basil' as const),
|
||||
selectedCustomColor: {},
|
||||
setGlobalDefaultConversationColor: action(
|
||||
'setGlobalDefaultConversationColor'
|
||||
),
|
||||
});
|
||||
|
||||
export function Default(): JSX.Element {
|
||||
return <ChatColorPicker {...createProps()} />;
|
||||
export function Default(args: PropsType): JSX.Element {
|
||||
return <ChatColorPicker {...args} />;
|
||||
}
|
||||
|
||||
const CUSTOM_COLORS = {
|
||||
|
@ -62,10 +69,10 @@ const CUSTOM_COLORS = {
|
|||
},
|
||||
};
|
||||
|
||||
export function CustomColors(): JSX.Element {
|
||||
export function CustomColors(args: PropsType): JSX.Element {
|
||||
return (
|
||||
<ChatColorPicker
|
||||
{...createProps()}
|
||||
{...args}
|
||||
customColors={CUSTOM_COLORS}
|
||||
selectedColor="custom"
|
||||
selectedCustomColor={{
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './Checkbox';
|
||||
import { Checkbox } from './Checkbox';
|
||||
|
||||
|
@ -16,7 +17,7 @@ const createProps = (): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/Checkbox',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function Normal(): JSX.Element {
|
||||
return <Checkbox {...createProps()} />;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { Props } from './CircleCheckbox';
|
||||
import { CircleCheckbox, Variant } from './CircleCheckbox';
|
||||
|
||||
|
@ -15,7 +15,7 @@ const createProps = (): Props => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/CircleCheckbox',
|
||||
};
|
||||
} satisfies Meta<Props>;
|
||||
|
||||
export function Normal(): JSX.Element {
|
||||
return <CircleCheckbox {...createProps()} />;
|
||||
|
|
|
@ -2,23 +2,19 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
import type { PropsType } from './ClearingData';
|
||||
import { ClearingData } from './ClearingData';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
export default {
|
||||
title: 'Components/ClearingData',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export const _ClearingData = (): JSX.Element => (
|
||||
<ClearingData deleteAllData={action('deleteAllData')} i18n={i18n} />
|
||||
);
|
||||
|
||||
_ClearingData.story = {
|
||||
name: 'Clearing data',
|
||||
};
|
||||
export function Basic(): JSX.Element {
|
||||
return <ClearingData deleteAllData={action('deleteAllData')} i18n={i18n} />;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { DecoratorFunction } from '@storybook/addons';
|
||||
import * as React from 'react';
|
||||
|
||||
import React, { useContext } from 'react';
|
||||
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 type { Props } from './CompositionArea';
|
||||
import { CompositionArea } from './CompositionArea';
|
||||
|
@ -28,287 +25,256 @@ export default {
|
|||
decorators: [
|
||||
// necessary for the add attachment button to render properly
|
||||
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 => ({
|
||||
addAttachment: action('addAttachment'),
|
||||
conversationId: '123',
|
||||
convertDraftBodyRangesIntoHydrated: () => undefined,
|
||||
discardEditMessage: action('discardEditMessage'),
|
||||
focusCounter: 0,
|
||||
sendCounter: 0,
|
||||
i18n,
|
||||
isDisabled: false,
|
||||
isFormattingFlagEnabled:
|
||||
overrideProps.isFormattingFlagEnabled === false
|
||||
? overrideProps.isFormattingFlagEnabled
|
||||
: true,
|
||||
isFormattingSpoilersFlagEnabled:
|
||||
overrideProps.isFormattingSpoilersFlagEnabled === false
|
||||
? overrideProps.isFormattingSpoilersFlagEnabled
|
||||
: true,
|
||||
isFormattingEnabled:
|
||||
overrideProps.isFormattingEnabled === false
|
||||
? overrideProps.isFormattingEnabled
|
||||
: true,
|
||||
messageCompositionId: '456',
|
||||
sendEditedMessage: action('sendEditedMessage'),
|
||||
sendMultiMediaMessage: action('sendMultiMediaMessage'),
|
||||
platform: 'darwin',
|
||||
processAttachments: action('processAttachments'),
|
||||
removeAttachment: action('removeAttachment'),
|
||||
theme: React.useContext(StorybookThemeContext),
|
||||
setComposerFocus: action('setComposerFocus'),
|
||||
setMessageToEdit: action('setMessageToEdit'),
|
||||
setQuoteByMessageId: action('setQuoteByMessageId'),
|
||||
showToast: action('showToast'),
|
||||
// AttachmentList
|
||||
draftAttachments: [],
|
||||
onClearAttachments: action('onClearAttachments'),
|
||||
// AudioCapture
|
||||
cancelRecording: action('cancelRecording'),
|
||||
completeRecording: action('completeRecording'),
|
||||
errorRecording: action('errorRecording'),
|
||||
recordingState: RecordingState.Idle,
|
||||
startRecording: action('startRecording'),
|
||||
// StagedLinkPreview
|
||||
linkPreviewLoading: false,
|
||||
linkPreviewResult: undefined,
|
||||
onCloseLinkPreview: action('onCloseLinkPreview'),
|
||||
// Quote
|
||||
quotedMessageProps: undefined,
|
||||
scrollToMessage: action('scrollToMessage'),
|
||||
// MediaEditor
|
||||
imageToBlurHash: async () => 'LDA,FDBnm+I=p{tkIUI;~UkpELV]',
|
||||
// MediaQualitySelector
|
||||
setMediaQualitySetting: action('setMediaQualitySetting'),
|
||||
shouldSendHighQualityAttachments: false,
|
||||
// CompositionInput
|
||||
onEditorStateChange: action('onEditorStateChange'),
|
||||
onTextTooLong: action('onTextTooLong'),
|
||||
draftText: undefined,
|
||||
clearQuotedMessage: action('clearQuotedMessage'),
|
||||
getPreferredBadge: () => undefined,
|
||||
getQuotedMessage: action('getQuotedMessage'),
|
||||
sortedGroupMembers: [],
|
||||
// EmojiButton
|
||||
onPickEmoji: action('onPickEmoji'),
|
||||
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
|
||||
draftAttachments: overrideProps.draftAttachments || [],
|
||||
onClearAttachments: action('onClearAttachments'),
|
||||
// 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 Default(args: Props): JSX.Element {
|
||||
const theme = useContext(StorybookThemeContext);
|
||||
return <CompositionArea {...args} theme={theme} />;
|
||||
}
|
||||
|
||||
export function StartingText(): JSX.Element {
|
||||
const props = useProps({
|
||||
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 {
|
||||
export function StartingText(args: Props): JSX.Element {
|
||||
const theme = useContext(StorybookThemeContext);
|
||||
return (
|
||||
<CompositionArea
|
||||
{...useProps({
|
||||
areWePendingApproval: true,
|
||||
})}
|
||||
{...args}
|
||||
theme={theme}
|
||||
draftText="here's some starting text"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
AnnouncementsOnlyGroup.story = {
|
||||
name: 'Announcements Only group',
|
||||
};
|
||||
|
||||
export function AnnouncementsOnlyGroup(): JSX.Element {
|
||||
export function StickerButton(args: Props): JSX.Element {
|
||||
const theme = useContext(StorybookThemeContext);
|
||||
return (
|
||||
<CompositionArea
|
||||
{...useProps({
|
||||
announcementsOnly: true,
|
||||
areWeAdmin: false,
|
||||
})}
|
||||
{...args}
|
||||
theme={theme}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
knownPacks={[{} as any]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
AnnouncementsOnlyGroup.story = {
|
||||
name: 'Announcements Only group',
|
||||
};
|
||||
export function MessageRequest(args: Props): JSX.Element {
|
||||
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 (
|
||||
<CompositionArea
|
||||
{...useProps({
|
||||
quotedMessageProps: {
|
||||
text: 'something',
|
||||
conversationColor: ConversationColors[10],
|
||||
conversationTitle: getDefaultConversation().title,
|
||||
isGiftBadge: false,
|
||||
isViewOnce: false,
|
||||
referencedMessageNotFound: false,
|
||||
authorTitle: 'Someone',
|
||||
isFromMe: false,
|
||||
{...args}
|
||||
theme={theme}
|
||||
draftAttachments={[
|
||||
fakeDraftAttachment({
|
||||
contentType: IMAGE_JPEG,
|
||||
url: landscapeGreenUrl,
|
||||
}),
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
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 (
|
||||
<CompositionArea
|
||||
{...useProps({
|
||||
quotedMessageProps: {
|
||||
text: '',
|
||||
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 })}
|
||||
{...args}
|
||||
theme={theme}
|
||||
isFormattingSpoilersFlagEnabled={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,11 +2,9 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
import 'react-quill/dist/quill.core.css';
|
||||
import { boolean, select } from '@storybook/addon-knobs';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
|
||||
import type { Props } from './CompositionInput';
|
||||
import { CompositionInput } from './CompositionInput';
|
||||
|
@ -19,11 +17,13 @@ const i18n = setupI18n('en', enMessages);
|
|||
|
||||
export default {
|
||||
title: 'Components/CompositionInput',
|
||||
};
|
||||
argTypes: {},
|
||||
args: {},
|
||||
} satisfies Meta<Props>;
|
||||
|
||||
const useProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||
i18n,
|
||||
disabled: boolean('disabled', overrideProps.disabled || false),
|
||||
disabled: overrideProps.disabled ?? false,
|
||||
draftText: overrideProps.draftText || undefined,
|
||||
draftBodyRanges: overrideProps.draftBodyRanges || [],
|
||||
clearQuotedMessage: action('clearQuotedMessage'),
|
||||
|
@ -41,7 +41,7 @@ const useProps = (overrideProps: Partial<Props> = {}): Props => ({
|
|||
overrideProps.isFormattingEnabled === false
|
||||
? overrideProps.isFormattingEnabled
|
||||
: true,
|
||||
large: boolean('large', overrideProps.large || false),
|
||||
large: overrideProps.large ?? false,
|
||||
onCloseLinkPreview: action('onCloseLinkPreview'),
|
||||
onEditorStateChange: action('onEditorStateChange'),
|
||||
onPickEmoji: action('onPickEmoji'),
|
||||
|
@ -49,19 +49,8 @@ const useProps = (overrideProps: Partial<Props> = {}): Props => ({
|
|||
onTextTooLong: action('onTextTooLong'),
|
||||
platform: 'darwin',
|
||||
sendCounter: 0,
|
||||
sortedGroupMembers: overrideProps.sortedGroupMembers || [],
|
||||
skinTone: select(
|
||||
'skinTone',
|
||||
{
|
||||
skinTone0: 0,
|
||||
skinTone1: 1,
|
||||
skinTone2: 2,
|
||||
skinTone3: 3,
|
||||
skinTone4: 4,
|
||||
skinTone5: 5,
|
||||
},
|
||||
overrideProps.skinTone || undefined
|
||||
),
|
||||
sortedGroupMembers: overrideProps.sortedGroupMembers ?? [],
|
||||
skinTone: overrideProps.skinTone ?? undefined,
|
||||
theme: React.useContext(StorybookThemeContext),
|
||||
});
|
||||
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
|
||||
import React, { useState } from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { Props } from './CompositionRecording';
|
||||
import { CompositionRecording } from './CompositionRecording';
|
||||
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
|
@ -13,7 +14,7 @@ const i18n = setupI18n('en', enMessages);
|
|||
export default {
|
||||
title: 'components/CompositionRecording',
|
||||
component: CompositionRecording,
|
||||
};
|
||||
} satisfies Meta<Props>;
|
||||
|
||||
export function Default(): JSX.Element {
|
||||
const [active, setActive] = useState(false);
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
|
||||
import React, { useState } from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { Props } from './CompositionRecordingDraft';
|
||||
import { CompositionRecordingDraft } from './CompositionRecordingDraft';
|
||||
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
|
@ -13,7 +14,7 @@ const i18n = setupI18n('en', enMessages);
|
|||
export default {
|
||||
title: 'components/CompositionRecordingDraft',
|
||||
component: CompositionRecordingDraft,
|
||||
};
|
||||
} satisfies Meta<Props>;
|
||||
|
||||
export function Default(): JSX.Element {
|
||||
const [isPlaying, setIsPlaying] = useState(false);
|
||||
|
|
|
@ -11,7 +11,7 @@ import * as log from '../logging/log';
|
|||
import type { Size } from '../hooks/useSizeObserver';
|
||||
import { SizeObserver } from '../hooks/useSizeObserver';
|
||||
|
||||
type Props = {
|
||||
export type Props = {
|
||||
i18n: LocalizerType;
|
||||
audioUrl: string | undefined;
|
||||
active:
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import React from 'react';
|
||||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
|
@ -20,7 +21,7 @@ const createProps = (): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/ConfirmDiscardDialog',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function Default(): JSX.Element {
|
||||
return <ConfirmDiscardDialog {...createProps()} />;
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
import * as React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { Props } from './ConfirmationDialog';
|
||||
import { ConfirmationDialog } from './ConfirmationDialog';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
@ -12,9 +14,9 @@ const i18n = setupI18n('en', enMessages);
|
|||
|
||||
export default {
|
||||
title: 'Components/ConfirmationDialog',
|
||||
};
|
||||
} satisfies Meta<Props>;
|
||||
|
||||
export const _ConfirmationDialog = (): JSX.Element => {
|
||||
export function Basic(): JSX.Element {
|
||||
return (
|
||||
<ConfirmationDialog
|
||||
dialogName="test"
|
||||
|
@ -37,11 +39,7 @@ export const _ConfirmationDialog = (): JSX.Element => {
|
|||
asdf blip
|
||||
</ConfirmationDialog>
|
||||
);
|
||||
};
|
||||
|
||||
_ConfirmationDialog.story = {
|
||||
name: 'ConfirmationDialog',
|
||||
};
|
||||
}
|
||||
|
||||
export function CustomCancelText(): JSX.Element {
|
||||
return (
|
||||
|
@ -64,10 +62,6 @@ export function CustomCancelText(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
CustomCancelText.story = {
|
||||
name: 'Custom cancel text',
|
||||
};
|
||||
|
||||
export function NoDefaultCancel(): JSX.Element {
|
||||
return (
|
||||
<ConfirmationDialog
|
||||
|
|
|
@ -6,6 +6,7 @@ import { times } from 'lodash';
|
|||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
import { ContactPills } from './ContactPills';
|
||||
|
@ -18,7 +19,7 @@ const i18n = setupI18n('en', enMessages);
|
|||
|
||||
export default {
|
||||
title: 'Components/Contact Pills',
|
||||
};
|
||||
} satisfies Meta<ContactPillPropsType>;
|
||||
|
||||
type ContactType = Omit<ContactPillPropsType, 'i18n' | 'onClickRemove'>;
|
||||
|
||||
|
@ -54,10 +55,6 @@ export function EmptyList(): JSX.Element {
|
|||
return <ContactPills />;
|
||||
}
|
||||
|
||||
EmptyList.story = {
|
||||
name: 'Empty list',
|
||||
};
|
||||
|
||||
export function OneContact(): JSX.Element {
|
||||
return (
|
||||
<ContactPills>
|
||||
|
@ -66,10 +63,6 @@ export function OneContact(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
OneContact.story = {
|
||||
name: 'One contact',
|
||||
};
|
||||
|
||||
export function ThreeContacts(): JSX.Element {
|
||||
return (
|
||||
<ContactPills>
|
||||
|
@ -80,10 +73,6 @@ export function ThreeContacts(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ThreeContacts.story = {
|
||||
name: 'Three contacts',
|
||||
};
|
||||
|
||||
export function FourContactsOneWithALongName(): JSX.Element {
|
||||
return (
|
||||
<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 {
|
||||
return (
|
||||
<ContactPills>
|
||||
|
@ -114,7 +99,3 @@ export function FiftyContacts(): JSX.Element {
|
|||
</ContactPills>
|
||||
);
|
||||
}
|
||||
|
||||
FiftyContacts.story = {
|
||||
name: 'Fifty contacts',
|
||||
};
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './ContextMenu';
|
||||
import { ContextMenu } from './ContextMenu';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
@ -13,7 +14,7 @@ const i18n = setupI18n('en', enMessages);
|
|||
|
||||
export default {
|
||||
title: 'Components/ContextMenu',
|
||||
};
|
||||
} satisfies Meta<PropsType<unknown>>;
|
||||
|
||||
const getDefaultProps = (): PropsType<number> => ({
|
||||
i18n,
|
||||
|
|
|
@ -4,11 +4,9 @@
|
|||
import React, { useContext } from 'react';
|
||||
import { times, omit } from 'lodash';
|
||||
import { v4 as generateUuid } from 'uuid';
|
||||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { boolean, date, select, text } from '@storybook/addon-knobs';
|
||||
|
||||
import type { Row } from './ConversationList';
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { Row, PropsType } from './ConversationList';
|
||||
import { ConversationList, RowType } from './ConversationList';
|
||||
import { MessageSearchResult } from './conversationList/MessageSearchResult';
|
||||
import type { PropsData as ConversationListItemPropsType } from './conversationList/ConversationListItem';
|
||||
|
@ -25,7 +23,9 @@ const i18n = setupI18n('en', enMessages);
|
|||
|
||||
export default {
|
||||
title: 'Components/ConversationList',
|
||||
};
|
||||
argTypes: {},
|
||||
args: {},
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
const defaultConversations: Array<ConversationListItemPropsType> = [
|
||||
getDefaultConversation({
|
||||
|
@ -105,15 +105,13 @@ function Wrapper({
|
|||
);
|
||||
}
|
||||
|
||||
export const _ArchiveButton = (): JSX.Element => (
|
||||
<Wrapper
|
||||
rows={[{ type: RowType.ArchiveButton, archivedConversationsCount: 123 }]}
|
||||
/>
|
||||
);
|
||||
|
||||
_ArchiveButton.story = {
|
||||
name: 'Archive button',
|
||||
};
|
||||
export function ArchiveButton(): JSX.Element {
|
||||
return (
|
||||
<Wrapper
|
||||
rows={[{ type: RowType.ArchiveButton, archivedConversationsCount: 123 }]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function ContactNoteToSelf(): JSX.Element {
|
||||
return (
|
||||
|
@ -132,10 +130,6 @@ export function ContactNoteToSelf(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ContactNoteToSelf.story = {
|
||||
name: 'Contact: note to self',
|
||||
};
|
||||
|
||||
export function ContactDirect(): JSX.Element {
|
||||
return (
|
||||
<Wrapper
|
||||
|
@ -144,10 +138,6 @@ export function ContactDirect(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ContactDirect.story = {
|
||||
name: 'Contact: direct',
|
||||
};
|
||||
|
||||
export function ContactDirectWithContextMenu(): JSX.Element {
|
||||
return (
|
||||
<Wrapper
|
||||
|
@ -162,10 +152,6 @@ export function ContactDirectWithContextMenu(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ContactDirectWithContextMenu.story = {
|
||||
name: 'Contact: context menu',
|
||||
};
|
||||
|
||||
export function ContactDirectWithShortAbout(): JSX.Element {
|
||||
return (
|
||||
<Wrapper
|
||||
|
@ -179,10 +165,6 @@ export function ContactDirectWithShortAbout(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ContactDirectWithShortAbout.story = {
|
||||
name: 'Contact: direct with short about',
|
||||
};
|
||||
|
||||
export function ContactDirectWithLongAbout(): JSX.Element {
|
||||
return (
|
||||
<Wrapper
|
||||
|
@ -200,10 +182,6 @@ export function ContactDirectWithLongAbout(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ContactDirectWithLongAbout.story = {
|
||||
name: 'Contact: direct with long about',
|
||||
};
|
||||
|
||||
export function ContactGroup(): JSX.Element {
|
||||
return (
|
||||
<Wrapper
|
||||
|
@ -217,10 +195,6 @@ export function ContactGroup(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ContactGroup.story = {
|
||||
name: 'Contact: group',
|
||||
};
|
||||
|
||||
export function ContactCheckboxes(): JSX.Element {
|
||||
return (
|
||||
<Wrapper
|
||||
|
@ -248,10 +222,6 @@ export function ContactCheckboxes(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ContactCheckboxes.story = {
|
||||
name: 'Contact checkboxes',
|
||||
};
|
||||
|
||||
export function ContactCheckboxesDisabled(): JSX.Element {
|
||||
return (
|
||||
<Wrapper
|
||||
|
@ -279,42 +249,29 @@ export function ContactCheckboxesDisabled(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ContactCheckboxesDisabled.story = {
|
||||
name: 'Contact checkboxes: disabled',
|
||||
};
|
||||
|
||||
const createConversation = (
|
||||
overrideProps: Partial<ConversationListItemPropsType> = {}
|
||||
): ConversationListItemPropsType => ({
|
||||
...overrideProps,
|
||||
acceptedMessageRequest: boolean(
|
||||
'acceptedMessageRequest',
|
||||
acceptedMessageRequest:
|
||||
overrideProps.acceptedMessageRequest !== undefined
|
||||
? overrideProps.acceptedMessageRequest
|
||||
: true
|
||||
),
|
||||
: true,
|
||||
badges: [],
|
||||
isMe: boolean('isMe', overrideProps.isMe || false),
|
||||
avatarPath: text('avatarPath', overrideProps.avatarPath || ''),
|
||||
isMe: overrideProps.isMe ?? false,
|
||||
avatarPath: overrideProps.avatarPath ?? '',
|
||||
id: overrideProps.id || '',
|
||||
isSelected: boolean('isSelected', overrideProps.isSelected || false),
|
||||
title: text('title', overrideProps.title || 'Some Person'),
|
||||
isSelected: overrideProps.isSelected ?? false,
|
||||
title: overrideProps.title ?? 'Some Person',
|
||||
profileName: overrideProps.profileName || 'Some Person',
|
||||
type: overrideProps.type || 'direct',
|
||||
markedUnread: boolean('markedUnread', overrideProps.markedUnread || false),
|
||||
markedUnread: overrideProps.markedUnread ?? false,
|
||||
lastMessage: overrideProps.lastMessage || {
|
||||
text: text('lastMessage.text', 'Hi there!'),
|
||||
status: select(
|
||||
'status',
|
||||
MessageStatuses.reduce((m, s) => ({ ...m, [s]: s }), {}),
|
||||
'read'
|
||||
),
|
||||
text: 'Hi there!',
|
||||
status: 'read',
|
||||
deletedForEveryone: false,
|
||||
},
|
||||
lastUpdated: date(
|
||||
'lastUpdated',
|
||||
new Date(overrideProps.lastUpdated || Date.now() - 5 * 60 * 1000)
|
||||
),
|
||||
lastUpdated: overrideProps.lastUpdated ?? Date.now() - 5 * 60 * 1000,
|
||||
sharedGroupNames: [],
|
||||
});
|
||||
|
||||
|
@ -333,19 +290,11 @@ const renderConversation = (
|
|||
|
||||
export const ConversationName = (): JSX.Element => renderConversation();
|
||||
|
||||
ConversationName.story = {
|
||||
name: 'Conversation: name',
|
||||
};
|
||||
|
||||
export const ConversationNameAndAvatar = (): JSX.Element =>
|
||||
renderConversation({
|
||||
avatarPath: '/fixtures/kitten-1-64-64.jpg',
|
||||
});
|
||||
|
||||
ConversationNameAndAvatar.story = {
|
||||
name: 'Conversation: name and avatar',
|
||||
};
|
||||
|
||||
export const ConversationWithYourself = (): JSX.Element =>
|
||||
renderConversation({
|
||||
lastMessage: {
|
||||
|
@ -358,10 +307,6 @@ export const ConversationWithYourself = (): JSX.Element =>
|
|||
isMe: true,
|
||||
});
|
||||
|
||||
ConversationWithYourself.story = {
|
||||
name: 'Conversation: with yourself',
|
||||
};
|
||||
|
||||
export function ConversationsMessageStatuses(): JSX.Element {
|
||||
return (
|
||||
<Wrapper
|
||||
|
@ -375,21 +320,13 @@ export function ConversationsMessageStatuses(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ConversationsMessageStatuses.story = {
|
||||
name: 'Conversations: Message Statuses',
|
||||
};
|
||||
|
||||
export const ConversationTypingStatus = (): JSX.Element =>
|
||||
renderConversation({
|
||||
typingContactIdTimestamps: {
|
||||
[generateUuid()]: date('timestamp', new Date()),
|
||||
[generateUuid()]: Date.now(),
|
||||
},
|
||||
});
|
||||
|
||||
ConversationTypingStatus.story = {
|
||||
name: 'Conversation: Typing Status',
|
||||
};
|
||||
|
||||
export const ConversationWithDraft = (): JSX.Element =>
|
||||
renderConversation({
|
||||
shouldShowDraft: true,
|
||||
|
@ -400,19 +337,11 @@ export const ConversationWithDraft = (): JSX.Element =>
|
|||
},
|
||||
});
|
||||
|
||||
ConversationWithDraft.story = {
|
||||
name: 'Conversation: With draft',
|
||||
};
|
||||
|
||||
export const ConversationDeletedForEveryone = (): JSX.Element =>
|
||||
renderConversation({
|
||||
lastMessage: { deletedForEveryone: true },
|
||||
});
|
||||
|
||||
ConversationDeletedForEveryone.story = {
|
||||
name: 'Conversation: Deleted for everyone',
|
||||
};
|
||||
|
||||
export const ConversationMessageRequest = (): JSX.Element =>
|
||||
renderConversation({
|
||||
acceptedMessageRequest: false,
|
||||
|
@ -423,10 +352,6 @@ export const ConversationMessageRequest = (): JSX.Element =>
|
|||
},
|
||||
});
|
||||
|
||||
ConversationMessageRequest.story = {
|
||||
name: 'Conversation: Message Request',
|
||||
};
|
||||
|
||||
export function ConversationsUnreadCount(): JSX.Element {
|
||||
return (
|
||||
<Wrapper
|
||||
|
@ -445,17 +370,9 @@ export function ConversationsUnreadCount(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ConversationsUnreadCount.story = {
|
||||
name: 'Conversations: unread count',
|
||||
};
|
||||
|
||||
export const ConversationMarkedUnread = (): JSX.Element =>
|
||||
renderConversation({ markedUnread: true });
|
||||
|
||||
ConversationMarkedUnread.story = {
|
||||
name: 'Conversation: marked unread',
|
||||
};
|
||||
|
||||
export const ConversationSelected = (): JSX.Element =>
|
||||
renderConversation({
|
||||
lastMessage: {
|
||||
|
@ -466,10 +383,6 @@ export const ConversationSelected = (): JSX.Element =>
|
|||
isSelected: true,
|
||||
});
|
||||
|
||||
ConversationSelected.story = {
|
||||
name: 'Conversation: Selected',
|
||||
};
|
||||
|
||||
export const ConversationEmojiInMessage = (): JSX.Element =>
|
||||
renderConversation({
|
||||
lastMessage: {
|
||||
|
@ -479,10 +392,6 @@ export const ConversationEmojiInMessage = (): JSX.Element =>
|
|||
},
|
||||
});
|
||||
|
||||
ConversationEmojiInMessage.story = {
|
||||
name: 'Conversation: Emoji in Message',
|
||||
};
|
||||
|
||||
export const ConversationLinkInMessage = (): JSX.Element =>
|
||||
renderConversation({
|
||||
lastMessage: {
|
||||
|
@ -492,10 +401,6 @@ export const ConversationLinkInMessage = (): JSX.Element =>
|
|||
},
|
||||
});
|
||||
|
||||
ConversationLinkInMessage.story = {
|
||||
name: 'Conversation: Link in Message',
|
||||
};
|
||||
|
||||
export const ConversationLongName = (): JSX.Element => {
|
||||
const name =
|
||||
'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 {
|
||||
const messages = [
|
||||
"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 {
|
||||
const pairs: Array<[number, string]> = [
|
||||
[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 {
|
||||
const row = {
|
||||
type: RowType.Conversation as const,
|
||||
|
@ -576,10 +469,6 @@ export function ConversationMissingDate(): JSX.Element {
|
|||
return <Wrapper rows={[row]} />;
|
||||
}
|
||||
|
||||
ConversationMissingDate.story = {
|
||||
name: 'Conversation: Missing Date',
|
||||
};
|
||||
|
||||
export function ConversationMissingMessage(): JSX.Element {
|
||||
const row = {
|
||||
type: RowType.Conversation as const,
|
||||
|
@ -589,10 +478,6 @@ export function ConversationMissingMessage(): JSX.Element {
|
|||
return <Wrapper rows={[row]} />;
|
||||
}
|
||||
|
||||
ConversationMissingMessage.story = {
|
||||
name: 'Conversation: Missing Message',
|
||||
};
|
||||
|
||||
export const ConversationMissingText = (): JSX.Element =>
|
||||
renderConversation({
|
||||
lastMessage: {
|
||||
|
@ -602,19 +487,11 @@ export const ConversationMissingText = (): JSX.Element =>
|
|||
},
|
||||
});
|
||||
|
||||
ConversationMissingText.story = {
|
||||
name: 'Conversation: Missing Text',
|
||||
};
|
||||
|
||||
export const ConversationMutedConversation = (): JSX.Element =>
|
||||
renderConversation({
|
||||
muteExpiresAt: Date.now() + 1000 * 60 * 60,
|
||||
});
|
||||
|
||||
ConversationMutedConversation.story = {
|
||||
name: 'Conversation: Muted Conversation',
|
||||
};
|
||||
|
||||
export const ConversationAtMention = (): JSX.Element =>
|
||||
renderConversation({
|
||||
title: 'The Rebellion',
|
||||
|
@ -626,10 +503,6 @@ export const ConversationAtMention = (): JSX.Element =>
|
|||
},
|
||||
});
|
||||
|
||||
ConversationAtMention.story = {
|
||||
name: 'Conversation: At Mention',
|
||||
};
|
||||
|
||||
export function Headers(): JSX.Element {
|
||||
return (
|
||||
<Wrapper
|
||||
|
@ -700,10 +573,6 @@ export function FindByPhoneNumber(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
FindByPhoneNumber.story = {
|
||||
name: 'Find by phone number',
|
||||
};
|
||||
|
||||
export function FindByUsername(): JSX.Element {
|
||||
return (
|
||||
<Wrapper
|
||||
|
@ -728,10 +597,6 @@ export function FindByUsername(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
FindByUsername.story = {
|
||||
name: 'Find by username',
|
||||
};
|
||||
|
||||
export function SearchResultsLoadingSkeleton(): JSX.Element {
|
||||
return (
|
||||
<Wrapper
|
||||
|
@ -746,10 +611,6 @@ export function SearchResultsLoadingSkeleton(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
SearchResultsLoadingSkeleton.story = {
|
||||
name: 'Search results loading skeleton',
|
||||
};
|
||||
|
||||
export function KitchenSink(): JSX.Element {
|
||||
return (
|
||||
<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 { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './CrashReportDialog';
|
||||
import { CrashReportDialog } from './CrashReportDialog';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import { sleep } from '../util/sleep';
|
||||
|
@ -11,11 +13,11 @@ import enMessages from '../../_locales/en/messages.json';
|
|||
|
||||
export default {
|
||||
title: 'Components/CrashReportDialog',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
export const _CrashReportDialog = (): JSX.Element => {
|
||||
export function Basic(): JSX.Element {
|
||||
const [isPending, setIsPending] = useState(false);
|
||||
|
||||
return (
|
||||
|
@ -31,8 +33,4 @@ export const _CrashReportDialog = (): JSX.Element => {
|
|||
eraseCrashReports={action('eraseCrashReports')}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
_CrashReportDialog.story = {
|
||||
name: 'CrashReportDialog',
|
||||
};
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ type PropsActionsType = {
|
|||
eraseCrashReports: () => void;
|
||||
};
|
||||
|
||||
type PropsType = {
|
||||
export type PropsType = {
|
||||
i18n: LocalizerType;
|
||||
isPending: boolean;
|
||||
} & PropsActionsType;
|
||||
|
|
|
@ -5,6 +5,7 @@ import React from 'react';
|
|||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
import type { PropsType } from './CustomColorEditor';
|
||||
import { CustomColorEditor } from './CustomColorEditor';
|
||||
|
@ -12,7 +13,7 @@ import { setupI18n } from '../util/setupI18n';
|
|||
|
||||
export default {
|
||||
title: 'Components/CustomColorEditor',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
|
|
|
@ -5,16 +5,18 @@ import type { ComponentProps } from 'react';
|
|||
import React from 'react';
|
||||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
import type { PropsType } from './CustomizingPreferredReactionsModal';
|
||||
import { CustomizingPreferredReactionsModal } from './CustomizingPreferredReactionsModal';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
export default {
|
||||
title: 'Components/CustomizingPreferredReactionsModal',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
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 {
|
||||
return <CustomizingPreferredReactionsModal {...defaultProps} isSaving />;
|
||||
}
|
||||
|
@ -61,7 +59,3 @@ export function Saving(): JSX.Element {
|
|||
export function HadError(): JSX.Element {
|
||||
return <CustomizingPreferredReactionsModal {...defaultProps} hadSaveError />;
|
||||
}
|
||||
|
||||
HadError.story = {
|
||||
name: 'Had error',
|
||||
};
|
||||
|
|
|
@ -19,7 +19,7 @@ import { convertShortName } from './emoji/lib';
|
|||
import { offsetDistanceModifier } from '../util/popperUtil';
|
||||
import { handleOutsideClick } from '../util/handleOutsideClick';
|
||||
|
||||
type PropsType = {
|
||||
export type PropsType = {
|
||||
draftPreferredReactions: ReadonlyArray<string>;
|
||||
hadSaveError: boolean;
|
||||
i18n: LocalizerType;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
import type { PropsType } from './DebugLogWindow';
|
||||
import { DebugLogWindow } from './DebugLogWindow';
|
||||
|
@ -31,12 +32,8 @@ const createProps = (): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/DebugLogWindow',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export const _DebugLogWindow = (): JSX.Element => (
|
||||
<DebugLogWindow {...createProps()} />
|
||||
);
|
||||
|
||||
_DebugLogWindow.story = {
|
||||
name: 'DebugLogWindow',
|
||||
};
|
||||
export function Basic(): JSX.Element {
|
||||
return <DebugLogWindow {...createProps()} />;
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
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 { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
@ -14,14 +14,12 @@ const i18n = setupI18n('en', enMessages);
|
|||
|
||||
export default {
|
||||
title: 'Components/DialogExpiredBuild',
|
||||
};
|
||||
argTypes: {},
|
||||
args: {},
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export const _DialogExpiredBuild = (): JSX.Element => {
|
||||
const containerWidthBreakpoint = select(
|
||||
'containerWidthBreakpoint',
|
||||
WidthBreakpoint,
|
||||
WidthBreakpoint.Wide
|
||||
);
|
||||
export function Basic(): JSX.Element {
|
||||
const containerWidthBreakpoint = WidthBreakpoint.Wide;
|
||||
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={containerWidthBreakpoint}>
|
||||
|
@ -31,8 +29,4 @@ export const _DialogExpiredBuild = (): JSX.Element => {
|
|||
/>
|
||||
</FakeLeftPaneContainer>
|
||||
);
|
||||
};
|
||||
|
||||
_DialogExpiredBuild.story = {
|
||||
name: 'DialogExpiredBuild',
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import * as React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './DialogNetworkStatus';
|
||||
import { DialogNetworkStatus } from './DialogNetworkStatus';
|
||||
import { SocketStatus } from '../types/SocketStatus';
|
||||
|
@ -27,7 +28,7 @@ const defaultProps = {
|
|||
|
||||
export default {
|
||||
title: 'Components/DialogNetworkStatus',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
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 {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||
|
@ -84,10 +81,6 @@ export function ClosingWide(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ClosingWide.story = {
|
||||
name: 'Closing Wide',
|
||||
};
|
||||
|
||||
export function ClosedWide(): JSX.Element {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||
|
@ -100,10 +93,6 @@ export function ClosedWide(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ClosedWide.story = {
|
||||
name: 'Closed Wide',
|
||||
};
|
||||
|
||||
export function OfflineWide(): JSX.Element {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||
|
@ -116,10 +105,6 @@ export function OfflineWide(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
OfflineWide.story = {
|
||||
name: 'Offline Wide',
|
||||
};
|
||||
|
||||
export function ConnectingNarrow(): JSX.Element {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||
|
@ -132,10 +117,6 @@ export function ConnectingNarrow(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ConnectingNarrow.story = {
|
||||
name: 'Connecting Narrow',
|
||||
};
|
||||
|
||||
export function ClosingNarrow(): JSX.Element {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||
|
@ -148,10 +129,6 @@ export function ClosingNarrow(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ClosingNarrow.story = {
|
||||
name: 'Closing Narrow',
|
||||
};
|
||||
|
||||
export function ClosedNarrow(): JSX.Element {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||
|
@ -164,10 +141,6 @@ export function ClosedNarrow(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ClosedNarrow.story = {
|
||||
name: 'Closed Narrow',
|
||||
};
|
||||
|
||||
export function OfflineNarrow(): JSX.Element {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||
|
@ -179,7 +152,3 @@ export function OfflineNarrow(): JSX.Element {
|
|||
</FakeLeftPaneContainer>
|
||||
);
|
||||
}
|
||||
|
||||
OfflineNarrow.story = {
|
||||
name: 'Offline Narrow',
|
||||
};
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
import * as React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './DialogRelink';
|
||||
import { DialogRelink } from './DialogRelink';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
@ -35,7 +36,7 @@ const permutations = [
|
|||
|
||||
export default {
|
||||
title: 'Components/DialogRelink',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function Iterations(): JSX.Element {
|
||||
return (
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
import { select } from '@storybook/addon-knobs';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './DialogUpdate';
|
||||
import { DialogUpdate } from './DialogUpdate';
|
||||
import { DialogType } from '../types/Dialogs';
|
||||
import { WidthBreakpoint } from './_util';
|
||||
|
@ -29,15 +30,13 @@ const defaultProps = {
|
|||
|
||||
export default {
|
||||
title: 'Components/DialogUpdate',
|
||||
};
|
||||
argTypes: {},
|
||||
args: {},
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function KnobsPlayground(): JSX.Element {
|
||||
const containerWidthBreakpoint = select(
|
||||
'containerWidthBreakpoint',
|
||||
WidthBreakpoint,
|
||||
WidthBreakpoint.Wide
|
||||
);
|
||||
const dialogType = select('dialogType', DialogType, DialogType.AutoUpdate);
|
||||
const containerWidthBreakpoint = WidthBreakpoint.Wide;
|
||||
const dialogType = DialogType.AutoUpdate;
|
||||
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={containerWidthBreakpoint}>
|
||||
|
@ -64,10 +63,6 @@ export function UpdateWide(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
UpdateWide.story = {
|
||||
name: 'Update (Wide)',
|
||||
};
|
||||
|
||||
export function DownloadedWide(): JSX.Element {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||
|
@ -81,10 +76,6 @@ export function DownloadedWide(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
DownloadedWide.story = {
|
||||
name: 'Downloaded (Wide)',
|
||||
};
|
||||
|
||||
export function DownloadReadyWide(): JSX.Element {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||
|
@ -99,10 +90,6 @@ export function DownloadReadyWide(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
DownloadReadyWide.story = {
|
||||
name: 'DownloadReady (Wide)',
|
||||
};
|
||||
|
||||
export function FullDownloadReadyWide(): JSX.Element {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||
|
@ -117,10 +104,6 @@ export function FullDownloadReadyWide(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
FullDownloadReadyWide.story = {
|
||||
name: 'FullDownloadReady (Wide)',
|
||||
};
|
||||
|
||||
export function DownloadingWide(): JSX.Element {
|
||||
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 {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||
|
@ -170,10 +149,6 @@ export function CannotUpdateWide(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
CannotUpdateWide.story = {
|
||||
name: 'Cannot_Update (Wide)',
|
||||
};
|
||||
|
||||
export function CannotUpdateBetaWide(): JSX.Element {
|
||||
return (
|
||||
<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 {
|
||||
return (
|
||||
<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 {
|
||||
return (
|
||||
<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 {
|
||||
return (
|
||||
<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 {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Wide}>
|
||||
|
@ -255,10 +214,6 @@ export function UnsupportedOSWide(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
UnsupportedOSWide.story = {
|
||||
name: 'UnsupportedOS (Wide)',
|
||||
};
|
||||
|
||||
export function UpdateNarrow(): JSX.Element {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||
|
@ -272,10 +227,6 @@ export function UpdateNarrow(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
UpdateNarrow.story = {
|
||||
name: 'Update (Narrow)',
|
||||
};
|
||||
|
||||
export function DownloadedNarrow(): JSX.Element {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||
|
@ -289,10 +240,6 @@ export function DownloadedNarrow(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
DownloadedNarrow.story = {
|
||||
name: 'Downloaded (Narrow)',
|
||||
};
|
||||
|
||||
export function DownloadReadyNarrow(): JSX.Element {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||
|
@ -307,10 +254,6 @@ export function DownloadReadyNarrow(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
DownloadReadyNarrow.story = {
|
||||
name: 'DownloadReady (Narrow)',
|
||||
};
|
||||
|
||||
export function FullDownloadReadyNarrow(): JSX.Element {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||
|
@ -325,10 +268,6 @@ export function FullDownloadReadyNarrow(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
FullDownloadReadyNarrow.story = {
|
||||
name: 'FullDownloadReady (Narrow)',
|
||||
};
|
||||
|
||||
export function DownloadingNarrow(): JSX.Element {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||
|
@ -342,10 +281,6 @@ export function DownloadingNarrow(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
DownloadingNarrow.story = {
|
||||
name: 'Downloading (Narrow)',
|
||||
};
|
||||
|
||||
export function CannotUpdateNarrow(): JSX.Element {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||
|
@ -359,10 +294,6 @@ export function CannotUpdateNarrow(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
CannotUpdateNarrow.story = {
|
||||
name: 'Cannot Update (Narrow)',
|
||||
};
|
||||
|
||||
export function CannotUpdateBetaNarrow(): JSX.Element {
|
||||
return (
|
||||
<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 {
|
||||
return (
|
||||
<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 {
|
||||
return (
|
||||
<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 {
|
||||
return (
|
||||
<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 {
|
||||
return (
|
||||
<FakeLeftPaneContainer containerWidthBreakpoint={WidthBreakpoint.Narrow}>
|
||||
|
@ -443,7 +358,3 @@ export function UnsupportedOSNarrow(): JSX.Element {
|
|||
</FakeLeftPaneContainer>
|
||||
);
|
||||
}
|
||||
|
||||
UnsupportedOSNarrow.story = {
|
||||
name: 'UnsupportedOS (Narrow)',
|
||||
};
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
import React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './DisappearingTimeDialog';
|
||||
import { DisappearingTimeDialog } from './DisappearingTimeDialog';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
@ -12,7 +13,7 @@ import { EXPIRE_TIMERS } from '../test-both/util/expireTimers';
|
|||
|
||||
export default {
|
||||
title: 'Components/DisappearingTimeDialog',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { Props } from './DisappearingTimerSelect';
|
||||
import { DisappearingTimerSelect } from './DisappearingTimerSelect';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import { DurationInSeconds } from '../util/durations';
|
||||
|
@ -10,15 +11,15 @@ import enMessages from '../../_locales/en/messages.json';
|
|||
|
||||
export default {
|
||||
title: 'Components/DisappearingTimerSelect',
|
||||
};
|
||||
} satisfies Meta<Props>;
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
type Props = {
|
||||
type Args = {
|
||||
initialValue: number;
|
||||
};
|
||||
|
||||
function TimerSelectWrap({ initialValue }: Props): JSX.Element {
|
||||
function TimerSelectWrap({ initialValue }: Args): JSX.Element {
|
||||
const [value, setValue] = useState(initialValue);
|
||||
|
||||
return (
|
||||
|
@ -34,14 +35,6 @@ export function InitialValue1Day(): JSX.Element {
|
|||
return <TimerSelectWrap initialValue={24 * 3600} />;
|
||||
}
|
||||
|
||||
InitialValue1Day.story = {
|
||||
name: 'Initial value: 1 day',
|
||||
};
|
||||
|
||||
export function InitialValue3DaysCustomTime(): JSX.Element {
|
||||
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
|
||||
|
||||
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 { setupI18n } from '../util/setupI18n';
|
||||
import type { UsernameReservationType } from '../types/Username';
|
||||
|
@ -29,11 +30,9 @@ export default {
|
|||
argTypes: {
|
||||
currentUsername: {
|
||||
type: { name: 'string', required: false },
|
||||
defaultValue: undefined,
|
||||
},
|
||||
state: {
|
||||
control: { type: 'radio' },
|
||||
defaultValue: State.Open,
|
||||
options: {
|
||||
Open: State.Open,
|
||||
Closed: State.Closed,
|
||||
|
@ -43,7 +42,6 @@ export default {
|
|||
},
|
||||
error: {
|
||||
control: { type: 'radio' },
|
||||
defaultValue: undefined,
|
||||
options: {
|
||||
None: undefined,
|
||||
NotEnoughCharacters: UsernameReservationError.NotEnoughCharacters,
|
||||
|
@ -54,26 +52,24 @@ export default {
|
|||
General: UsernameReservationError.General,
|
||||
},
|
||||
},
|
||||
maxUsername: {
|
||||
defaultValue: 20,
|
||||
},
|
||||
minUsername: {
|
||||
defaultValue: 3,
|
||||
},
|
||||
discriminator: {
|
||||
reservation: {
|
||||
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 & {
|
||||
discriminator?: string;
|
||||
|
@ -81,7 +77,7 @@ type ArgsType = PropsType & {
|
|||
};
|
||||
|
||||
// eslint-disable-next-line react/function-component-definition
|
||||
const Template: Story<ArgsType> = args => {
|
||||
const Template: StoryFn<ArgsType> = args => {
|
||||
let { reservation } = args;
|
||||
if (!reservation && args.discriminator) {
|
||||
reservation = {
|
||||
|
@ -95,27 +91,16 @@ const Template: Story<ArgsType> = args => {
|
|||
|
||||
export const WithoutUsername = Template.bind({});
|
||||
WithoutUsername.args = {};
|
||||
WithoutUsername.story = {
|
||||
name: 'without current username',
|
||||
};
|
||||
|
||||
export const WithUsername = Template.bind({});
|
||||
WithUsername.args = {};
|
||||
WithUsername.story = {
|
||||
name: 'with current username',
|
||||
args: {
|
||||
currentUsername: 'signaluser.12',
|
||||
},
|
||||
WithUsername.args = {
|
||||
currentUsername: 'signaluser.12',
|
||||
};
|
||||
|
||||
export const WithReservation = Template.bind({});
|
||||
WithReservation.args = {};
|
||||
WithReservation.story = {
|
||||
name: 'with reservation',
|
||||
args: {
|
||||
currentUsername: 'reserved',
|
||||
reservation: DEFAULT_RESERVATION,
|
||||
},
|
||||
WithReservation.args = {
|
||||
currentUsername: 'reserved',
|
||||
reservation: DEFAULT_RESERVATION,
|
||||
};
|
||||
|
||||
export const UsernameEditingConfirming = Template.bind({});
|
||||
|
@ -123,9 +108,6 @@ UsernameEditingConfirming.args = {
|
|||
state: State.Confirming,
|
||||
currentUsername: 'signaluser.12',
|
||||
};
|
||||
UsernameEditingConfirming.story = {
|
||||
name: 'Username editing, Confirming',
|
||||
};
|
||||
|
||||
export const UsernameEditingUsernameTaken = Template.bind({});
|
||||
UsernameEditingUsernameTaken.args = {
|
||||
|
@ -133,9 +115,6 @@ UsernameEditingUsernameTaken.args = {
|
|||
error: UsernameReservationError.UsernameNotAvailable,
|
||||
currentUsername: 'signaluser.12',
|
||||
};
|
||||
UsernameEditingUsernameTaken.story = {
|
||||
name: 'Username editing, username taken',
|
||||
};
|
||||
|
||||
export const UsernameEditingUsernameWrongCharacters = Template.bind({});
|
||||
UsernameEditingUsernameWrongCharacters.args = {
|
||||
|
@ -143,9 +122,6 @@ UsernameEditingUsernameWrongCharacters.args = {
|
|||
error: UsernameReservationError.CheckCharacters,
|
||||
currentUsername: 'signaluser.12',
|
||||
};
|
||||
UsernameEditingUsernameWrongCharacters.story = {
|
||||
name: 'Username editing, Wrong Characters',
|
||||
};
|
||||
|
||||
export const UsernameEditingUsernameTooShort = Template.bind({});
|
||||
UsernameEditingUsernameTooShort.args = {
|
||||
|
@ -153,9 +129,6 @@ UsernameEditingUsernameTooShort.args = {
|
|||
error: UsernameReservationError.NotEnoughCharacters,
|
||||
currentUsername: 'sig',
|
||||
};
|
||||
UsernameEditingUsernameTooShort.story = {
|
||||
name: 'Username editing, username too short',
|
||||
};
|
||||
|
||||
export const UsernameEditingGeneralError = Template.bind({});
|
||||
UsernameEditingGeneralError.args = {
|
||||
|
@ -163,6 +136,3 @@ UsernameEditingGeneralError.args = {
|
|||
error: UsernameReservationError.General,
|
||||
currentUsername: 'signaluser.12',
|
||||
};
|
||||
UsernameEditingGeneralError.story = {
|
||||
name: 'Username editing, general error',
|
||||
};
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
import { text } from '@storybook/addon-knobs';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './ErrorModal';
|
||||
import { ErrorModal } from './ErrorModal';
|
||||
|
||||
|
@ -14,15 +14,17 @@ import enMessages from '../../_locales/en/messages.json';
|
|||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||
title: text('title', overrideProps.title || ''),
|
||||
description: text('description', overrideProps.description || ''),
|
||||
title: overrideProps.title ?? '',
|
||||
description: overrideProps.description ?? '',
|
||||
i18n,
|
||||
onClose: action('onClick'),
|
||||
});
|
||||
|
||||
export default {
|
||||
title: 'Components/ErrorModal',
|
||||
};
|
||||
argTypes: {},
|
||||
args: {},
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function Normal(): JSX.Element {
|
||||
return <ErrorModal {...createProps()} />;
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
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 type { AttachmentType } from '../types/Attachment';
|
||||
import type { PropsType } from './ForwardMessagesModal';
|
||||
|
@ -15,25 +13,25 @@ import { getDefaultConversation } from '../test-both/helpers/getDefaultConversat
|
|||
import { setupI18n } from '../util/setupI18n';
|
||||
import { StorybookThemeContext } from '../../.storybook/StorybookThemeContext';
|
||||
import { CompositionTextArea } from './CompositionTextArea';
|
||||
import type { MessageForwardDraft } from '../util/maybeForwardMessages';
|
||||
import type { MessageForwardDraft } from '../types/ForwardDraft';
|
||||
|
||||
const createAttachment = (
|
||||
props: Partial<AttachmentType> = {}
|
||||
): AttachmentType => ({
|
||||
pending: false,
|
||||
path: 'fileName.jpg',
|
||||
contentType: stringToMIMEType(
|
||||
text('attachment contentType', props.contentType || '')
|
||||
),
|
||||
fileName: text('attachment fileName', props.fileName || ''),
|
||||
contentType: stringToMIMEType(props.contentType ?? ''),
|
||||
fileName: props.fileName ?? '',
|
||||
screenshotPath: props.pending === false ? props.screenshotPath : undefined,
|
||||
url: text('attachment url', props.pending === false ? props.url || '' : ''),
|
||||
url: props.pending === false ? props.url ?? '' : '',
|
||||
size: 3433,
|
||||
});
|
||||
|
||||
export default {
|
||||
title: 'Components/ForwardMessageModal',
|
||||
};
|
||||
argTypes: {},
|
||||
args: {},
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
|
@ -82,7 +80,7 @@ function getMessageForwardDraft(
|
|||
attachments: overrideProps.attachments,
|
||||
hasContact: Boolean(overrideProps.hasContact),
|
||||
isSticker: Boolean(overrideProps.isSticker),
|
||||
messageBody: text('messageBody', overrideProps.messageBody || ''),
|
||||
messageBody: overrideProps.messageBody ?? '',
|
||||
originalMessageId: '123',
|
||||
previews: overrideProps.previews ?? [],
|
||||
};
|
||||
|
@ -102,10 +100,6 @@ export function WithText(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
WithText.story = {
|
||||
name: 'with text',
|
||||
};
|
||||
|
||||
export function ASticker(): JSX.Element {
|
||||
return (
|
||||
<ForwardMessagesModal
|
||||
|
@ -116,10 +110,6 @@ export function ASticker(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ASticker.story = {
|
||||
name: 'a sticker',
|
||||
};
|
||||
|
||||
export function WithAContact(): JSX.Element {
|
||||
return (
|
||||
<ForwardMessagesModal
|
||||
|
@ -130,10 +120,6 @@ export function WithAContact(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
WithAContact.story = {
|
||||
name: 'with a contact',
|
||||
};
|
||||
|
||||
export function LinkPreview(): JSX.Element {
|
||||
return (
|
||||
<ForwardMessagesModal
|
||||
|
@ -162,10 +148,6 @@ export function LinkPreview(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
LinkPreview.story = {
|
||||
name: 'link preview',
|
||||
};
|
||||
|
||||
export function MediaAttachments(): JSX.Element {
|
||||
return (
|
||||
<ForwardMessagesModal
|
||||
|
@ -196,10 +178,6 @@ export function MediaAttachments(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
MediaAttachments.story = {
|
||||
name: 'media attachments',
|
||||
};
|
||||
|
||||
export function AnnouncementOnlyGroupsNonAdmin(): JSX.Element {
|
||||
return (
|
||||
<ForwardMessagesModal
|
||||
|
@ -213,7 +191,3 @@ export function AnnouncementOnlyGroupsNonAdmin(): JSX.Element {
|
|||
/>
|
||||
);
|
||||
}
|
||||
|
||||
AnnouncementOnlyGroupsNonAdmin.story = {
|
||||
name: 'announcement only groups non-admin',
|
||||
};
|
||||
|
|
|
@ -27,11 +27,6 @@ import {
|
|||
shouldNeverBeCalled,
|
||||
asyncShouldNeverBeCalled,
|
||||
} from '../util/shouldNeverBeCalled';
|
||||
import type { MessageForwardDraft } from '../util/maybeForwardMessages';
|
||||
import {
|
||||
isDraftEditable,
|
||||
isDraftForwardable,
|
||||
} from '../util/maybeForwardMessages';
|
||||
import type { LinkPreviewType } from '../types/message/LinkPreviews';
|
||||
import { LinkPreviewSourceType } from '../types/LinkPreview';
|
||||
import { ToastType } from '../types/Toast';
|
||||
|
@ -41,6 +36,11 @@ import { BodyRange } from '../types/BodyRange';
|
|||
import { UserText } from './UserText';
|
||||
import { Modal } from './Modal';
|
||||
import { SizeObserver } from '../hooks/useSizeObserver';
|
||||
import {
|
||||
isDraftEditable,
|
||||
isDraftForwardable,
|
||||
type MessageForwardDraft,
|
||||
} from '../types/ForwardDraft';
|
||||
|
||||
export type DataPropsType = {
|
||||
candidateConversations: ReadonlyArray<ConversationType>;
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
import React from 'react';
|
||||
import { memoize, times } from 'lodash';
|
||||
import { number } from '@storybook/addon-knobs';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './GroupCallOverflowArea';
|
||||
import { GroupCallOverflowArea } from './GroupCallOverflowArea';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import { getDefaultConversationWithServiceId } from '../test-both/helpers/getDefaultConversation';
|
||||
|
@ -34,7 +34,9 @@ const allRemoteParticipants = times(MAX_PARTICIPANTS).map(index => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/GroupCallOverflowArea',
|
||||
};
|
||||
argTypes: {},
|
||||
args: {},
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
const defaultProps = {
|
||||
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 {
|
||||
return (
|
||||
<Container>
|
||||
|
@ -83,10 +81,6 @@ export function OneOverflowedParticipant(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
OneOverflowedParticipant.story = {
|
||||
name: 'One overflowed participant',
|
||||
};
|
||||
|
||||
export function ThreeOverflowedParticipants(): JSX.Element {
|
||||
return (
|
||||
<Container>
|
||||
|
@ -98,10 +92,6 @@ export function ThreeOverflowedParticipants(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ThreeOverflowedParticipants.story = {
|
||||
name: 'Three overflowed participants',
|
||||
};
|
||||
|
||||
export function ManyOverflowedParticipants(): JSX.Element {
|
||||
return (
|
||||
<Container>
|
||||
|
@ -109,18 +99,9 @@ export function ManyOverflowedParticipants(): JSX.Element {
|
|||
{...defaultProps}
|
||||
overflowedParticipants={allRemoteParticipants.slice(
|
||||
0,
|
||||
number('Participant count', MAX_PARTICIPANTS, {
|
||||
range: true,
|
||||
min: 0,
|
||||
max: MAX_PARTICIPANTS,
|
||||
step: 1,
|
||||
})
|
||||
MAX_PARTICIPANTS
|
||||
)}
|
||||
/>
|
||||
</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.
|
||||
export const OVERFLOW_PARTICIPANT_WIDTH = 140;
|
||||
|
||||
type PropsType = {
|
||||
export type PropsType = {
|
||||
getFrameBuffer: () => Buffer;
|
||||
getGroupCallVideoFrameSource: (demuxId: number) => VideoFrameSource;
|
||||
i18n: LocalizerType;
|
||||
|
|
|
@ -2,9 +2,8 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
import { memoize, noop } from 'lodash';
|
||||
import { select } from '@storybook/addon-knobs';
|
||||
|
||||
import { memoize } from 'lodash';
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './GroupCallRemoteParticipant';
|
||||
import { GroupCallRemoteParticipant } from './GroupCallRemoteParticipant';
|
||||
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
|
||||
|
@ -46,8 +45,9 @@ const createProps = (
|
|||
} = {}
|
||||
): PropsType => ({
|
||||
getFrameBuffer,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
getGroupCallVideoFrameSource: noop as any,
|
||||
getGroupCallVideoFrameSource: () => {
|
||||
return { receiveVideoFrame: () => undefined };
|
||||
},
|
||||
i18n,
|
||||
audioLevel: 0,
|
||||
remoteParticipant: {
|
||||
|
@ -72,7 +72,9 @@ const createProps = (
|
|||
|
||||
export default {
|
||||
title: 'Components/GroupCallRemoteParticipant',
|
||||
};
|
||||
argTypes: {},
|
||||
args: {},
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function Default(): JSX.Element {
|
||||
return (
|
||||
|
@ -101,7 +103,7 @@ export function Speaking(): JSX.Element {
|
|||
left: (120 + 10) * index,
|
||||
top: 0,
|
||||
width: 120,
|
||||
audioLevel: select('audioLevel', [0, 0.5, 1], 0.5),
|
||||
audioLevel: 0.5,
|
||||
remoteParticipantsCount,
|
||||
},
|
||||
{ hasRemoteAudio: true, presenting }
|
||||
|
@ -126,10 +128,6 @@ export function IsInPip(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
IsInPip.story = {
|
||||
name: 'isInPip',
|
||||
};
|
||||
|
||||
export function Blocked(): JSX.Element {
|
||||
return (
|
||||
<GroupCallRemoteParticipant
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
import type { PropsType } from './GroupDescriptionInput';
|
||||
import { GroupDescriptionInput } from './GroupDescriptionInput';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
export default {
|
||||
title: 'Components/GroupDescriptionInput',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
function Wrapper({
|
||||
disabled,
|
||||
|
|
|
@ -6,7 +6,7 @@ import React, { forwardRef } from 'react';
|
|||
import { Input } from './Input';
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
|
||||
type PropsType = {
|
||||
export type PropsType = {
|
||||
disabled?: boolean;
|
||||
i18n: LocalizerType;
|
||||
onChangeValue: (value: string) => void;
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
import type { PropsType } from './GroupTitleInput';
|
||||
import { GroupTitleInput } from './GroupTitleInput';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
export default {
|
||||
title: 'Components/GroupTitleInput',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
function Wrapper({
|
||||
disabled,
|
||||
|
|
|
@ -6,7 +6,7 @@ import React, { forwardRef } from 'react';
|
|||
import { Input } from './Input';
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
|
||||
type PropsType = {
|
||||
export type PropsType = {
|
||||
disabled?: boolean;
|
||||
i18n: LocalizerType;
|
||||
onChangeValue: (value: string) => void;
|
||||
|
|
|
@ -5,6 +5,7 @@ import * as React from 'react';
|
|||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './GroupV1MigrationDialog';
|
||||
import { GroupV1MigrationDialog } from './GroupV1MigrationDialog';
|
||||
import type { ConversationType } from '../state/ducks/conversations';
|
||||
|
@ -48,16 +49,12 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/GroupV1MigrationDialog',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function NotYetMigratedBasic(): JSX.Element {
|
||||
return <GroupV1MigrationDialog {...createProps()} />;
|
||||
}
|
||||
|
||||
NotYetMigratedBasic.story = {
|
||||
name: 'Not yet migrated, basic',
|
||||
};
|
||||
|
||||
export function MigratedBasic(): JSX.Element {
|
||||
return (
|
||||
<GroupV1MigrationDialog
|
||||
|
@ -68,10 +65,6 @@ export function MigratedBasic(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
MigratedBasic.story = {
|
||||
name: 'Migrated, basic',
|
||||
};
|
||||
|
||||
export function MigratedYouAreInvited(): JSX.Element {
|
||||
return (
|
||||
<GroupV1MigrationDialog
|
||||
|
@ -83,10 +76,6 @@ export function MigratedYouAreInvited(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
MigratedYouAreInvited.story = {
|
||||
name: 'Migrated, you are invited',
|
||||
};
|
||||
|
||||
export function NotYetMigratedMultipleDroppedAndInvitedMembers(): JSX.Element {
|
||||
return (
|
||||
<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 {
|
||||
return (
|
||||
<GroupV1MigrationDialog
|
||||
|
@ -113,10 +98,6 @@ export function NotYetMigratedNoMembers(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
NotYetMigratedNoMembers.story = {
|
||||
name: 'Not yet migrated, no members',
|
||||
};
|
||||
|
||||
export function NotYetMigratedJustDroppedMember(): JSX.Element {
|
||||
return (
|
||||
<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
|
||||
|
||||
import * as React from 'react';
|
||||
import { boolean, number, text } from '@storybook/addon-knobs';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import type { PropsType } from './GroupV2JoinDialog';
|
||||
import { GroupV2JoinDialog } from './GroupV2JoinDialog';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
|
@ -13,13 +12,10 @@ import enMessages from '../../_locales/en/messages.json';
|
|||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||
memberCount: number('memberCount', overrideProps.memberCount || 12),
|
||||
memberCount: overrideProps.memberCount ?? 12,
|
||||
avatar: overrideProps.avatar,
|
||||
title: text('title', overrideProps.title || 'Random Group!'),
|
||||
approvalRequired: boolean(
|
||||
'approvalRequired',
|
||||
overrideProps.approvalRequired || false
|
||||
),
|
||||
title: overrideProps.title ?? 'Random Group!',
|
||||
approvalRequired: overrideProps.approvalRequired ?? false,
|
||||
groupDescription: overrideProps.groupDescription,
|
||||
join: action('join'),
|
||||
onClose: action('onClose'),
|
||||
|
@ -28,7 +24,9 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|||
|
||||
export default {
|
||||
title: 'Components/GroupV2JoinDialog',
|
||||
};
|
||||
argTypes: {},
|
||||
args: {},
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function Basic(): JSX.Element {
|
||||
return <GroupV2JoinDialog {...createProps()} />;
|
||||
|
@ -45,10 +43,6 @@ export function ApprovalRequired(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
ApprovalRequired.story = {
|
||||
name: 'Approval required',
|
||||
};
|
||||
|
||||
export function WithAvatar(): JSX.Element {
|
||||
return (
|
||||
<GroupV2JoinDialog
|
||||
|
@ -62,10 +56,6 @@ export function WithAvatar(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
WithAvatar.story = {
|
||||
name: 'With avatar',
|
||||
};
|
||||
|
||||
export function WithOneMember(): JSX.Element {
|
||||
return (
|
||||
<GroupV2JoinDialog
|
||||
|
@ -77,10 +67,6 @@ export function WithOneMember(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
WithOneMember.story = {
|
||||
name: 'With one member',
|
||||
};
|
||||
|
||||
export function AvatarLoadingState(): JSX.Element {
|
||||
return (
|
||||
<GroupV2JoinDialog
|
||||
|
@ -94,10 +80,6 @@ export function AvatarLoadingState(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
AvatarLoadingState.story = {
|
||||
name: 'Avatar loading state',
|
||||
};
|
||||
|
||||
export function Full(): JSX.Element {
|
||||
return (
|
||||
<GroupV2JoinDialog
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { IdenticonSVGForContact, IdenticonSVGForGroup } from './IdenticonSVG';
|
||||
import { AvatarColorMap } from '../types/Colors';
|
||||
|
||||
export default {
|
||||
title: 'Components/IdenticonSVG',
|
||||
};
|
||||
} satisfies Meta;
|
||||
|
||||
export function AllColorsForContact(): JSX.Element {
|
||||
const stories: Array<JSX.Element> = [];
|
||||
|
|
|
@ -2,16 +2,17 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
import type { PropsType } from './InContactsIcon';
|
||||
import { InContactsIcon } from './InContactsIcon';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
export default {
|
||||
title: 'Components/InContactsIcon',
|
||||
};
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
export function Default(): JSX.Element {
|
||||
return <InContactsIcon i18n={i18n} />;
|
||||
|
|
|
@ -7,7 +7,7 @@ import classNames from 'classnames';
|
|||
import { Tooltip } from './Tooltip';
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
|
||||
type PropsType = {
|
||||
export type PropsType = {
|
||||
className?: string;
|
||||
tooltipContainerRef?: React.RefObject<HTMLElement>;
|
||||
i18n: LocalizerType;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
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 { Inbox } from './Inbox';
|
||||
|
@ -16,41 +16,15 @@ const i18n = setupI18n('en', enMessages);
|
|||
|
||||
export default {
|
||||
title: 'Components/Inbox',
|
||||
argTypes: {
|
||||
i18n: {
|
||||
defaultValue: i18n,
|
||||
},
|
||||
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,
|
||||
},
|
||||
args: {
|
||||
i18n,
|
||||
hasInitialLoadCompleted: false,
|
||||
isCustomizingPreferredReactions: false,
|
||||
},
|
||||
} as Meta;
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
// eslint-disable-next-line react/function-component-definition
|
||||
const Template: Story<PropsType & { daysAgo?: number }> = ({
|
||||
const Template: StoryFn<PropsType & { daysAgo?: number }> = ({
|
||||
daysAgo,
|
||||
...args
|
||||
}) => {
|
||||
|
@ -90,6 +64,3 @@ const Template: Story<PropsType & { daysAgo?: number }> = ({
|
|||
};
|
||||
|
||||
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