├── .babelrc
├── .codesandbox
└── ci.json
├── .editorconfig
├── .env
├── .eslintrc.js
├── .firebaserc
├── .github
├── FUNDING.yml
└── workflows
│ ├── ci.yml
│ └── release.yml
├── .gitignore
├── .prettierrc
├── .storybook
├── decorators
│ └── withGlobalStyle.tsx
├── logo.png
├── main.ts
├── manager.css
├── manager.ts
├── preview.ts
├── theme-picker
│ ├── ThemeButton.tsx
│ ├── ThemeList.tsx
│ ├── ThemeProvider.tsx
│ ├── constants.ts
│ └── register.ts
└── theme.js
├── LICENSE
├── README.md
├── docs
├── Contributing.stories.mdx
├── Getting-Started.stories.mdx
├── Submit-your-Project.stories.mdx
└── Welcome.stories.mdx
├── firebase.json
├── jest.config.js
├── package.json
├── rollup.config.js
├── src
├── Anchor
│ ├── Anchor.spec.tsx
│ ├── Anchor.stories.tsx
│ └── Anchor.tsx
├── AppBar
│ ├── AppBar.spec.tsx
│ ├── AppBar.stories.tsx
│ └── AppBar.tsx
├── Avatar
│ ├── Avatar.spec.tsx
│ ├── Avatar.stories.tsx
│ └── Avatar.tsx
├── Button
│ ├── Button.spec.tsx
│ ├── Button.stories.tsx
│ └── Button.tsx
├── Checkbox
│ ├── Checkbox.spec.tsx
│ ├── Checkbox.stories.tsx
│ └── Checkbox.tsx
├── ColorInput
│ ├── ColorInput.spec.tsx
│ ├── ColorInput.stories.tsx
│ └── ColorInput.tsx
├── Counter
│ ├── Counter.spec.tsx
│ ├── Counter.stories.tsx
│ ├── Counter.tsx
│ └── Digit.tsx
├── DatePicker
│ ├── DatePicker.stories.tsx
│ └── DatePicker.tsx
├── Frame
│ ├── Frame.spec.tsx
│ ├── Frame.stories.tsx
│ └── Frame.tsx
├── GroupBox
│ ├── GroupBox.spec.tsx
│ ├── GroupBox.stories.tsx
│ └── GroupBox.tsx
├── Handle
│ ├── Handle.spec.tsx
│ ├── Handle.stories.tsx
│ └── Handle.tsx
├── Hourglass
│ ├── Hourglass.spec.tsx
│ ├── Hourglass.stories.tsx
│ ├── Hourglass.tsx
│ └── base64hourglass.tsx
├── MenuList
│ ├── MenuList.spec.tsx
│ ├── MenuList.stories.tsx
│ ├── MenuList.tsx
│ ├── MenuListItem.spec.tsx
│ └── MenuListItem.tsx
├── Monitor
│ ├── Monitor.spec.tsx
│ ├── Monitor.stories.tsx
│ └── Monitor.tsx
├── NumberInput
│ ├── NumberInput.spec.tsx
│ ├── NumberInput.stories.tsx
│ └── NumberInput.tsx
├── ProgressBar
│ ├── ProgressBar.spec.tsx
│ ├── ProgressBar.stories.tsx
│ └── ProgressBar.tsx
├── Radio
│ ├── Radio.spec.tsx
│ ├── Radio.stories.tsx
│ └── Radio.tsx
├── ScrollView
│ ├── ScrollView.spec.tsx
│ ├── ScrollView.stories.tsx
│ └── ScrollView.tsx
├── Select
│ ├── Select.spec.tsx
│ ├── Select.stories.data.ts
│ ├── Select.stories.tsx
│ ├── Select.styles.tsx
│ ├── Select.tsx
│ ├── Select.types.ts
│ ├── SelectNative.spec.tsx
│ ├── SelectNative.tsx
│ ├── useSelectCommon.tsx
│ └── useSelectState.ts
├── Separator
│ ├── Separator.spec.tsx
│ ├── Separator.stories.tsx
│ └── Separator.tsx
├── Slider
│ ├── Slider.spec.tsx
│ ├── Slider.stories.tsx
│ └── Slider.tsx
├── Table
│ ├── Table.spec.tsx
│ ├── Table.stories.tsx
│ ├── Table.tsx
│ ├── TableBody.spec.tsx
│ ├── TableBody.tsx
│ ├── TableDataCell.spec.tsx
│ ├── TableDataCell.tsx
│ ├── TableHead.spec.tsx
│ ├── TableHead.tsx
│ ├── TableHeadCell.spec.tsx
│ ├── TableHeadCell.tsx
│ ├── TableRow.spec.tsx
│ └── TableRow.tsx
├── Tabs
│ ├── Tab.spec.tsx
│ ├── Tab.tsx
│ ├── TabBody.spec.tsx
│ ├── TabBody.tsx
│ ├── Tabs.spec.tsx
│ ├── Tabs.stories.tsx
│ └── Tabs.tsx
├── TextInput
│ ├── TextInput.spec.tsx
│ ├── TextInput.stories.tsx
│ └── TextInput.tsx
├── Toolbar
│ ├── Toolbar.spec.tsx
│ └── Toolbar.tsx
├── Tooltip
│ ├── Tooltip.spec.tsx
│ ├── Tooltip.stories.tsx
│ └── Tooltip.tsx
├── TreeView
│ ├── TreeView.spec.tsx
│ ├── TreeView.stories.tsx
│ └── TreeView.tsx
├── Window
│ ├── Window.spec.tsx
│ ├── Window.stories.tsx
│ ├── Window.tsx
│ ├── WindowContent.spec.tsx
│ ├── WindowContent.tsx
│ ├── WindowHeader.spec.tsx
│ └── WindowHeader.tsx
├── assets
│ ├── fonts
│ │ ├── dist
│ │ │ ├── ms_sans_serif.woff
│ │ │ ├── ms_sans_serif.woff2
│ │ │ ├── ms_sans_serif_bold.woff
│ │ │ └── ms_sans_serif_bold.woff2
│ │ └── src
│ │ │ ├── ms-sans-serif-bold
│ │ │ ├── MS Sans Serif Bold.ttf
│ │ │ ├── license.txt
│ │ │ └── readme.txt
│ │ │ └── ms-sans-serif
│ │ │ ├── MS Sans Serif.ttf
│ │ │ ├── license.txt
│ │ │ └── readme.txt
│ └── images
│ │ ├── logo.png
│ │ └── logo.psd
├── common
│ ├── SwitchBase.ts
│ ├── constants.ts
│ ├── hooks
│ │ ├── useControlledOrUncontrolled.ts
│ │ ├── useEventCallback.ts
│ │ ├── useForkRef.spec.tsx
│ │ ├── useForkRef.ts
│ │ ├── useId.spec.ts
│ │ ├── useId.ts
│ │ └── useIsFocusVisible.ts
│ ├── index.ts
│ ├── styleReset.ts
│ ├── system.ts
│ ├── themes
│ │ ├── aiee.ts
│ │ ├── ash.ts
│ │ ├── azureOrange.ts
│ │ ├── bee.ts
│ │ ├── blackAndWhite.ts
│ │ ├── blue.ts
│ │ ├── brick.ts
│ │ ├── candy.ts
│ │ ├── cherry.ts
│ │ ├── coldGray.ts
│ │ ├── counterStrike.ts
│ │ ├── darkTeal.ts
│ │ ├── denim.ts
│ │ ├── eggplant.ts
│ │ ├── fxDev.ts
│ │ ├── highContrast.ts
│ │ ├── honey.ts
│ │ ├── hotChocolate.ts
│ │ ├── hotdogStand.ts
│ │ ├── index.ts
│ │ ├── lilac.ts
│ │ ├── lilacRoseDark.ts
│ │ ├── maple.ts
│ │ ├── marine.ts
│ │ ├── matrix.ts
│ │ ├── millenium.ts
│ │ ├── modernDark.ts
│ │ ├── molecule.ts
│ │ ├── monochrome.ts
│ │ ├── ninjaTurtles.ts
│ │ ├── olive.ts
│ │ ├── original.ts
│ │ ├── pamelaAnderson.ts
│ │ ├── peggysPastels.ts
│ │ ├── plum.ts
│ │ ├── polarized.ts
│ │ ├── powerShell.ts
│ │ ├── rainyDay.ts
│ │ ├── raspberry.ts
│ │ ├── redWine.ts
│ │ ├── rose.ts
│ │ ├── seawater.ts
│ │ ├── shelbiTeal.ts
│ │ ├── slate.ts
│ │ ├── solarizedDark.ts
│ │ ├── solarizedLight.ts
│ │ ├── spruce.ts
│ │ ├── stormClouds.ts
│ │ ├── theSixtiesUSA.ts
│ │ ├── tokyoDark.ts
│ │ ├── toner.ts
│ │ ├── tooSexy.ts
│ │ ├── travel.ts
│ │ ├── types.ts
│ │ ├── vaporTeal.ts
│ │ ├── vermillion.ts
│ │ ├── violetDark.ts
│ │ ├── vistaesqueMidnight.ts
│ │ ├── water.ts
│ │ ├── white.ts
│ │ ├── windows1.ts
│ │ └── wmii.ts
│ └── utils
│ │ ├── events.spec.tsx
│ │ ├── events.ts
│ │ ├── index.spec.ts
│ │ └── index.ts
├── index.ts
├── legacy
│ ├── Bar.tsx
│ ├── Cutout.tsx
│ ├── Desktop.tsx
│ ├── Divider.tsx
│ ├── Fieldset.tsx
│ ├── List.tsx
│ ├── ListItem.tsx
│ ├── NumberField.tsx
│ ├── Panel.tsx
│ ├── Progress.tsx
│ ├── TextField.tsx
│ └── Tree.tsx
└── types.ts
├── test
├── setup-test.ts
└── utils.tsx
├── tsconfig.build.index.json
├── tsconfig.build.themes.json
├── tsconfig.json
├── types
├── globals.d.ts
└── themes.d.ts
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "sourceType": "unambiguous",
3 | "presets": [
4 | [
5 | "@babel/preset-env",
6 | {
7 | "shippedProposals": true,
8 | "loose": true
9 | }
10 | ],
11 | "@babel/preset-typescript"
12 | ],
13 | "plugins": [
14 | "@babel/plugin-transform-shorthand-properties",
15 | "@babel/plugin-transform-block-scoping",
16 | [
17 | "@babel/plugin-proposal-decorators",
18 | {
19 | "legacy": true
20 | }
21 | ],
22 | [
23 | "@babel/plugin-proposal-class-properties",
24 | {
25 | "loose": true
26 | }
27 | ],
28 | [
29 | "@babel/plugin-proposal-private-property-in-object",
30 | {
31 | "loose": true
32 | }
33 | ],
34 | [
35 | "@babel/plugin-proposal-private-methods",
36 | {
37 | "loose": true
38 | }
39 | ],
40 | "@babel/plugin-proposal-export-default-from",
41 | "@babel/plugin-syntax-dynamic-import",
42 | [
43 | "@babel/plugin-proposal-object-rest-spread",
44 | {
45 | "loose": true,
46 | "useBuiltIns": true
47 | }
48 | ],
49 | "@babel/plugin-transform-classes",
50 | "@babel/plugin-transform-arrow-functions",
51 | "@babel/plugin-transform-parameters",
52 | "@babel/plugin-transform-destructuring",
53 | "@babel/plugin-transform-spread",
54 | "@babel/plugin-transform-for-of",
55 | "babel-plugin-macros",
56 | "@babel/plugin-proposal-optional-chaining",
57 | "@babel/plugin-proposal-nullish-coalescing-operator"
58 | ]
59 | }
60 |
--------------------------------------------------------------------------------
/.codesandbox/ci.json:
--------------------------------------------------------------------------------
1 | {
2 | "buildCommand": "build:prod",
3 | "node": "16",
4 | "sandboxes": [
5 | "react95-template-xkfj0"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = yes
9 | insert_final_newline = yes
10 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | BROWSER=none
2 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: [
3 | 'plugin:@typescript-eslint/recommended',
4 | 'airbnb',
5 | 'plugin:prettier/recommended',
6 | 'plugin:react-hooks/recommended'
7 | ],
8 | parser: '@typescript-eslint/parser',
9 | plugins: ['react', 'prettier'],
10 | env: {
11 | browser: true,
12 | es6: true,
13 | jest: true
14 | },
15 | rules: {
16 | '@typescript-eslint/explicit-module-boundary-types': 'off',
17 | '@typescript-eslint/no-empty-function': 'off',
18 | '@typescript-eslint/no-empty-interface': 'off',
19 | '@typescript-eslint/no-use-before-define': 'off',
20 | '@typescript-eslint/no-unused-vars': [
21 | 'error',
22 | {
23 | argsIgnorePattern: '^_\\d*$'
24 | }
25 | ],
26 | 'import/extensions': ['error', { js: 'never', ts: 'never', tsx: 'never' }],
27 | 'import/no-unresolved': [
28 | 'error',
29 | // TODO: Remove ../../test/utils when TypeScript migration is complete
30 | { ignore: ['react95', '../../test/utils'] }
31 | ],
32 | 'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
33 | 'import/prefer-default-export': 'off',
34 | 'jsx-a11y/label-has-associated-control': ['error', { assert: 'either' }],
35 | 'jsx-a11y/label-has-for': 'off',
36 | 'no-nested-ternary': 'off',
37 | 'prettier/prettier': 'error',
38 | 'react/forbid-prop-types': 'off',
39 | 'react/jsx-filename-extension': [
40 | 'warn',
41 | { extensions: ['.js', '.jsx', '.tsx'] }
42 | ],
43 | 'react/jsx-props-no-spreading': 'off',
44 | 'react/no-array-index-key': 'off',
45 | 'react/prop-types': 'off',
46 | 'react/require-default-props': 'off',
47 | 'react/static-property-placement': ['error', 'static public field']
48 | },
49 | overrides: [
50 | {
51 | files: ['*.spec.@(js|jsx|ts|tsx)', '*.stories.@(js|jsx|ts|tsx)'],
52 | rules: {
53 | 'no-console': 'off'
54 | }
55 | },
56 | {
57 | files: ['*.@(ts|tsx)'],
58 | rules: {
59 | // This is handled by @typescript-eslint/no-unused-vars
60 | 'no-undef': 'off'
61 | }
62 | }
63 | ],
64 | settings: {
65 | 'import/parsers': {
66 | '@typescript-eslint/parser': ['.ts', '.tsx']
67 | },
68 | 'import/resolver': {
69 | typescript: {}
70 | }
71 | }
72 | };
73 |
--------------------------------------------------------------------------------
/.firebaserc:
--------------------------------------------------------------------------------
1 | {
2 | "projects": {
3 | "default": "react95-storybook"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: arturbien
4 | patreon: arturbien
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | custom: https://www.paypal.me/react95
9 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - next
8 | - beta
9 | - alpha
10 | - '*.x' # maintenance releases
11 |
12 | jobs:
13 | release-library:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - name: Git Checkout
17 | uses: actions/checkout@v2
18 |
19 | - name: Setup node
20 | uses: actions/setup-node@v3
21 | with:
22 | node-version: 16
23 |
24 | - name: Cache packages
25 | uses: actions/cache@v3
26 | with:
27 | key: node_modules-v4-${{ hashFiles('yarn.lock') }}
28 | path: |-
29 | node_modules
30 | */node_modules
31 | restore-keys: 'node_modules-v4-'
32 |
33 | - name: Yarn install
34 | run: yarn install --ignore-optional --frozen-lockfile
35 |
36 | - name: Build library
37 | run: yarn run build
38 |
39 | - name: Deploy library
40 | run: yarn run semantic-release || true
41 | env:
42 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
43 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
44 |
45 | release-storybook:
46 | needs:
47 | - release-library
48 | if: github.ref == 'refs/heads/master'
49 | runs-on: ubuntu-latest
50 | steps:
51 | - name: Git Checkout
52 | uses: actions/checkout@v2
53 |
54 | - name: Setup node
55 | uses: actions/setup-node@v3
56 | with:
57 | node-version: 16
58 |
59 | - name: Cache packages
60 | uses: actions/cache@v3
61 | with:
62 | key: node_modules-v4-${{ hashFiles('yarn.lock') }}
63 | path: |-
64 | node_modules
65 | */node_modules
66 | restore-keys: 'node_modules-v4-'
67 |
68 | - name: Yarn install
69 | run: yarn install --ignore-optional --frozen-lockfile
70 |
71 | - name: Build Storybook
72 | run: yarn run build:storybook
73 |
74 | - name: Deploy Storybook
75 | run: ./node_modules/.bin/firebase deploy --token=$FIREBASE_TOKEN
76 | env:
77 | FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
78 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # library build
12 | /cjs
13 | /esm
14 | /themes
15 | /images
16 | /fonts
17 | /dist
18 |
19 | # storybook
20 | /storybook
21 | /.firebase
22 |
23 | # misc
24 | .DS_Store
25 | .env.local
26 | .env.development.local
27 | .env.test.local
28 | .env.production.local
29 |
30 | npm-debug.log*
31 | yarn-debug.log*
32 | yarn-error.log*
33 |
34 | # JetBrains IDEs
35 | .idea/*
36 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "arrowParens": "avoid",
3 | "bracketSpacing": true,
4 | "htmlWhitespaceSensitivity": "css",
5 | "insertPragma": false,
6 | "jsxBracketSameLine": false,
7 | "jsxSingleQuote": true,
8 | "printWidth": 80,
9 | "proseWrap": "preserve",
10 | "quoteProps": "as-needed",
11 | "requirePragma": false,
12 | "semi": true,
13 | "singleQuote": true,
14 | "tabWidth": 2,
15 | "trailingComma": "none",
16 | "useTabs": false
17 | }
18 |
--------------------------------------------------------------------------------
/.storybook/decorators/withGlobalStyle.tsx:
--------------------------------------------------------------------------------
1 | import { DecoratorFn } from '@storybook/react';
2 | import React from 'react';
3 | import { createGlobalStyle } from 'styled-components';
4 |
5 | import ms_sans_serif from '../../src/assets/fonts/dist/ms_sans_serif.woff2';
6 | import ms_sans_serif_bold from '../../src/assets/fonts/dist/ms_sans_serif_bold.woff2';
7 | import styleReset from '../../src/common/styleReset';
8 |
9 | const GlobalStyle = createGlobalStyle`
10 | ${styleReset}
11 | @font-face {
12 | font-family: 'ms_sans_serif';
13 | src: url('${ms_sans_serif}') format('woff2');
14 | font-weight: 400;
15 | font-style: normal
16 | }
17 | @font-face {
18 | font-family: 'ms_sans_serif';
19 | src: url('${ms_sans_serif_bold}') format("woff2");
20 | font-weight: bold;
21 | font-style: normal
22 | }
23 | html, body, #root {
24 | height: 100%;
25 | }
26 | #root > * {
27 | height: 100%;
28 | box-sizing: border-box;
29 | }
30 | body {
31 | font-family: 'ms_sans_serif', 'sans-serif';
32 | }
33 | `;
34 |
35 | export const withGlobalStyle: DecoratorFn = story => (
36 | <>
37 |
38 | {story()}
39 | >
40 | );
41 |
--------------------------------------------------------------------------------
/.storybook/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react95-io/React95/871d5335daebdda1469f66f81266523f4191a595/.storybook/logo.png
--------------------------------------------------------------------------------
/.storybook/main.ts:
--------------------------------------------------------------------------------
1 | import type { StorybookConfig } from '@storybook/react/types';
2 | import type { PropItem } from 'react-docgen-typescript';
3 |
4 | const path = require('path');
5 |
6 | const storybookConfig: StorybookConfig = {
7 | stories: ['../@(docs|src)/**/*.stories.@(tsx|mdx)'],
8 | addons: [
9 | {
10 | name: '@storybook/addon-docs',
11 | options: {
12 | sourceLoaderOptions: {
13 | injectStoryParameters: false
14 | }
15 | }
16 | },
17 | '@storybook/addon-storysource',
18 | './theme-picker/register.ts'
19 | ],
20 | core: {
21 | builder: 'webpack5'
22 | },
23 | features: {
24 | babelModeV7: true,
25 | storyStoreV7: true,
26 | modernInlineRender: true,
27 | postcss: false
28 | },
29 | typescript: {
30 | check: false,
31 | checkOptions: {},
32 | reactDocgen: 'react-docgen-typescript',
33 | reactDocgenTypescriptOptions: {
34 | shouldExtractLiteralValuesFromEnum: true,
35 | propFilter: (prop: PropItem) =>
36 | prop.parent ? !/node_modules/.test(prop.parent.fileName) : true
37 | }
38 | },
39 | webpackFinal: config => {
40 | config.resolve = {
41 | ...config.resolve,
42 | alias: {
43 | ...config.resolve?.alias,
44 | react95: path.resolve(__dirname, '../src/index')
45 | }
46 | };
47 |
48 | return config;
49 | }
50 | };
51 |
52 | module.exports = storybookConfig;
53 |
--------------------------------------------------------------------------------
/.storybook/manager.css:
--------------------------------------------------------------------------------
1 | /* Remove from the sidebar menu stories that contains "unstable" */
2 | a[data-item-id$='-unstable'].sidebar-item,
3 | a[data-item-id*='-unstable-'].sidebar-item,
4 | button[data-item-id$='-unstable'].sidebar-item,
5 | button[data-item-id$='-unstable-'].sidebar-item {
6 | display: none !important;
7 | }
8 |
--------------------------------------------------------------------------------
/.storybook/manager.ts:
--------------------------------------------------------------------------------
1 | import './manager.css';
2 |
3 | import { addons } from '@storybook/addons';
4 | import theme from './theme';
5 |
6 | addons.setConfig({
7 | theme
8 | });
9 |
--------------------------------------------------------------------------------
/.storybook/preview.ts:
--------------------------------------------------------------------------------
1 | import { DecoratorFn, Parameters } from '@storybook/react';
2 | import { withGlobalStyle } from './decorators/withGlobalStyle';
3 | import { withThemesProvider } from './theme-picker/ThemeProvider';
4 |
5 | export const decorators: DecoratorFn[] = [withGlobalStyle, withThemesProvider];
6 |
7 | export const parameters: Parameters = {
8 | layout: 'fullscreen',
9 | options: {
10 | storySort: {
11 | order: [
12 | 'Docs',
13 | [
14 | 'Welcome to React95',
15 | 'Getting Started',
16 | 'Contributing',
17 | 'Submit your Project'
18 | ],
19 | 'Controls',
20 | 'Environment',
21 | 'Layout',
22 | 'Typography',
23 | 'Other'
24 | ]
25 | }
26 | }
27 | };
28 |
--------------------------------------------------------------------------------
/.storybook/theme-picker/ThemeButton.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from 'react';
2 | import { ThemeProvider } from 'styled-components';
3 | import { Button } from '../../src/Button/Button';
4 | import { Theme } from '../../src/types';
5 |
6 | export function ThemeButton({
7 | active,
8 | onChoose,
9 | theme
10 | }: {
11 | active: boolean;
12 | onChoose: (themeName: string) => void;
13 | theme: Theme;
14 | }) {
15 | const handleClick = useCallback(() => {
16 | onChoose(theme.name);
17 | }, []);
18 |
19 | return (
20 |
21 |
22 | {theme.name}
23 |
24 |
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/.storybook/theme-picker/ThemeList.tsx:
--------------------------------------------------------------------------------
1 | import { useAddonState } from '@storybook/api';
2 | import React, { useCallback } from 'react';
3 | import styled from 'styled-components';
4 |
5 | import themes from '../../src/common/themes';
6 | import { Theme } from '../../src/types';
7 | import { THEMES_ID } from './constants';
8 | import { ThemeButton } from './ThemeButton';
9 |
10 | const {
11 | original,
12 | rainyDay,
13 | vaporTeal,
14 | theSixtiesUSA,
15 | olive,
16 | tokyoDark,
17 | rose,
18 | plum,
19 | matrix,
20 | travel,
21 | ...otherThemes
22 | } = themes;
23 |
24 | const themeList = [
25 | original,
26 | rainyDay,
27 | vaporTeal,
28 | theSixtiesUSA,
29 | olive,
30 | tokyoDark,
31 | rose,
32 | plum,
33 | matrix,
34 | travel,
35 | ...Object.values(otherThemes)
36 | ];
37 |
38 | type ThemesProps = {
39 | active?: boolean;
40 | };
41 |
42 | const Wrapper = styled.div<{ theme: Theme }>`
43 | display: grid;
44 | padding: 1em;
45 | gap: 1em;
46 | grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
47 | grid-template-rows: repeat(auto-fill, 40px);
48 | background-color: ${({ theme }) => theme.material};
49 | `;
50 |
51 | export function ThemeList({ active }: ThemesProps) {
52 | const [themeName, setThemeName] = useAddonState(THEMES_ID, 'original');
53 |
54 | const handleChoose = useCallback(
55 | (newThemeName: string) => {
56 | setThemeName(newThemeName);
57 | },
58 | [setThemeName]
59 | );
60 |
61 | if (!active) {
62 | return <>>;
63 | }
64 |
65 | return (
66 |
67 | {themeList.map(theme => (
68 |
74 | ))}
75 |
76 | );
77 | }
78 |
--------------------------------------------------------------------------------
/.storybook/theme-picker/ThemeProvider.tsx:
--------------------------------------------------------------------------------
1 | import { useAddonState } from '@storybook/client-api';
2 | import { DecoratorFn } from '@storybook/react';
3 | import React from 'react';
4 | import { ThemeProvider } from 'styled-components';
5 |
6 | import themes from '../../src/common/themes/index';
7 | import { THEMES_ID } from './constants';
8 |
9 | export const withThemesProvider: DecoratorFn = story => {
10 | const [themeName] = useAddonState(THEMES_ID, 'original');
11 |
12 | return (
13 |
14 | {story()}
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/.storybook/theme-picker/constants.ts:
--------------------------------------------------------------------------------
1 | export const THEMES_ID = 'storybook/themes';
2 |
--------------------------------------------------------------------------------
/.storybook/theme-picker/register.ts:
--------------------------------------------------------------------------------
1 | import addons, { makeDecorator, types } from '@storybook/addons';
2 | import { THEMES_ID } from './constants';
3 | import { ThemeList } from './ThemeList';
4 |
5 | addons.register(THEMES_ID, () => {
6 | addons.addPanel(`${THEMES_ID}/panel`, {
7 | title: 'Themes',
8 | type: types.PANEL,
9 | render: ThemeList
10 | });
11 | });
12 |
13 | export default makeDecorator({
14 | name: 'withThemesProvider',
15 | parameterName: 'theme',
16 | wrapper: (getStory, context) => getStory(context)
17 | });
18 |
--------------------------------------------------------------------------------
/.storybook/theme.js:
--------------------------------------------------------------------------------
1 | import { create } from '@storybook/theming';
2 |
3 | import brandImage from './logo.png';
4 |
5 | export default create({
6 | base: 'light',
7 | brandTitle: 'React95',
8 | brandUrl: 'https://react95.io',
9 | brandImage,
10 | brandTarget: '_self',
11 |
12 | // UI
13 | appBg: '#dfdfdf',
14 | appContentBg: '#ffffff',
15 | appBorderColor: '#848584',
16 | appBorderRadius: 0,
17 |
18 | // Typography
19 | fontBase: '"ms_sans_serif", sans-serif',
20 | fontCode: 'monospace',
21 |
22 | // Text colors
23 | textColor: '#0a0a0a',
24 | textInverseColor: 'rgba(255,255,255,0.9)',
25 |
26 | // Toolbar default and active colors
27 | barTextColor: '#c6c6c6',
28 | barSelectedColor: '#fefefe',
29 | barBg: '#060084',
30 |
31 | // Form colors
32 | inputBg: '#ffffff',
33 | inputBorder: '#dfdfdf',
34 | inputTextColor: '#0a0a0a',
35 | inputBorderRadius: 0
36 | });
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Artur Bień
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/docs/Contributing.stories.mdx:
--------------------------------------------------------------------------------
1 | import { Meta } from '@storybook/addon-docs';
2 |
3 |
4 |
5 | # Contributing
6 |
7 | Any help from UI/UX designers would be EXTREMELY appreciated. The challenge is
8 | to come up with new component designs/layouts that are broadly used in modern
9 | UIs, that weren't present back in 95.
10 |
11 | If you want to help with the project, feel free to [open pull requests][1],
12 | [submit issues or component proposals][2] and join our [Slack channels][3]!
13 | Let's bring this UI back to life ♥️
14 |
15 | [1]: https://github.com/arturbien/react95/pulls
16 | [2]: https://github.com/arturbien/React95/issues
17 | [3]: https://join.slack.com/t/react95/shared_invite/enQtOTA1NzEyNjAyNTc4LWYxZjU3NWRiMWJlMGJiMjhkNzE2MDA3ZmZjZDc1YmY0ODdlZjMwZDA1NWJiYWExYmY1NTJmNmE4OWVjNWFhMTE
18 |
--------------------------------------------------------------------------------
/docs/Getting-Started.stories.mdx:
--------------------------------------------------------------------------------
1 | import { Meta } from '@storybook/addon-docs';
2 |
3 |
4 |
5 | # Installation
6 |
7 | React95 is available as an [npm package](https://www.npmjs.com/package/react95).
8 |
9 | ## npm
10 |
11 | To install and save your `package.json` dependencies, run:
12 |
13 | ```sh
14 | # yarn
15 | yarn add react95 styled-components
16 |
17 | # npm
18 | npm install -S react95 styled-components
19 | ```
20 |
21 | In order to have `react95` working properly, you'll also need
22 | [styled-components 💅](https://github.com/styled-components/styled-components),
23 | this way you can use custom themes and get the best of the library 🙂
24 |
25 | ## Usage
26 |
27 | Apply style reset, wrap your app content with ThemeProvider with theme of your
28 | choice... and you are ready to go! 🚀
29 |
30 | ```jsx
31 | import React from 'react';
32 | import { MenuList, MenuListItem, Separator, styleReset } from 'react95';
33 | import { createGlobalStyle, ThemeProvider } from 'styled-components';
34 |
35 | /* Pick a theme of your choice */
36 | import original from 'react95/dist/themes/original';
37 |
38 | /* Original Windows95 font (optional) */
39 | import ms_sans_serif from 'react95/dist/fonts/ms_sans_serif.woff2';
40 | import ms_sans_serif_bold from 'react95/dist/fonts/ms_sans_serif_bold.woff2';
41 |
42 | const GlobalStyles = createGlobalStyle`
43 | ${styleReset}
44 | @font-face {
45 | font-family: 'ms_sans_serif';
46 | src: url('${ms_sans_serif}') format('woff2');
47 | font-weight: 400;
48 | font-style: normal
49 | }
50 | @font-face {
51 | font-family: 'ms_sans_serif';
52 | src: url('${ms_sans_serif_bold}') format('woff2');
53 | font-weight: bold;
54 | font-style: normal
55 | }
56 | body, input, select, textarea {
57 | font-family: 'ms_sans_serif';
58 | }
59 | `;
60 |
61 | const App = () => (
62 |
63 |
64 |
65 |
66 | 🎤 Sing
67 | 💃🏻 Dance
68 |
69 | 😴 Sleep
70 |
71 |
72 |
73 | );
74 |
75 | export default App;
76 | ```
77 |
--------------------------------------------------------------------------------
/docs/Submit-your-Project.stories.mdx:
--------------------------------------------------------------------------------
1 | import { Meta } from '@storybook/addon-docs';
2 |
3 |
4 |
5 | # Submit your Project
6 |
7 | Apps built with React95 will be featured on the official React95 [website](https://react95.io) 🤟🏻
8 |
9 | In order to submit your project, just drop a comment on [this issue](https://github.com/arturbien/React95/issues/25)!
10 |
--------------------------------------------------------------------------------
/docs/Welcome.stories.mdx:
--------------------------------------------------------------------------------
1 | import { Meta } from '@storybook/addon-docs';
2 |
3 |
4 |
5 | # Welcome to React95
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
35 |
36 | **Refreshed** Windows 95 UI components for your modern React apps. Built with
37 | [styled-components](https://github.com/styled-components/styled-components) 💅.
38 |
39 | 
40 |
41 | ### Getting Started
42 |
43 | Check out our [getting started](?path=/story/docs-getting-started--page) docs!
44 |
45 | ### Motivation
46 |
47 | Create modern mobile/web applications with the retro and old school Windows 95 style. Our goal is not to exactly recreate Windows95 components, but to provide a solid component library for current scenarios.
48 |
49 | ### Support
50 |
51 | - [Become a backer or sponsor on Patreon](https://www.patreon.com/arturbien)
52 | - [One-time donation via PayPal](https://www.paypal.me/react95)
53 |
--------------------------------------------------------------------------------
/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | "hosting": {
3 | "public": "storybook",
4 | "ignore": [
5 | "firebase.json",
6 | "**/.*",
7 | "**/node_modules/**"
8 | ],
9 | "rewrites": [
10 | {
11 | "source": "**",
12 | "destination": "/index.html"
13 | }
14 | ]
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | globals: {
3 | 'ts-jest': {
4 | diagnostics: false,
5 | isolatedModules: true
6 | }
7 | },
8 | coverageReporters: ['text', 'html'],
9 | preset: 'ts-jest/presets/default-esm',
10 | setupFilesAfterEnv: ['/test/setup-test.ts'],
11 | testEnvironment: 'jsdom'
12 | };
13 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import typescript from '@rollup/plugin-typescript';
2 | import copy from 'rollup-plugin-copy';
3 | import esbuild from 'rollup-plugin-esbuild';
4 | import replace from 'rollup-plugin-replace';
5 |
6 | const NODE_ENV = process.env.NODE_ENV || 'development';
7 |
8 | const baseBundle = {
9 | external: id => !/^[./]/.test(id),
10 | plugins: [
11 | replace({
12 | 'process.env.NODE_ENV': JSON.stringify(NODE_ENV)
13 | }),
14 | esbuild()
15 | ]
16 | };
17 |
18 | export default [
19 | {
20 | ...baseBundle,
21 | input: ['./src/index.ts', './src/types.ts'],
22 | output: [
23 | {
24 | dir: 'dist',
25 | entryFileNames: '[name].js',
26 | exports: 'auto',
27 | format: 'cjs',
28 | preserveModules: true,
29 | preserveModulesRoot: 'src'
30 | },
31 | {
32 | dir: 'dist',
33 | entryFileNames: '[name].mjs',
34 | exports: 'auto',
35 | format: 'es',
36 | preserveModules: true,
37 | preserveModulesRoot: 'src'
38 | }
39 | ],
40 | plugins: [
41 | ...baseBundle.plugins,
42 | typescript({
43 | tsconfig: './tsconfig.build.index.json',
44 | declaration: true,
45 | declarationDir: 'dist'
46 | })
47 | ]
48 | },
49 | {
50 | ...baseBundle,
51 | input: './src/common/themes/index.ts',
52 | output: {
53 | dir: 'dist/themes',
54 | exports: 'default',
55 | format: 'cjs',
56 | preserveModules: true,
57 | preserveModulesRoot: 'src/common/themes'
58 | },
59 | plugins: [
60 | ...baseBundle.plugins,
61 | copy({
62 | targets: [
63 | { src: './src/assets/fonts/dist/*', dest: './dist/fonts' },
64 | { src: './src/assets/images/*', dest: './dist/images' }
65 | ]
66 | }),
67 | typescript({
68 | tsconfig: './tsconfig.build.themes.json',
69 | declaration: true,
70 | declarationDir: 'dist/themes'
71 | })
72 | ]
73 | }
74 | ];
75 |
--------------------------------------------------------------------------------
/src/Anchor/Anchor.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { render } from '@testing-library/react';
4 |
5 | import { Anchor } from './Anchor';
6 |
7 | const defaultProps = {
8 | children: '',
9 | href: ''
10 | };
11 |
12 | describe(' ', () => {
13 | it('should render href', () => {
14 | const { container } = render(
15 |
16 | );
17 | const anchorEl = container.firstChild;
18 |
19 | expect(anchorEl).toHaveAttribute('href', 'http://yoda.com');
20 | });
21 |
22 | it('should render children', () => {
23 | const { container } = render(
24 | You shall pass
25 | );
26 | const anchorEl = container.firstChild;
27 |
28 | expect(anchorEl).toHaveTextContent('You shall pass');
29 | });
30 |
31 | it('should render custom style', () => {
32 | const { container } = render(
33 |
34 | );
35 | const anchorEl = container.firstChild;
36 |
37 | expect(anchorEl).toHaveAttribute('style', 'color: papayawhip;');
38 | });
39 |
40 | it('should render custom props', () => {
41 | const customProps = { target: '_blank' };
42 | const { container } = render( );
43 | const anchorEl = container.firstChild;
44 |
45 | expect(anchorEl).toHaveAttribute('target', '_blank');
46 | });
47 | });
48 |
--------------------------------------------------------------------------------
/src/Anchor/Anchor.stories.tsx:
--------------------------------------------------------------------------------
1 | import { ComponentMeta } from '@storybook/react';
2 | import React from 'react';
3 | import { Anchor } from 'react95';
4 | import styled from 'styled-components';
5 |
6 | const Wrapper = styled.div`
7 | padding: 5rem;
8 | background: ${({ theme }) => theme.material};
9 | `;
10 |
11 | export default {
12 | title: 'Typography/Anchor',
13 | component: Anchor,
14 | decorators: [story => {story()} ]
15 | } as ComponentMeta;
16 |
17 | export function Default() {
18 | return (
19 |
20 | Everybody likes{' '}
21 |
22 | https://expensive.toys
23 |
24 |
25 | );
26 | }
27 |
28 | Default.story = {
29 | name: 'default'
30 | };
31 |
--------------------------------------------------------------------------------
/src/Anchor/Anchor.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import styled from 'styled-components';
3 |
4 | import { CommonStyledProps } from '../types';
5 |
6 | type AnchorProps = {
7 | children: React.ReactNode;
8 | underline?: boolean;
9 | } & React.AnchorHTMLAttributes &
10 | CommonStyledProps;
11 |
12 | const StyledAnchor = styled.a<{ underline: boolean }>`
13 | color: ${({ theme }) => theme.anchor};
14 | font-size: inherit;
15 | text-decoration: ${({ underline }) => (underline ? 'underline' : 'none')};
16 | &:visited {
17 | color: ${({ theme }) => theme.anchorVisited};
18 | }
19 | `;
20 |
21 | const Anchor = forwardRef(
22 | ({ children, underline = true, ...otherProps }: AnchorProps, ref) => {
23 | return (
24 |
25 | {children}
26 |
27 | );
28 | }
29 | );
30 |
31 | Anchor.displayName = 'Anchor';
32 |
33 | export { Anchor, AnchorProps };
34 |
--------------------------------------------------------------------------------
/src/AppBar/AppBar.spec.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react';
2 | import React from 'react';
3 |
4 | import { AppBar } from './AppBar';
5 |
6 | const defaultProps = { children: '' };
7 |
8 | describe(' ', () => {
9 | it('should render header', () => {
10 | const { container } = render( );
11 | const headerEl = container.firstElementChild;
12 |
13 | expect(headerEl && headerEl.tagName).toBe('HEADER');
14 | });
15 |
16 | it('should render children', () => {
17 | const { container } = render(A nice app bar );
18 | const headerEl = container.firstElementChild;
19 |
20 | expect(headerEl).toHaveTextContent('A nice app bar');
21 | });
22 |
23 | it('should render fixed prop properly', () => {
24 | const { container, rerender } = render( );
25 | const headerEl = container.firstElementChild;
26 |
27 | expect(headerEl).toHaveStyleRule('position', 'fixed');
28 |
29 | rerender( );
30 |
31 | expect(headerEl).toHaveStyleRule('position', 'absolute');
32 | });
33 |
34 | it('should render position prop properly', () => {
35 | const { container } = render(
36 |
37 | );
38 | const headerEl = container.firstElementChild;
39 |
40 | expect(headerEl).toHaveStyleRule('position', 'sticky');
41 | });
42 |
43 | it('should custom style', () => {
44 | const { container } = render(
45 |
46 | );
47 | const headerEl = container.firstElementChild;
48 |
49 | expect(headerEl).toHaveAttribute('style', 'background-color: papayawhip;');
50 | });
51 |
52 | it('should render custom props', () => {
53 | const customProps = { title: 'cool-header' };
54 | const { container } = render( );
55 | const headerEl = container.firstElementChild;
56 |
57 | expect(headerEl).toHaveAttribute('title', 'cool-header');
58 | });
59 | });
60 |
--------------------------------------------------------------------------------
/src/AppBar/AppBar.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import styled, { CSSProperties } from 'styled-components';
3 |
4 | import { createBorderStyles, createBoxStyles } from '../common';
5 | import { CommonStyledProps } from '../types';
6 |
7 | type AppBarProps = {
8 | children: React.ReactNode;
9 | /** @deprecated Use `position` instead */
10 | fixed?: boolean;
11 | position?: CSSProperties['position'];
12 | } & React.HTMLAttributes &
13 | CommonStyledProps;
14 |
15 | const StyledAppBar = styled.header`
16 | ${createBorderStyles()};
17 | ${createBoxStyles()};
18 |
19 | position: ${props => props.position ?? (props.fixed ? 'fixed' : 'absolute')};
20 | top: 0;
21 | right: 0;
22 | left: auto;
23 | display: flex;
24 | flex-direction: column;
25 | width: 100%;
26 | `;
27 |
28 | const AppBar = forwardRef(
29 | ({ children, fixed = true, position = 'fixed', ...otherProps }, ref) => {
30 | return (
31 |
37 | {children}
38 |
39 | );
40 | }
41 | );
42 |
43 | AppBar.displayName = 'AppBar';
44 |
45 | export { AppBar, AppBarProps };
46 |
--------------------------------------------------------------------------------
/src/Avatar/Avatar.stories.tsx:
--------------------------------------------------------------------------------
1 | import { ComponentMeta } from '@storybook/react';
2 | import React from 'react';
3 | import { Avatar } from 'react95';
4 | import styled from 'styled-components';
5 |
6 | const Wrapper = styled.div`
7 | padding: 5rem;
8 | background: ${({ theme }) => theme.material};
9 | & > div > * {
10 | margin-right: 1rem;
11 | }
12 | `;
13 |
14 | export default {
15 | title: 'Other/Avatar',
16 | component: Avatar,
17 | decorators: [story => {story()} ]
18 | } as ComponentMeta;
19 |
20 | export function Default() {
21 | return (
22 |
23 |
24 |
25 |
26 | AK
27 |
28 |
29 |
30 | 🚀
31 |
32 |
33 |
34 | );
35 | }
36 |
37 | Default.story = {
38 | name: 'default'
39 | };
40 |
--------------------------------------------------------------------------------
/src/Avatar/Avatar.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import styled from 'styled-components';
3 | import { getSize } from '../common/utils';
4 | import { CommonStyledProps } from '../types';
5 |
6 | type AvatarProps = {
7 | alt?: string;
8 | children?: React.ReactNode;
9 | noBorder?: boolean;
10 | size?: string | number;
11 | square?: boolean;
12 | src?: string;
13 | } & React.HTMLAttributes &
14 | CommonStyledProps;
15 |
16 | const StyledAvatar = styled.div<
17 | Pick & { size?: string }
18 | >`
19 | display: inline-block;
20 | box-sizing: border-box;
21 | object-fit: contain;
22 | ${({ size }) =>
23 | `
24 | height: ${size};
25 | width: ${size};
26 | `}
27 | border-radius: ${({ square }) => (square ? 0 : '50%')};
28 | overflow: hidden;
29 | ${({ noBorder, theme }) =>
30 | !noBorder &&
31 | `
32 | border-top: 2px solid ${theme.borderDark};
33 | border-left: 2px solid ${theme.borderDark};
34 | border-bottom: 2px solid ${theme.borderLightest};
35 | border-right: 2px solid ${theme.borderLightest};
36 | background: ${theme.material};
37 | `}
38 | ${({ src }) =>
39 | !src &&
40 | `
41 | display: flex;
42 | align-items: center;
43 | justify-content: space-around;
44 | font-weight: bold;
45 | font-size: 1rem;
46 | `}
47 | `;
48 |
49 | const StyledAvatarImg = styled.img`
50 | display: block;
51 | object-fit: contain;
52 | width: 100%;
53 | height: 100%;
54 | `;
55 |
56 | const Avatar = forwardRef(
57 | (
58 | {
59 | alt = '',
60 | children,
61 | noBorder = false,
62 | size = 35,
63 | square = false,
64 | src,
65 | ...otherProps
66 | },
67 | ref
68 | ) => {
69 | return (
70 |
78 | {src ? : children}
79 |
80 | );
81 | }
82 | );
83 |
84 | Avatar.displayName = 'Avatar';
85 |
86 | export { Avatar, AvatarProps };
87 |
--------------------------------------------------------------------------------
/src/ColorInput/ColorInput.spec.tsx:
--------------------------------------------------------------------------------
1 | import { fireEvent } from '@testing-library/react';
2 | import React from 'react';
3 | import { renderWithTheme } from '../../test/utils';
4 | import { ColorInput } from './ColorInput';
5 |
6 | function rgb2hex(str: string) {
7 | const rgb = str.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
8 | function hex(x: string) {
9 | return `0${parseInt(x, 10).toString(16)}`.slice(-2);
10 | }
11 | return rgb ? `#${hex(rgb[1])}${hex(rgb[2])}${hex(rgb[3])}` : '';
12 | }
13 |
14 | describe(' ', () => {
15 | it('should call handlers', () => {
16 | const color = '#f0f0dd';
17 | const onChange = jest.fn();
18 | const { container } = renderWithTheme( );
19 | const input = container.querySelector(`[type="color"]`) as HTMLInputElement;
20 | fireEvent.change(input, { target: { value: color } });
21 | expect(onChange).toBeCalledTimes(1);
22 | });
23 |
24 | it('should properly pass value to input element', () => {
25 | const color = '#f0f0dd';
26 | const { container } = renderWithTheme( );
27 | const input = container.querySelector(`[type="color"]`) as HTMLInputElement;
28 |
29 | expect(input.value).toBe(color);
30 | });
31 | it('should display current color', () => {
32 | const color = '#f0f0dd';
33 | const { getByRole } = renderWithTheme( );
34 | const colorPreview = getByRole('presentation');
35 | const displayedColor = window.getComputedStyle(
36 | colorPreview,
37 | null
38 | ).background;
39 |
40 | const displayedColorHex = rgb2hex(displayedColor);
41 | expect(displayedColorHex).toBe(color);
42 | });
43 |
44 | describe('prop: disabled', () => {
45 | it('should render disabled input', () => {
46 | const { container } = renderWithTheme( );
47 | const input = container.querySelector(`[type="color"]`);
48 |
49 | expect(input).toHaveAttribute('disabled');
50 | });
51 |
52 | it('should be overridden by props', () => {
53 | const { container, rerender } = renderWithTheme( );
54 | rerender( );
55 | const input = container.querySelector(`[type="color"]`);
56 |
57 | expect(input).not.toHaveAttribute('disabled');
58 | });
59 | });
60 | });
61 |
--------------------------------------------------------------------------------
/src/ColorInput/ColorInput.stories.tsx:
--------------------------------------------------------------------------------
1 | import { ComponentMeta } from '@storybook/react';
2 | import React from 'react';
3 | import styled from 'styled-components';
4 |
5 | import { ColorInput, ScrollView } from 'react95';
6 |
7 | const Wrapper = styled.div`
8 | background: ${({ theme }) => theme.material};
9 | padding: 5rem;
10 | & > span {
11 | margin-left: 1rem;
12 | margin-right: 0.5rem;
13 | }
14 | #cutout {
15 | background: ${({ theme }) => theme.canvas};
16 | display: inline-block;
17 | }
18 | .content {
19 | padding: 1rem;
20 | & > div {
21 | margin: 1rem 0;
22 | }
23 |
24 | & > div > span {
25 | margin-right: 0.5rem;
26 | }
27 | }
28 | `;
29 |
30 | export default {
31 | title: 'Controls/ColorInput',
32 | component: ColorInput,
33 | decorators: [story => {story()} ]
34 | } as ComponentMeta;
35 |
36 | export function Default() {
37 | return (
38 | <>
39 | enabled:
40 |
41 | disabled:
42 |
43 | >
44 | );
45 | }
46 |
47 | Default.story = {
48 | name: 'default'
49 | };
50 |
51 | export function Flat() {
52 | return (
53 |
54 |
55 |
56 | enabled:
57 |
58 |
59 |
60 | disabled:
61 |
62 |
63 |
64 |
65 | );
66 | }
67 |
68 | Flat.story = {
69 | name: 'flat'
70 | };
71 |
--------------------------------------------------------------------------------
/src/Counter/Counter.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { renderWithTheme } from '../../test/utils';
4 |
5 | import { Counter } from './Counter';
6 |
7 | describe(' ', () => {
8 | it('should render', () => {
9 | const { container } = renderWithTheme( );
10 | const counter = container.firstElementChild;
11 |
12 | expect(counter).toBeInTheDocument();
13 | });
14 |
15 | it('should handle custom style', () => {
16 | const { container } = renderWithTheme(
17 |
18 | );
19 | const counter = container.firstElementChild;
20 |
21 | expect(counter).toHaveAttribute('style', 'background-color: papayawhip;');
22 | });
23 |
24 | it('should handle custom props', () => {
25 | const customProps: React.HTMLAttributes = {
26 | title: 'potatoe'
27 | };
28 | const { container } = renderWithTheme( );
29 | const counter = container.firstElementChild;
30 |
31 | expect(counter).toHaveAttribute('title', 'potatoe');
32 | });
33 |
34 | describe('prop: minLength', () => {
35 | it('renders correct number of digits', () => {
36 | const { container } = renderWithTheme(
37 |
38 | );
39 | const counter = container.firstElementChild;
40 |
41 | expect(counter && counter.childElementCount).toBe(7);
42 | });
43 |
44 | it('value length takes priority if bigger than minLength', () => {
45 | const { container } = renderWithTheme(
46 |
47 | );
48 | const counter = container.firstElementChild;
49 |
50 | expect(counter && counter.childElementCount).toBe(4);
51 | });
52 | });
53 | });
54 |
--------------------------------------------------------------------------------
/src/Counter/Counter.stories.tsx:
--------------------------------------------------------------------------------
1 | import { ComponentMeta } from '@storybook/react';
2 | import React, { useState } from 'react';
3 | import { Button, Counter, Frame } from 'react95';
4 | import styled from 'styled-components';
5 |
6 | const Wrapper = styled.div`
7 | padding: 5rem;
8 | background: ${({ theme }) => theme.desktopBackground};
9 | .counter-wrapper {
10 | display: flex;
11 | margin-top: 1rem;
12 | }
13 | .counter-wrapper button {
14 | margin-left: 0.5rem;
15 | height: 51px;
16 | }
17 | .wrapper {
18 | padding: 1rem;
19 | }
20 | `;
21 |
22 | export default {
23 | title: 'Other/Counter',
24 | component: Counter,
25 | decorators: [story => {story()} ]
26 | } as ComponentMeta;
27 |
28 | export function Default() {
29 | const [count, setCount] = useState(13);
30 | const handleClick = () => setCount(count + 1);
31 | return (
32 |
33 |
34 |
35 |
36 |
37 | Click!
38 |
39 |
40 | );
41 | }
42 |
43 | Default.story = {
44 | name: 'default'
45 | };
46 |
--------------------------------------------------------------------------------
/src/Counter/Counter.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef, useMemo } from 'react';
2 | import styled from 'styled-components';
3 |
4 | import { createBorderStyles } from '../common';
5 | import { CommonStyledProps, Sizes } from '../types';
6 | import { Digit } from './Digit';
7 |
8 | type CounterProps = {
9 | minLength?: number;
10 | size?: Sizes | 'xl';
11 | value?: number;
12 | } & React.HTMLAttributes &
13 | CommonStyledProps;
14 |
15 | const CounterWrapper = styled.div`
16 | ${createBorderStyles({ style: 'status' })}
17 | display: inline-flex;
18 | background: #000000;
19 | `;
20 |
21 | const pixelSizes = {
22 | sm: 1,
23 | md: 2,
24 | lg: 3,
25 | xl: 4
26 | };
27 |
28 | const Counter = forwardRef(
29 | ({ value = 0, minLength = 3, size = 'md', ...otherProps }, ref) => {
30 | const digits = useMemo(
31 | () => value.toString().padStart(minLength, '0').split(''),
32 | [minLength, value]
33 | );
34 | return (
35 |
36 | {digits.map((digit, i) => (
37 |
38 | ))}
39 |
40 | );
41 | }
42 | );
43 |
44 | Counter.displayName = 'Counter';
45 |
46 | export { Counter, CounterProps };
47 |
--------------------------------------------------------------------------------
/src/DatePicker/DatePicker.stories.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable camelcase, react/jsx-pascal-case */
2 | import { ComponentMeta } from '@storybook/react';
3 | import React from 'react';
4 | import { DatePicker__UNSTABLE } from 'react95';
5 | import styled from 'styled-components';
6 |
7 | const Wrapper = styled.div`
8 | padding: 5rem;
9 | background: ${({ theme }) => theme.desktopBackground};
10 | `;
11 |
12 | export default {
13 | title: 'DatePicker__UNSTABLE',
14 | component: DatePicker__UNSTABLE,
15 | decorators: [story => {story()} ]
16 | } as ComponentMeta;
17 |
18 | export function Default() {
19 | return console.log(date)} />;
20 | }
21 |
22 | Default.story = {
23 | name: 'default'
24 | };
25 |
--------------------------------------------------------------------------------
/src/Frame/Frame.spec.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react';
2 | import React from 'react';
3 |
4 | import { Frame } from './Frame';
5 |
6 | describe(' ', () => {
7 | it('should render frame', () => {
8 | const { container } = render( );
9 | const frame = container.firstElementChild;
10 |
11 | expect(frame).toBeInTheDocument();
12 | });
13 |
14 | it('should render custom styles', () => {
15 | const { container } = render(
16 |
17 | );
18 | const frame = container.firstElementChild;
19 |
20 | expect(frame).toHaveAttribute('style', 'background-color: papayawhip;');
21 | });
22 |
23 | it('should render children', async () => {
24 | const { findByText } = render(
25 |
26 | Cool frame
27 |
28 | );
29 | const content = await findByText(/cool frame/i);
30 |
31 | expect(content).toBeInTheDocument();
32 | });
33 |
34 | it('should render custom props', () => {
35 | const customProps = { title: 'frame' };
36 | const { container } = render( );
37 | const frame = container.firstElementChild;
38 |
39 | expect(frame).toHaveAttribute('title', 'frame');
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/src/Frame/Frame.stories.tsx:
--------------------------------------------------------------------------------
1 | import { ComponentMeta } from '@storybook/react';
2 | import React from 'react';
3 | import { Frame } from 'react95';
4 | import styled from 'styled-components';
5 |
6 | const Wrapper = styled.div`
7 | padding: 5rem;
8 | background: ${({ theme }) => theme.material};
9 | #default-buttons button {
10 | margin-bottom: 1rem;
11 | margin-right: 1rem;
12 | }
13 |
14 | #cutout {
15 | background: ${({ theme }) => theme.canvas};
16 | padding: 1rem;
17 | width: 300px;
18 | }
19 | `;
20 |
21 | export default {
22 | title: 'Layout/Frame',
23 | component: Frame,
24 | decorators: [story => {story()} ]
25 | } as ComponentMeta;
26 |
27 | export function Default() {
28 | return (
29 |
34 |
35 | This is a frame of the 'window' variant, the default. Notice
36 | the subtle difference in borders. The lightest border is not on the edge
37 | of this frame.
38 |
39 |
40 | This frame of the 'button' variant on the other hand has the
41 | lightest border on the edge. Use this frame inside 'window'
42 | frames.
43 |
44 |
53 | A field frame variant is used to display content.
54 |
55 |
56 |
60 | The 'status' variant of a frame is often used as a status bar
61 | at the end of the window.
62 |
63 |
64 | );
65 | }
66 |
67 | Default.story = {
68 | name: 'default'
69 | };
70 |
--------------------------------------------------------------------------------
/src/Frame/Frame.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import styled, { css } from 'styled-components';
3 | import { createBorderStyles, createBoxStyles } from '../common';
4 | import { CommonStyledProps } from '../types';
5 |
6 | type FrameProps = {
7 | children?: React.ReactNode;
8 | shadow?: boolean;
9 | } & (
10 | | {
11 | variant?: 'window' | 'button' | 'field' | 'status';
12 | }
13 | | {
14 | /** @deprecated Use 'window', 'button' or 'status' */
15 | variant?: 'outside' | 'inside' | 'well';
16 | }
17 | ) &
18 | React.HTMLAttributes &
19 | CommonStyledProps;
20 |
21 | const createFrameStyles = (variant: FrameProps['variant']) => {
22 | switch (variant) {
23 | case 'status':
24 | case 'well':
25 | return css`
26 | ${createBorderStyles({ style: 'status' })}
27 | `;
28 | case 'window':
29 | case 'outside':
30 | return css`
31 | ${createBorderStyles({ style: 'window' })}
32 | `;
33 | case 'field':
34 | return css`
35 | ${createBorderStyles({ style: 'field' })}
36 | `;
37 | default:
38 | return css`
39 | ${createBorderStyles()}
40 | `;
41 | }
42 | };
43 |
44 | const StyledFrame = styled.div>>`
45 | position: relative;
46 | font-size: 1rem;
47 | ${({ variant }) => createFrameStyles(variant)}
48 | ${({ variant }) =>
49 | createBoxStyles(
50 | variant === 'field'
51 | ? { background: 'canvas', color: 'canvasText' }
52 | : undefined
53 | )}
54 | `;
55 |
56 | const Frame = forwardRef(
57 | ({ children, shadow = false, variant = 'window', ...otherProps }, ref) => {
58 | return (
59 |
60 | {children}
61 |
62 | );
63 | }
64 | );
65 |
66 | Frame.displayName = 'Frame';
67 |
68 | export { Frame, FrameProps };
69 |
--------------------------------------------------------------------------------
/src/GroupBox/GroupBox.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { renderWithTheme, theme } from '../../test/utils';
4 |
5 | import { GroupBox } from './GroupBox';
6 |
7 | describe(' ', () => {
8 | it('renders GroupBox', () => {
9 | const { container } = renderWithTheme( );
10 | const groupBox = container.firstChild as HTMLFieldSetElement;
11 |
12 | expect(groupBox).toBeInTheDocument();
13 | });
14 | it('renders children', () => {
15 | const textContent = 'Hi there!';
16 | const { getByText } = renderWithTheme(
17 |
18 | {textContent}
19 |
20 | );
21 | expect(getByText(textContent)).toBeInTheDocument();
22 | });
23 |
24 | describe('prop: label', () => {
25 | it('renders Label', () => {
26 | const labelText = 'Name:';
27 | const { container } = renderWithTheme( );
28 | const groupBox = container.firstChild as HTMLFieldSetElement;
29 | const legend = groupBox.querySelector('legend');
30 | expect(legend?.textContent).toBe(labelText);
31 | });
32 | it('when not provided, element is not rendered', () => {
33 | const { container } = renderWithTheme( );
34 | const groupBox = container.firstChild as HTMLFieldSetElement;
35 | const legend = groupBox.querySelector('legend');
36 | expect(legend).not.toBeInTheDocument();
37 | });
38 | });
39 | describe('prop: disabled', () => {
40 | it('renders with disabled text content', () => {
41 | const { container } = renderWithTheme( );
42 | const groupBox = container.firstChild as HTMLFieldSetElement;
43 |
44 | expect(groupBox).toHaveAttribute('aria-disabled', 'true');
45 |
46 | expect(groupBox).toHaveStyleRule('color', theme.materialTextDisabled);
47 | expect(groupBox).toHaveStyleRule(
48 | 'text-shadow',
49 | `1px 1px ${theme.materialTextDisabledShadow}`
50 | );
51 | });
52 | });
53 | });
54 |
--------------------------------------------------------------------------------
/src/GroupBox/GroupBox.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import styled, { css } from 'styled-components';
3 | import { createDisabledTextStyles } from '../common';
4 | import { CommonStyledProps } from '../types';
5 |
6 | type GroupBoxProps = {
7 | label?: React.ReactNode;
8 | children?: React.ReactNode;
9 | disabled?: boolean;
10 | variant?: 'default' | 'flat';
11 | } & React.FieldsetHTMLAttributes &
12 | CommonStyledProps;
13 |
14 | const StyledFieldset = styled.fieldset<
15 | Pick & { $disabled: boolean }
16 | >`
17 | position: relative;
18 | border: 2px solid
19 | ${({ theme, variant }) =>
20 | variant === 'flat' ? theme.flatDark : theme.borderLightest};
21 | padding: 16px;
22 | margin-top: 8px;
23 | font-size: 1rem;
24 | color: ${({ theme }) => theme.materialText};
25 | ${({ variant }) =>
26 | variant !== 'flat' &&
27 | css`
28 | box-shadow: -1px -1px 0 1px ${({ theme }) => theme.borderDark},
29 | inset -1px -1px 0 1px ${({ theme }) => theme.borderDark};
30 | `}
31 | ${props => props.$disabled && createDisabledTextStyles()}
32 | `;
33 |
34 | const StyledLegend = styled.legend>`
35 | display: flex;
36 | position: absolute;
37 | top: 0;
38 | left: 8px;
39 | transform: translateY(calc(-50% - 2px));
40 | padding: 0 8px;
41 |
42 | font-size: 1rem;
43 | background: ${({ theme, variant }) =>
44 | variant === 'flat' ? theme.canvas : theme.material};
45 | `;
46 |
47 | const GroupBox = forwardRef(
48 | (
49 | { label, disabled = false, variant = 'default', children, ...otherProps },
50 | ref
51 | ) => {
52 | return (
53 |
60 | {label && {label} }
61 | {children}
62 |
63 | );
64 | }
65 | );
66 |
67 | GroupBox.displayName = 'GroupBox';
68 |
69 | export { GroupBox, GroupBoxProps };
70 |
--------------------------------------------------------------------------------
/src/Handle/Handle.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { renderWithTheme } from '../../test/utils';
4 |
5 | import { Handle } from './Handle';
6 |
7 | describe(' ', () => {
8 | it('should render bar', () => {
9 | const { container } = renderWithTheme( );
10 | const barEl = container.firstChild;
11 |
12 | expect(barEl).toBeInTheDocument();
13 | });
14 |
15 | it('should handle custom style', () => {
16 | const { container } = renderWithTheme(
17 |
18 | );
19 | const barEl = container.firstChild;
20 |
21 | expect(barEl).toHaveAttribute('style', 'background-color: papayawhip;');
22 | });
23 |
24 | it('should handle custom props', () => {
25 | const customProps = { title: 'potatoe' };
26 | const { container } = renderWithTheme( );
27 | const barEl = container.firstChild;
28 |
29 | expect(barEl).toHaveAttribute('title', 'potatoe');
30 | });
31 |
32 | describe('prop: size', () => {
33 | it('should set proper size', () => {
34 | const { container } = renderWithTheme( );
35 | const barEl = container.firstChild;
36 |
37 | expect(barEl).toHaveStyleRule('height', '85%');
38 | });
39 |
40 | it('when passed a number, sets size in px', () => {
41 | const { container } = renderWithTheme( );
42 | const barEl = container.firstChild;
43 |
44 | expect(barEl).toHaveStyleRule('height', '25px');
45 | });
46 | });
47 | });
48 |
--------------------------------------------------------------------------------
/src/Handle/Handle.stories.tsx:
--------------------------------------------------------------------------------
1 | import { ComponentMeta } from '@storybook/react';
2 | import React from 'react';
3 | import { AppBar, Button, Handle, Toolbar } from 'react95';
4 | import styled from 'styled-components';
5 |
6 | const Wrapper = styled.div`
7 | padding: 5rem;
8 | background: ${({ theme }) => theme.desktopBackground};
9 | `;
10 |
11 | export default {
12 | title: 'Controls/Handle',
13 | component: Handle,
14 | decorators: [story => {story()} ]
15 | } as ComponentMeta;
16 |
17 | export function Default() {
18 | return (
19 |
20 |
21 |
22 | Edit
23 |
24 | Save
25 |
26 |
27 |
28 |
29 | );
30 | }
31 |
32 | Default.story = {
33 | name: 'default'
34 | };
35 |
--------------------------------------------------------------------------------
/src/Handle/Handle.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styled from 'styled-components';
3 | import { CommonStyledProps } from '../types';
4 | import { getSize } from '../common/utils';
5 |
6 | type HandleProps = {
7 | size?: string | number;
8 | } & React.HTMLAttributes &
9 | CommonStyledProps;
10 |
11 | // TODO: add horizontal variant
12 | // TODO: allow user to specify number of bars (like 3 horizontal bars for drag handle)
13 | const Handle = styled.div`
14 | ${({ theme, size = '100%' }) => `
15 | display: inline-block;
16 | box-sizing: border-box;
17 | height: ${getSize(size)};
18 | width: 5px;
19 | border-top: 2px solid ${theme.borderLightest};
20 | border-left: 2px solid ${theme.borderLightest};
21 | border-bottom: 2px solid ${theme.borderDark};
22 | border-right: 2px solid ${theme.borderDark};
23 | background: ${theme.material};
24 | `}
25 | `;
26 |
27 | Handle.displayName = 'Handle';
28 |
29 | export { Handle, HandleProps };
30 |
--------------------------------------------------------------------------------
/src/Hourglass/Hourglass.spec.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react';
2 | import React from 'react';
3 |
4 | import { Hourglass } from './Hourglass';
5 |
6 | describe(' ', () => {
7 | it('should render hourglass', () => {
8 | const { container } = render( );
9 | const hourglass = container.firstElementChild;
10 |
11 | expect(hourglass).toBeInTheDocument();
12 | });
13 |
14 | it('should render correct size', () => {
15 | const { container } = render( );
16 | const hourglass = container.firstElementChild;
17 |
18 | const computedStyles = hourglass
19 | ? window.getComputedStyle(hourglass)
20 | : null;
21 | expect(computedStyles?.width).toBe('66px');
22 | expect(computedStyles?.height).toBe('66px');
23 | });
24 |
25 | it('should handle custom props', () => {
26 | const customProps: React.HTMLAttributes = {
27 | title: 'hourglass'
28 | };
29 | const { container } = render( );
30 | const hourglass = container.firstElementChild;
31 |
32 | expect(hourglass).toHaveAttribute('title', 'hourglass');
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/src/Hourglass/Hourglass.stories.tsx:
--------------------------------------------------------------------------------
1 | import { ComponentMeta } from '@storybook/react';
2 | import React from 'react';
3 | import { Hourglass } from 'react95';
4 | import styled from 'styled-components';
5 |
6 | const Wrapper = styled.div`
7 | padding: 5rem;
8 | background: ${({ theme }) => theme.desktopBackground};
9 | `;
10 |
11 | export default {
12 | title: 'Other/Hourglass',
13 | component: Hourglass,
14 | decorators: [story => {story()} ]
15 | } as ComponentMeta;
16 |
17 | export function Default() {
18 | return ;
19 | }
20 |
21 | Default.story = {
22 | name: 'default'
23 | };
24 |
--------------------------------------------------------------------------------
/src/Hourglass/Hourglass.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import styled from 'styled-components';
3 | import { getSize } from '../common/utils';
4 | import { CommonStyledProps } from '../types';
5 | import base64hourglass from './base64hourglass';
6 |
7 | type HourglassProps = {
8 | size?: string | number;
9 | } & React.HTMLAttributes &
10 | CommonStyledProps;
11 |
12 | const StyledContainer = styled.div>>`
13 | display: inline-block;
14 | height: ${({ size }) => getSize(size)};
15 | width: ${({ size }) => getSize(size)};
16 | `;
17 |
18 | const StyledHourglass = styled.span`
19 | display: block;
20 | background: ${base64hourglass};
21 | background-size: cover;
22 | width: 100%;
23 | height: 100%;
24 | `;
25 |
26 | const Hourglass = forwardRef(
27 | ({ size = 30, ...otherProps }, ref) => {
28 | return (
29 |
30 |
31 |
32 | );
33 | }
34 | );
35 |
36 | Hourglass.displayName = 'Hourglass';
37 |
38 | export { Hourglass, HourglassProps };
39 |
--------------------------------------------------------------------------------
/src/MenuList/MenuList.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { renderWithTheme } from '../../test/utils';
4 |
5 | import { MenuList } from './MenuList';
6 |
7 | describe(' ', () => {
8 | it('renders MenuList', () => {
9 | const { container } = renderWithTheme( );
10 | const menuList = container.firstElementChild;
11 |
12 | expect(menuList).toBeInTheDocument();
13 | });
14 | it('is an ul', () => {
15 | const { container } = renderWithTheme( );
16 | const menuList = container.firstElementChild;
17 |
18 | expect(menuList?.tagName).toBe('UL');
19 | });
20 | it('renders children', () => {
21 | const textContent = 'Hi there!';
22 | const { getByText } = renderWithTheme(
23 |
24 | {textContent}
25 |
26 | );
27 | expect(getByText(textContent)).toBeInTheDocument();
28 | });
29 |
30 | describe('prop: inline', () => {
31 | it('renders inline', () => {
32 | const { container } = renderWithTheme( );
33 | const menuList = container.firstElementChild;
34 |
35 | expect(menuList).toHaveStyleRule('display', 'inline-flex');
36 | expect(menuList).toHaveStyleRule('align-items', 'center');
37 | });
38 | });
39 | describe('prop: fullWidth', () => {
40 | it('has 100% width', () => {
41 | const { container } = renderWithTheme( );
42 | const menuList = container.firstElementChild;
43 |
44 | expect(menuList).toHaveStyleRule('width', '100%');
45 | });
46 | });
47 | });
48 |
--------------------------------------------------------------------------------
/src/MenuList/MenuList.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import styled from 'styled-components';
4 | import { createBorderStyles, createBoxStyles } from '../common';
5 | import { CommonStyledProps } from '../types';
6 |
7 | type MenuListProps = React.HTMLAttributes & {
8 | fullWidth?: boolean;
9 | shadow?: boolean;
10 | inline?: boolean;
11 | } & CommonStyledProps;
12 |
13 | // TODO keyboard controls
14 | const MenuList = styled.ul.attrs(() => ({
15 | role: 'menu'
16 | }))`
17 | box-sizing: border-box;
18 | width: ${props => (props.fullWidth ? '100%' : 'auto')};
19 | padding: 4px;
20 | ${createBorderStyles({ style: 'window' })}
21 | ${createBoxStyles()}
22 | ${props =>
23 | props.inline &&
24 | `
25 | display: inline-flex;
26 | align-items: center;
27 | `}
28 | list-style: none;
29 | position: relative;
30 | `;
31 |
32 | MenuList.displayName = 'MenuList';
33 |
34 | export * from './MenuListItem';
35 |
36 | export { MenuList, MenuListProps };
37 |
--------------------------------------------------------------------------------
/src/Monitor/Monitor.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { renderWithTheme } from '../../test/utils';
4 |
5 | import { Monitor } from './Monitor';
6 |
7 | describe(' ', () => {
8 | it('should render', () => {
9 | const { container } = renderWithTheme( );
10 | const monitorElement = container.firstElementChild;
11 |
12 | expect(monitorElement).toBeInTheDocument();
13 | });
14 |
15 | it('should handle custom props', () => {
16 | const customProps: React.HTMLAttributes = {
17 | title: 'potatoe'
18 | };
19 | const { container } = renderWithTheme( );
20 | const monitorElement = container.firstElementChild;
21 |
22 | expect(monitorElement).toHaveAttribute('title', 'potatoe');
23 | });
24 |
25 | describe('prop: backgroundStyles', () => {
26 | it('should forward styles to background element', () => {
27 | const { getByTestId } = renderWithTheme(
28 |
29 | );
30 | const backgroundElement = getByTestId('background');
31 |
32 | expect(backgroundElement).toHaveAttribute(
33 | 'style',
34 | 'background-color: papayawhip;'
35 | );
36 | });
37 | });
38 |
39 | describe('prop: children', () => {
40 | it('children should be rendered in background element', () => {
41 | const { getByTestId } = renderWithTheme(Hi! );
42 | const backgroundElement = getByTestId('background');
43 |
44 | expect(backgroundElement.innerHTML).toBe('Hi!');
45 | });
46 | });
47 | });
48 |
--------------------------------------------------------------------------------
/src/Monitor/Monitor.stories.tsx:
--------------------------------------------------------------------------------
1 | import { ComponentMeta } from '@storybook/react';
2 | import React from 'react';
3 | import { Monitor } from 'react95';
4 | import styled from 'styled-components';
5 |
6 | const Wrapper = styled.div`
7 | padding: 5rem;
8 | background: ${({ theme }) => theme.desktopBackground};
9 | `;
10 |
11 | export default {
12 | title: 'Other/Monitor',
13 | component: Monitor,
14 | decorators: [story => {story()} ]
15 | } as ComponentMeta;
16 |
17 | export function Default() {
18 | return ;
19 | }
20 |
21 | Default.story = {
22 | name: 'default'
23 | };
24 |
--------------------------------------------------------------------------------
/src/NumberInput/NumberInput.stories.tsx:
--------------------------------------------------------------------------------
1 | import { ComponentMeta } from '@storybook/react';
2 | import React from 'react';
3 | import { ScrollView, NumberInput } from 'react95';
4 | import styled from 'styled-components';
5 |
6 | const Wrapper = styled.div`
7 | background: ${({ theme }) => theme.material};
8 | padding: 5rem;
9 | & > * {
10 | margin-bottom: 1rem;
11 | }
12 |
13 | #cutout {
14 | background: ${({ theme }) => theme.canvas};
15 | padding: 2rem;
16 | width: 300px;
17 | & > div > * {
18 | margin-bottom: 1rem;
19 | }
20 | }
21 | `;
22 |
23 | export default {
24 | title: 'Controls/NumberInput',
25 | component: NumberInput,
26 | decorators: [story => {story()} ]
27 | } as ComponentMeta;
28 |
29 | export function Default() {
30 | return (
31 | <>
32 |
33 |
34 |
35 |
36 |
37 | >
38 | );
39 | }
40 |
41 | Default.story = {
42 | name: 'default'
43 | };
44 |
45 | export function Flat() {
46 | return (
47 |
48 |
49 | When you want to use NumberInput on a light background (like scrollable
50 | content), just use the flat variant:
51 |
52 |
59 |
60 |
61 |
62 |
63 |
64 | );
65 | }
66 |
67 | Flat.story = {
68 | name: 'flat'
69 | };
70 |
--------------------------------------------------------------------------------
/src/ScrollView/ScrollView.spec.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react';
2 | import React from 'react';
3 |
4 | import { ScrollView } from './ScrollView';
5 |
6 | describe(' ', () => {
7 | it('should render scrollview', () => {
8 | const { container } = render( );
9 | const scrollView = container.firstElementChild;
10 |
11 | expect(scrollView).toBeInTheDocument();
12 | });
13 |
14 | it('should render custom styles', () => {
15 | const { container } = render(
16 |
17 | );
18 | const scrollView = container.firstElementChild;
19 |
20 | expect(scrollView).toHaveAttribute(
21 | 'style',
22 | 'background-color: papayawhip;'
23 | );
24 | });
25 |
26 | it('should render children', async () => {
27 | const { findByText } = render(
28 |
29 | Cool ScrollView
30 |
31 | );
32 | const content = await findByText(/cool scrollview/i);
33 |
34 | expect(content).toBeInTheDocument();
35 | });
36 |
37 | it('should render custom props', () => {
38 | const customProps = { title: 'scrollview' };
39 | const { container } = render( );
40 | const scrollView = container.firstElementChild;
41 |
42 | expect(scrollView).toHaveAttribute('title', 'scrollview');
43 | });
44 | });
45 |
--------------------------------------------------------------------------------
/src/ScrollView/ScrollView.stories.tsx:
--------------------------------------------------------------------------------
1 | import { ComponentMeta } from '@storybook/react';
2 | import React from 'react';
3 | import { ScrollView, Window, WindowContent } from 'react95';
4 | import styled from 'styled-components';
5 |
6 | const Wrapper = styled.div`
7 | padding: 5rem;
8 | background: ${({ theme }) => theme.desktopBackground};
9 | `;
10 |
11 | export default {
12 | title: 'Layout/ScrollView',
13 | component: ScrollView,
14 | decorators: [story => {story()} ]
15 | } as ComponentMeta;
16 |
17 | export function Default() {
18 | return (
19 |
20 |
21 |
22 |
23 |
24 | React95 is the best UI library ever created
25 |
26 |
React95 is the best UI library ever created
27 |
React95 is the best UI library ever created
28 |
React95 is the best UI library ever created
29 |
React95 is the best UI library ever created
30 |
React95 is the best UI library ever created
31 |
React95 is the best UI library ever created
32 |
React95 is the best UI library ever created
33 |
React95 is the best UI library ever created
34 |
35 |
36 |
37 |
38 | );
39 | }
40 |
41 | Default.story = {
42 | name: 'default'
43 | };
44 |
--------------------------------------------------------------------------------
/src/ScrollView/ScrollView.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import styled from 'styled-components';
3 | import { insetShadow, createScrollbars } from '../common';
4 | import { CommonStyledProps } from '../types';
5 |
6 | type ScrollViewProps = {
7 | children?: React.ReactNode;
8 | shadow?: boolean;
9 | } & React.HTMLAttributes &
10 | CommonStyledProps;
11 |
12 | export const StyledScrollView = styled.div>`
13 | position: relative;
14 | box-sizing: border-box;
15 | padding: 2px;
16 | font-size: 1rem;
17 | border-style: solid;
18 | border-width: 2px;
19 | border-left-color: ${({ theme }) => theme.borderDark};
20 | border-top-color: ${({ theme }) => theme.borderDark};
21 | border-right-color: ${({ theme }) => theme.borderLightest};
22 | border-bottom-color: ${({ theme }) => theme.borderLightest};
23 | line-height: 1.5;
24 | &:before {
25 | position: absolute;
26 | left: 0;
27 | top: 0;
28 | content: '';
29 | width: calc(100% - 4px);
30 | height: calc(100% - 4px);
31 |
32 | border-style: solid;
33 | border-width: 2px;
34 | border-left-color: ${({ theme }) => theme.borderDarkest};
35 | border-top-color: ${({ theme }) => theme.borderDarkest};
36 | border-right-color: ${({ theme }) => theme.borderLight};
37 | border-bottom-color: ${({ theme }) => theme.borderLight};
38 |
39 | pointer-events: none;
40 | ${props => props.shadow && `box-shadow:${insetShadow};`}
41 | }
42 | `;
43 |
44 | const Content = styled.div`
45 | box-sizing: border-box;
46 | width: 100%;
47 | height: 100%;
48 | padding: 4px;
49 | overflow: auto;
50 | ${createScrollbars()}
51 | `;
52 |
53 | const ScrollView = forwardRef(
54 | ({ children, shadow = true, ...otherProps }, ref) => {
55 | return (
56 |
57 | {children}
58 |
59 | );
60 | }
61 | );
62 |
63 | ScrollView.displayName = 'ScrollView';
64 |
65 | export { ScrollView, ScrollViewProps };
66 |
--------------------------------------------------------------------------------
/src/Select/Select.types.ts:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { HTMLDataAttributes } from '../types';
3 |
4 | type SelectChangeEventTargetValue = { value: T; name: string | undefined };
5 |
6 | export type SelectChangeEvent =
7 | | (Omit, 'target'> & {
8 | target: Omit<
9 | React.ChangeEvent['target'],
10 | 'name' | 'value'
11 | > &
12 | SelectChangeEventTargetValue;
13 | })
14 | | (Omit & {
15 | target: Omit &
16 | SelectChangeEventTargetValue;
17 | });
18 |
19 | export type SelectOption = {
20 | label?: string;
21 | value: T;
22 | };
23 |
24 | export type SelectRef = Pick & {
25 | node: HTMLInputElement | null;
26 | };
27 |
28 | export type SelectVariants = 'default' | 'flat';
29 |
30 | export type SelectFormatDisplayCallback = (
31 | option: SelectOption
32 | ) => string;
33 |
34 | export type SelectCommonProps = {
35 | 'aria-label'?: string;
36 | 'aria-labelledby'?: string;
37 | className?: string;
38 | defaultValue?: T;
39 | disabled?: boolean;
40 | name?: string;
41 | onChange?: (
42 | selectedOption: SelectOption,
43 | options: {
44 | fromEvent: Event | React.SyntheticEvent;
45 | }
46 | ) => void;
47 | options?: (SelectOption | null | undefined)[];
48 | readOnly?: boolean;
49 | shadow?: boolean;
50 | style?: React.CSSProperties;
51 | value?: T;
52 | variant?: SelectVariants;
53 | width?: React.CSSProperties['width'];
54 | };
55 |
56 | export type SelectInnerProps = {
57 | formatDisplay?: SelectFormatDisplayCallback;
58 | inputProps?: React.HTMLAttributes & HTMLDataAttributes;
59 | /** @deprecated Use `aria-labelledby` instead */
60 | labelId?: string;
61 | menuMaxHeight?: string | number;
62 | onClose?: (options: { fromEvent: Event | React.SyntheticEvent }) => void;
63 | onOpen?: (options: { fromEvent: Event | React.SyntheticEvent }) => void;
64 | open?: boolean;
65 | } & Pick<
66 | React.HTMLAttributes,
67 | 'onBlur' | 'onFocus' | 'onKeyDown' | 'onMouseDown'
68 | > &
69 | SelectCommonProps;
70 |
--------------------------------------------------------------------------------
/src/Select/useSelectCommon.tsx:
--------------------------------------------------------------------------------
1 | import React, { useMemo } from 'react';
2 | import useControlledOrUncontrolled from '../common/hooks/useControlledOrUncontrolled';
3 | import {
4 | StyledDropdownButton,
5 | StyledDropdownIcon,
6 | StyledFlatSelectWrapper,
7 | StyledSelectWrapper
8 | } from './Select.styles';
9 |
10 | import { SelectCommonProps, SelectOption } from './Select.types';
11 |
12 | const emptyArray: [] = [];
13 |
14 | export const useSelectCommon = ({
15 | className,
16 | defaultValue,
17 | disabled,
18 | native,
19 | onChange,
20 | options: optionsProp = emptyArray,
21 | readOnly,
22 | style,
23 | value: valueProp,
24 | variant,
25 | width
26 | }: { native: boolean } & SelectCommonProps) => {
27 | const options = useMemo(
28 | () => optionsProp.filter(Boolean) as SelectOption[],
29 | [optionsProp]
30 | );
31 |
32 | const [value, setValue] = useControlledOrUncontrolled({
33 | defaultValue: defaultValue ?? options?.[0]?.value,
34 | onChange,
35 | readOnly,
36 | value: valueProp
37 | });
38 |
39 | const isEnabled = !(disabled || readOnly);
40 |
41 | const wrapperProps: React.HTMLAttributes = useMemo(
42 | () => ({
43 | className,
44 | style: { ...style, width }
45 | }),
46 | [className, style, width]
47 | );
48 |
49 | const DropdownButton = useMemo(
50 | () => (
51 |
59 |
60 |
61 | ),
62 | [disabled, native, variant]
63 | );
64 |
65 | const Wrapper = useMemo(
66 | () => (variant === 'flat' ? StyledFlatSelectWrapper : StyledSelectWrapper),
67 | [variant]
68 | );
69 |
70 | return useMemo(
71 | () => ({
72 | isEnabled,
73 | options,
74 | value,
75 | setValue,
76 | wrapperProps,
77 | DropdownButton,
78 | Wrapper
79 | }),
80 | [DropdownButton, Wrapper, isEnabled, options, setValue, value, wrapperProps]
81 | );
82 | };
83 |
--------------------------------------------------------------------------------
/src/Separator/Separator.stories.tsx:
--------------------------------------------------------------------------------
1 | import { ComponentMeta } from '@storybook/react';
2 | import React from 'react';
3 | import styled from 'styled-components';
4 |
5 | import { MenuList, MenuListItem, Separator } from 'react95';
6 |
7 | const Wrapper = styled.div`
8 | padding: 5rem;
9 | background: ${({ theme }) => theme.desktopBackground};
10 | `;
11 |
12 | export default {
13 | title: 'Layout/Separator',
14 | component: Separator,
15 | decorators: [story => {story()} ]
16 | } as ComponentMeta;
17 |
18 | export function Default() {
19 | return (
20 | <>
21 |
22 | Item 1
23 |
24 | Item 2
25 |
26 | Item 3
27 |
28 |
29 | Item 1
30 |
31 | Item 2
32 |
33 | Item 3
34 |
35 | >
36 | );
37 | }
38 |
39 | Default.story = {
40 | name: 'default'
41 | };
42 |
--------------------------------------------------------------------------------
/src/Separator/Separator.tsx:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import { getSize } from '../common/utils';
3 | import { Orientation } from '../types';
4 |
5 | type SeparatorProps = {
6 | size?: string | number;
7 | orientation?: Orientation;
8 | };
9 |
10 | const Separator = styled.div`
11 | ${({ orientation, theme, size = '100%' }) =>
12 | orientation === 'vertical'
13 | ? `
14 | height: ${getSize(size)};
15 | border-left: 2px solid ${theme.borderDark};
16 | border-right: 2px solid ${theme.borderLightest};
17 | margin: 0;
18 | `
19 | : `
20 | width: ${getSize(size)};
21 | border-bottom: 2px solid ${theme.borderLightest};
22 | border-top: 2px solid ${theme.borderDark};
23 | margin: 0;
24 | `}
25 | `;
26 |
27 | Separator.displayName = 'Separator';
28 |
29 | export { Separator, SeparatorProps };
30 |
--------------------------------------------------------------------------------
/src/Table/Table.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { renderWithTheme } from '../../test/utils';
4 |
5 | import { Table } from './Table';
6 |
7 | describe('', () => {
8 | it('renders Table', () => {
9 | const { container } = renderWithTheme();
10 | const table = container.firstElementChild;
11 |
12 | expect(table).toBeInTheDocument();
13 | });
14 | it('renders table element', () => {
15 | const { getByRole } = renderWithTheme();
16 |
17 | expect(getByRole('table')).toBeInTheDocument();
18 | });
19 | it('renders children', () => {
20 | const { getByTestId } = renderWithTheme(
21 |
24 | );
25 | expect(getByTestId('children')).toBeInTheDocument();
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/src/Table/Table.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import styled from 'styled-components';
3 | import { StyledScrollView } from '../ScrollView/ScrollView';
4 | import { CommonStyledProps } from '../types';
5 |
6 | type TableProps = {
7 | children?: React.ReactNode;
8 | } & React.TableHTMLAttributes &
9 | CommonStyledProps;
10 |
11 | const StyledTable = styled.table`
12 | display: table;
13 | width: 100%;
14 | border-collapse: collapse;
15 | border-spacing: 0;
16 | font-size: 1rem;
17 | `;
18 |
19 | const Wrapper = styled(StyledScrollView)`
20 | &:before {
21 | box-shadow: none;
22 | }
23 | `;
24 |
25 | const Table = forwardRef(
26 | ({ children, ...otherProps }, ref) => {
27 | return (
28 |
29 |
30 | {children}
31 |
32 |
33 | );
34 | }
35 | );
36 |
37 | Table.displayName = 'Table';
38 |
39 | export * from './TableBody';
40 | export * from './TableDataCell';
41 | export * from './TableHead';
42 | export * from './TableHeadCell';
43 | export * from './TableRow';
44 |
45 | export { Table, TableProps };
46 |
--------------------------------------------------------------------------------
/src/Table/TableBody.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { renderWithTheme } from '../../test/utils';
4 |
5 | import { TableBody } from './TableBody';
6 |
7 | describe(' ', () => {
8 | function mountInTable(node: React.ReactNode) {
9 | const { container, getByTestId } = renderWithTheme();
10 | return {
11 | tbody: container.querySelector('table')?.firstElementChild,
12 | getByTestId
13 | };
14 | }
15 |
16 | it('renders TableBody', () => {
17 | const { tbody } = mountInTable( );
18 |
19 | expect(tbody).toBeInTheDocument();
20 | expect(tbody?.tagName).toBe('TBODY');
21 | });
22 |
23 | it('renders children', () => {
24 | const children = ;
25 | const { getByTestId } = mountInTable({children} );
26 | expect(getByTestId('tr')).toBeInTheDocument();
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/src/Table/TableBody.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import styled from 'styled-components';
3 | import { insetShadow } from '../common';
4 | import { CommonStyledProps } from '../types';
5 |
6 | type TableBodyProps = {
7 | children?: React.ReactNode;
8 | } & React.HTMLAttributes &
9 | CommonStyledProps;
10 |
11 | const StyledTableBody = styled.tbody`
12 | background: ${({ theme }) => theme.canvas};
13 | display: table-row-group;
14 | box-shadow: ${insetShadow};
15 | overflow-y: auto;
16 | `;
17 |
18 | const TableBody = forwardRef(
19 | function TableBody({ children, ...otherProps }, ref) {
20 | return (
21 |
22 | {children}
23 |
24 | );
25 | }
26 | );
27 |
28 | TableBody.displayName = 'TableBody';
29 |
30 | export { TableBody, TableBodyProps };
31 |
--------------------------------------------------------------------------------
/src/Table/TableDataCell.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { renderWithTheme } from '../../test/utils';
4 |
5 | import { TableDataCell } from './TableDataCell';
6 |
7 | describe(' ', () => {
8 | function mountInTable(node: React.ReactNode) {
9 | const { container, getByText } = renderWithTheme(
10 |
11 |
12 | {node}
13 |
14 |
15 | );
16 | return {
17 | td: container.querySelector('tr')?.firstElementChild,
18 | getByText
19 | };
20 | }
21 |
22 | it('renders TableDataCell', () => {
23 | const { td } = mountInTable( );
24 | expect(td?.tagName).toBe('TD');
25 | });
26 |
27 | it('renders children', () => {
28 | const { getByText } = mountInTable(children );
29 | expect(getByText('children')).toBeInTheDocument();
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/src/Table/TableDataCell.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import styled from 'styled-components';
3 | import { CommonStyledProps } from '../types';
4 |
5 | type TableDataCellProps = {
6 | children?: React.ReactNode;
7 | } & React.HTMLAttributes &
8 | CommonStyledProps;
9 |
10 | const StyledTd = styled.td`
11 | padding: 0 8px;
12 | `;
13 |
14 | const TableDataCell = forwardRef(
15 | function TableDataCell({ children, ...otherProps }, ref) {
16 | return (
17 |
18 | {children}
19 |
20 | );
21 | }
22 | );
23 |
24 | TableDataCell.displayName = 'TableDataCell';
25 |
26 | export { TableDataCell, TableDataCellProps };
27 |
--------------------------------------------------------------------------------
/src/Table/TableHead.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { renderWithTheme } from '../../test/utils';
4 |
5 | import { TableHead } from './TableHead';
6 |
7 | describe(' ', () => {
8 | function mountInTable(node: React.ReactNode) {
9 | const { container, getByTestId } = renderWithTheme();
10 | return {
11 | tbody: container.querySelector('table')?.firstElementChild,
12 | getByTestId
13 | };
14 | }
15 |
16 | it('renders TableHead', () => {
17 | const { tbody } = mountInTable( );
18 |
19 | expect(tbody).toBeInTheDocument();
20 | expect(tbody?.tagName).toBe('THEAD');
21 | });
22 |
23 | it('renders children', () => {
24 | const children = ;
25 | const { getByTestId } = mountInTable({children} );
26 | expect(getByTestId('tr')).toBeInTheDocument();
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/src/Table/TableHead.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import styled from 'styled-components';
3 | import { CommonStyledProps } from '../types';
4 |
5 | type TableHeadProps = {
6 | children?: React.ReactNode;
7 | } & React.HTMLAttributes &
8 | CommonStyledProps;
9 |
10 | const StyledTableHead = styled.thead`
11 | display: table-header-group;
12 | `;
13 | const TableHead = forwardRef(
14 | function TableHead({ children, ...otherProps }, ref) {
15 | return (
16 |
17 | {children}
18 |
19 | );
20 | }
21 | );
22 |
23 | TableHead.displayName = 'TableHead';
24 |
25 | export { TableHead, TableHeadProps };
26 |
--------------------------------------------------------------------------------
/src/Table/TableHeadCell.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { renderWithTheme } from '../../test/utils';
4 |
5 | import { TableHeadCell } from './TableHeadCell';
6 |
7 | describe(' ', () => {
8 | function mountInTable(node: React.ReactNode) {
9 | const { container, getByText } = renderWithTheme(
10 |
11 |
12 | {node}
13 |
14 |
15 | );
16 | return {
17 | th: container.querySelector('tr')?.firstElementChild as HTMLElement,
18 | getByText
19 | };
20 | }
21 |
22 | it('renders TableHeadCell', () => {
23 | const { th } = mountInTable( );
24 | expect(th?.tagName).toBe('TH');
25 | });
26 |
27 | it('renders children', () => {
28 | const { getByText } = mountInTable(children );
29 | expect(getByText('children')).toBeInTheDocument();
30 | });
31 |
32 | describe('prop: sort', () => {
33 | it('should render without aria-sort attribute by default', () => {
34 | const { th } = mountInTable( );
35 | expect(th).not.toHaveAttribute('aria-sort');
36 | });
37 |
38 | it('should render aria-sort="ascending" when prop sort="asc" provided', () => {
39 | const { th } = mountInTable( );
40 | expect(th).toHaveAttribute('aria-sort', 'ascending');
41 | });
42 |
43 | it('should render aria-sort="descending" when prop sort="desc" provided', () => {
44 | const { th } = mountInTable( );
45 | expect(th).toHaveAttribute('aria-sort', 'descending');
46 | });
47 | });
48 |
49 | describe('prop: disabled', () => {
50 | it('should disable th element', () => {
51 | const handleChange = jest.fn();
52 |
53 | const { th } = mountInTable(
54 |
55 | );
56 | expect(th).toHaveAttribute('aria-disabled', 'true');
57 |
58 | th?.click?.();
59 | expect(handleChange).not.toHaveBeenCalled();
60 | });
61 | });
62 | });
63 |
--------------------------------------------------------------------------------
/src/Table/TableRow.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { renderWithTheme } from '../../test/utils';
3 |
4 | import { TableRow } from './TableRow';
5 |
6 | describe(' ', () => {
7 | function mountInTable(node: React.ReactNode) {
8 | const { container, getByTestId } = renderWithTheme(
9 |
12 | );
13 | return {
14 | tr: container.querySelector('tbody')?.firstElementChild,
15 | getByTestId
16 | };
17 | }
18 |
19 | it('renders TableRow', () => {
20 | const { tr } = mountInTable( );
21 | expect(tr?.tagName).toBe('TR');
22 | });
23 |
24 | it('renders children', () => {
25 | const children = ;
26 | const { getByTestId } = mountInTable({children} );
27 | expect(getByTestId('td')).toBeInTheDocument();
28 | });
29 | });
30 |
--------------------------------------------------------------------------------
/src/Table/TableRow.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import styled from 'styled-components';
3 | import { blockSizes } from '../common/system';
4 |
5 | type TableRowProps = {
6 | children?: React.ReactNode;
7 | } & React.HTMLAttributes;
8 |
9 | const StyledTr = styled.tr`
10 | color: inherit;
11 | display: table-row;
12 | height: calc(${blockSizes.md} - 2px);
13 | line-height: calc(${blockSizes.md} - 2px);
14 | vertical-align: middle;
15 | outline: none;
16 |
17 | color: ${({ theme }) => theme.canvasText};
18 | &:hover {
19 | background: ${({ theme }) => theme.hoverBackground};
20 | color: ${({ theme }) => theme.canvasTextInvert};
21 | }
22 | `;
23 |
24 | const TableRow = forwardRef(
25 | function TableRow({ children, ...otherProps }, ref) {
26 | return (
27 |
28 | {children}
29 |
30 | );
31 | }
32 | );
33 |
34 | TableRow.displayName = 'TableRow';
35 |
36 | export { TableRow, TableRowProps };
37 |
--------------------------------------------------------------------------------
/src/Tabs/Tab.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { renderWithTheme } from '../../test/utils';
4 | import { Tab } from './Tab';
5 |
6 | describe(' ', () => {
7 | describe('prop: children', () => {
8 | it('should render passed child', () => {
9 | const child = 'Hey there!';
10 | const { getByText } = renderWithTheme({child} );
11 |
12 | expect(getByText(child)).toBeInTheDocument();
13 | });
14 | });
15 |
16 | describe('prop: selected', () => {
17 | it('should render with correct aria attribute', () => {
18 | const { getByRole } = renderWithTheme( );
19 |
20 | expect(getByRole('tab')).toHaveAttribute('aria-selected', 'true');
21 | });
22 | });
23 |
24 | describe('prop: onClick', () => {
25 | it('should be called when a click is triggered', () => {
26 | const handleClick = jest.fn();
27 | const { getByRole } = renderWithTheme( );
28 |
29 | getByRole('tab').click();
30 |
31 | expect(handleClick).toHaveBeenCalledTimes(1);
32 | });
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/src/Tabs/TabBody.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { renderWithTheme } from '../../test/utils';
4 | import { TabBody } from './TabBody';
5 |
6 | describe(' ', () => {
7 | describe('prop: children', () => {
8 | it('should render passed child', () => {
9 | const child = 'Hey there!';
10 | const { getByText } = renderWithTheme({child} );
11 |
12 | expect(getByText(child)).toBeInTheDocument();
13 | });
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/src/Tabs/TabBody.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 |
3 | import styled from 'styled-components';
4 | import { createBorderStyles, createBoxStyles } from '../common';
5 | import { CommonStyledProps } from '../types';
6 |
7 | type TabBodyProps = {
8 | children: React.ReactNode;
9 | } & React.HTMLAttributes &
10 | CommonStyledProps;
11 |
12 | const StyledTabBody = styled.div`
13 | ${createBoxStyles()}
14 | ${createBorderStyles()}
15 | position: relative;
16 | display: block;
17 | height: 100%;
18 | padding: 16px;
19 | font-size: 1rem;
20 | `;
21 | const TabBody = forwardRef(
22 | ({ children, ...otherProps }, ref) => {
23 | return (
24 |
25 | {children}
26 |
27 | );
28 | }
29 | );
30 |
31 | TabBody.displayName = 'TabBody';
32 |
33 | export { TabBody, TabBodyProps };
34 |
--------------------------------------------------------------------------------
/src/Toolbar/Toolbar.spec.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react';
2 | import React from 'react';
3 |
4 | import { Toolbar } from './Toolbar';
5 |
6 | describe(' ', () => {
7 | it('should render', () => {
8 | const { container } = render( );
9 | const toolbar = container.firstChild;
10 |
11 | expect(toolbar).toBeInTheDocument();
12 | });
13 |
14 | it('should render children', () => {
15 | const { container } = render(A nice app bar );
16 | const toolbar = container.firstChild;
17 |
18 | expect(toolbar).toHaveTextContent('A nice app bar');
19 | });
20 |
21 | describe('prop: noPadding', () => {
22 | it('should apply 0 padding', () => {
23 | const { container } = render( );
24 | const toolbar = container.firstChild;
25 |
26 | expect(toolbar).toHaveStyleRule('padding', '0');
27 | });
28 | });
29 | });
30 |
--------------------------------------------------------------------------------
/src/Toolbar/Toolbar.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import styled from 'styled-components';
3 |
4 | type ToolbarProps = {
5 | children?: React.ReactNode;
6 | noPadding?: boolean;
7 | } & React.HTMLAttributes;
8 |
9 | const StyledToolbar = styled.div`
10 | position: relative;
11 | display: flex;
12 | align-items: center;
13 | padding: ${props => (props.noPadding ? '0' : '4px')};
14 | `;
15 |
16 | const Toolbar = forwardRef(function Toolbar(
17 | { children, noPadding = false, ...otherProps },
18 | ref
19 | ) {
20 | return (
21 |
22 | {children}
23 |
24 | );
25 | });
26 |
27 | Toolbar.displayName = 'Toolbar';
28 |
29 | export { Toolbar };
30 |
--------------------------------------------------------------------------------
/src/Tooltip/Tooltip.stories.tsx:
--------------------------------------------------------------------------------
1 | import { ComponentMeta } from '@storybook/react';
2 | import React from 'react';
3 | import { Button, Tooltip } from 'react95';
4 | import styled from 'styled-components';
5 |
6 | const Wrapper = styled.div`
7 | padding: 5rem;
8 | background: ${({ theme }) => theme.desktopBackground};
9 | `;
10 |
11 | export default {
12 | title: 'Controls/Tooltip',
13 | component: Tooltip,
14 | decorators: [story => {story()} ]
15 | } as ComponentMeta;
16 |
17 | export function Default() {
18 | return (
19 |
20 | Hover me
21 |
22 | );
23 | }
24 |
25 | Default.story = {
26 | name: 'default'
27 | };
28 |
--------------------------------------------------------------------------------
/src/Window/Window.spec.tsx:
--------------------------------------------------------------------------------
1 | import React, { createRef } from 'react';
2 |
3 | import { renderWithTheme } from '../../test/utils';
4 |
5 | import { Window } from './Window';
6 |
7 | describe(' ', () => {
8 | it('renders Window', () => {
9 | const { container } = renderWithTheme( );
10 | const window = container.firstChild;
11 |
12 | expect(window).toBeInTheDocument();
13 | });
14 |
15 | it('renders children', () => {
16 | const textContent = 'Hi there!';
17 | const { getByText } = renderWithTheme(
18 |
19 | {textContent}
20 |
21 | );
22 | expect(getByText(textContent)).toBeInTheDocument();
23 | });
24 |
25 | describe('prop: resizable', () => {
26 | it('does not render resize handle by default', () => {
27 | const { queryByTestId } = renderWithTheme( );
28 |
29 | expect(queryByTestId('resizeHandle')).not.toBeInTheDocument();
30 | });
31 |
32 | it('renders resize handle when set to true', () => {
33 | const { queryByTestId } = renderWithTheme( );
34 |
35 | expect(queryByTestId('resizeHandle')).toBeInTheDocument();
36 | });
37 |
38 | it('passes resizeRef to the resizable element', () => {
39 | const ref = createRef();
40 | const { queryByTestId } = renderWithTheme(
41 |
42 | );
43 |
44 | expect(queryByTestId('resizeHandle')).toBe(ref.current);
45 | });
46 | });
47 | });
48 |
--------------------------------------------------------------------------------
/src/Window/Window.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import styled, { css } from 'styled-components';
3 | import { createBorderStyles, createBoxStyles } from '../common';
4 | import { CommonStyledProps } from '../types';
5 |
6 | type WindowProps = {
7 | children?: React.ReactNode;
8 | resizable?: boolean;
9 | resizeRef?: React.Ref;
10 | shadow?: boolean;
11 | } & React.HTMLAttributes &
12 | CommonStyledProps;
13 |
14 | const StyledWindow = styled.div`
15 | position: relative;
16 | padding: 4px;
17 | font-size: 1rem;
18 | ${createBorderStyles({ style: 'window' })}
19 | ${createBoxStyles()}
20 | `;
21 |
22 | const ResizeHandle = styled.span`
23 | ${({ theme }) => css`
24 | display: inline-block;
25 | position: absolute;
26 | bottom: 10px;
27 | right: 10px;
28 | width: 25px;
29 | height: 25px;
30 | background-image: linear-gradient(
31 | 135deg,
32 | ${theme.borderLightest} 16.67%,
33 | ${theme.material} 16.67%,
34 | ${theme.material} 33.33%,
35 | ${theme.borderDark} 33.33%,
36 | ${theme.borderDark} 50%,
37 | ${theme.borderLightest} 50%,
38 | ${theme.borderLightest} 66.67%,
39 | ${theme.material} 66.67%,
40 | ${theme.material} 83.33%,
41 | ${theme.borderDark} 83.33%,
42 | ${theme.borderDark} 100%
43 | );
44 | background-size: 8.49px 8.49px;
45 | clip-path: polygon(100% 0px, 0px 100%, 100% 100%);
46 | cursor: nwse-resize;
47 | `}
48 | `;
49 |
50 | const Window = forwardRef(
51 | (
52 | { children, resizable = false, resizeRef, shadow = true, ...otherProps },
53 | ref
54 | ) => {
55 | return (
56 |
57 | {children}
58 | {resizable && (
59 |
60 | )}
61 |
62 | );
63 | }
64 | );
65 |
66 | Window.displayName = 'Window';
67 |
68 | export * from './WindowContent';
69 |
70 | export * from './WindowHeader';
71 |
72 | export { Window, WindowProps };
73 |
--------------------------------------------------------------------------------
/src/Window/WindowContent.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { renderWithTheme } from '../../test/utils';
4 |
5 | import { WindowContent } from './WindowContent';
6 |
7 | describe(' ', () => {
8 | it('renders WindowContent', () => {
9 | const { container } = renderWithTheme( );
10 | const windowContent = container.firstChild;
11 |
12 | expect(windowContent).toBeInTheDocument();
13 | });
14 |
15 | it('renders children', () => {
16 | const textContent = 'Hi there!';
17 | const { getByText } = renderWithTheme(
18 |
19 | {textContent}
20 |
21 | );
22 | expect(getByText(textContent)).toBeInTheDocument();
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/src/Window/WindowContent.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import styled from 'styled-components';
3 | import { CommonStyledProps } from '../types';
4 |
5 | type WindowContentProps = {
6 | children?: React.ReactNode;
7 | } & React.HTMLAttributes &
8 | CommonStyledProps;
9 |
10 | const StyledWindowContent = styled.div`
11 | padding: 16px;
12 | `;
13 |
14 | const WindowContent = forwardRef(
15 | function WindowContent({ children, ...otherProps }, ref) {
16 | return (
17 |
18 | {children}
19 |
20 | );
21 | }
22 | );
23 |
24 | WindowContent.displayName = 'WindowContent';
25 |
26 | export { WindowContent, WindowContentProps };
27 |
--------------------------------------------------------------------------------
/src/Window/WindowHeader.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { renderWithTheme, theme } from '../../test/utils';
4 |
5 | import { WindowHeader } from './WindowHeader';
6 |
7 | describe(' ', () => {
8 | it('renders WindowHeader', () => {
9 | const { container } = renderWithTheme( );
10 | const windowHeader = container.firstChild;
11 |
12 | expect(windowHeader).toBeInTheDocument();
13 | });
14 |
15 | it('renders children', () => {
16 | const textContent = 'Hi there!';
17 | const { getByText } = renderWithTheme(
18 |
19 | {textContent}
20 |
21 | );
22 | expect(getByText(textContent)).toBeInTheDocument();
23 | });
24 |
25 | describe('prop: active', () => {
26 | it('displays active header by default', () => {
27 | const { container } = renderWithTheme( );
28 | const windowHeader = container.firstChild as HTMLDivElement;
29 |
30 | expect(windowHeader).toHaveStyleRule('color', theme.headerText);
31 | expect(windowHeader).toHaveStyleRule(
32 | 'background',
33 | theme.headerBackground
34 | );
35 | });
36 |
37 | it('displays active header when set to true', () => {
38 | const { container } = renderWithTheme( );
39 | const windowHeader = container.firstChild as HTMLDivElement;
40 |
41 | expect(windowHeader).toHaveStyleRule('color', theme.headerText);
42 | expect(windowHeader).toHaveStyleRule(
43 | 'background',
44 | theme.headerBackground
45 | );
46 | });
47 |
48 | it('renders non-active header when set to false', () => {
49 | const { container } = renderWithTheme( );
50 | const windowHeader = container.firstChild;
51 |
52 | expect(windowHeader).toHaveStyleRule('color', theme.headerNotActiveText);
53 | expect(windowHeader).toHaveStyleRule(
54 | 'background',
55 | theme.headerNotActiveBackground
56 | );
57 | });
58 | });
59 | });
60 |
--------------------------------------------------------------------------------
/src/Window/WindowHeader.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import styled, { css } from 'styled-components';
3 | import { StyledButton } from '../Button/Button';
4 | import { CommonStyledProps } from '../types';
5 |
6 | type WindowHeaderProps = {
7 | children?: React.ReactNode;
8 | active?: boolean;
9 | } & React.HTMLAttributes &
10 | CommonStyledProps;
11 |
12 | const StyledWindowHeader = styled.div>`
13 | height: 33px;
14 | line-height: 33px;
15 | padding-left: 0.25rem;
16 | padding-right: 3px;
17 | font-weight: bold;
18 | border: 2px solid ${({ theme }) => theme.material};
19 | ${({ active }) =>
20 | active === false
21 | ? css`
22 | background: ${({ theme }) => theme.headerNotActiveBackground};
23 | color: ${({ theme }) => theme.headerNotActiveText};
24 | `
25 | : css`
26 | background: ${({ theme }) => theme.headerBackground};
27 | color: ${({ theme }) => theme.headerText};
28 | `}
29 |
30 | ${StyledButton} {
31 | padding-left: 0;
32 | padding-right: 0;
33 | height: 27px;
34 | width: 31px;
35 | }
36 | `;
37 |
38 | // TODO - should we add some aria label indicating if window is currently active?
39 | const WindowHeader = forwardRef(
40 | function WindowHeader({ active = true, children, ...otherProps }, ref) {
41 | return (
42 |
43 | {children}
44 |
45 | );
46 | }
47 | );
48 |
49 | WindowHeader.displayName = 'WindowHeader';
50 |
51 | export { WindowHeader, WindowHeaderProps };
52 |
--------------------------------------------------------------------------------
/src/assets/fonts/dist/ms_sans_serif.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react95-io/React95/871d5335daebdda1469f66f81266523f4191a595/src/assets/fonts/dist/ms_sans_serif.woff
--------------------------------------------------------------------------------
/src/assets/fonts/dist/ms_sans_serif.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react95-io/React95/871d5335daebdda1469f66f81266523f4191a595/src/assets/fonts/dist/ms_sans_serif.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/dist/ms_sans_serif_bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react95-io/React95/871d5335daebdda1469f66f81266523f4191a595/src/assets/fonts/dist/ms_sans_serif_bold.woff
--------------------------------------------------------------------------------
/src/assets/fonts/dist/ms_sans_serif_bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react95-io/React95/871d5335daebdda1469f66f81266523f4191a595/src/assets/fonts/dist/ms_sans_serif_bold.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/src/ms-sans-serif-bold/MS Sans Serif Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react95-io/React95/871d5335daebdda1469f66f81266523f4191a595/src/assets/fonts/src/ms-sans-serif-bold/MS Sans Serif Bold.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/src/ms-sans-serif-bold/license.txt:
--------------------------------------------------------------------------------
1 | The FontStruction “MS Sans Serif Bold”
2 | (https://fontstruct.com/fontstructions/show/1384862) by “lou” is licensed
3 | under a Creative Commons Attribution Share Alike license
4 | (http://creativecommons.org/licenses/by-sa/3.0/).
5 |
--------------------------------------------------------------------------------
/src/assets/fonts/src/ms-sans-serif-bold/readme.txt:
--------------------------------------------------------------------------------
1 | The font file in this archive was created using Fontstruct the free, online
2 | font-building tool.
3 | This font was created by “lou”.
4 | This font has a homepage where this archive and other versions may be found:
5 | https://fontstruct.com/fontstructions/show/1384862
6 |
7 | Try Fontstruct at http://fontstruct.com
8 | It’s easy and it’s fun.
9 |
10 | NOTE FOR FLASH USERS: Fontstruct fonts (fontstructions) are optimized for Flash.
11 | If the font in this archive is a pixel font, it is best displayed at a font-size
12 | of 11.
13 |
14 | Fontstruct is sponsored by FontShop.
15 | Visit them at https://fontshop.com
16 | FontShop is the original independent font retailer. We’ve been around since
17 | the dawn of digital type. Whether you need the right font or need to create the
18 | right font from scratch, let our 26 years of experience work for you.
19 |
20 | Fontstruct is copyright ©2017 Rob Meek
21 |
22 | LEGAL NOTICE:
23 | In using this font you must comply with the licensing terms described in the
24 | file “license.txt” included with this archive.
25 | If you redistribute the font file in this archive, it must be accompanied by all
26 | the other files from this archive, including this one.
27 |
--------------------------------------------------------------------------------
/src/assets/fonts/src/ms-sans-serif/MS Sans Serif.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react95-io/React95/871d5335daebdda1469f66f81266523f4191a595/src/assets/fonts/src/ms-sans-serif/MS Sans Serif.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/src/ms-sans-serif/license.txt:
--------------------------------------------------------------------------------
1 | The FontStruction “MS Sans Serif”
2 | (https://fontstruct.com/fontstructions/show/1384746) by “lou” is licensed
3 | under a Creative Commons Attribution Share Alike license
4 | (http://creativecommons.org/licenses/by-sa/3.0/).
5 |
--------------------------------------------------------------------------------
/src/assets/fonts/src/ms-sans-serif/readme.txt:
--------------------------------------------------------------------------------
1 | The font file in this archive was created using Fontstruct the free, online
2 | font-building tool.
3 | This font was created by “lou”.
4 | This font has a homepage where this archive and other versions may be found:
5 | https://fontstruct.com/fontstructions/show/1384746
6 |
7 | Try Fontstruct at http://fontstruct.com
8 | It’s easy and it’s fun.
9 |
10 | NOTE FOR FLASH USERS: Fontstruct fonts (fontstructions) are optimized for Flash.
11 | If the font in this archive is a pixel font, it is best displayed at a font-size
12 | of 11.
13 |
14 | Fontstruct is sponsored by FontShop.
15 | Visit them at https://fontshop.com
16 | FontShop is the original independent font retailer. We’ve been around since
17 | the dawn of digital type. Whether you need the right font or need to create the
18 | right font from scratch, let our 26 years of experience work for you.
19 |
20 | Fontstruct is copyright ©2017 Rob Meek
21 |
22 | LEGAL NOTICE:
23 | In using this font you must comply with the licensing terms described in the
24 | file “license.txt” included with this archive.
25 | If you redistribute the font file in this archive, it must be accompanied by all
26 | the other files from this archive, including this one.
27 |
--------------------------------------------------------------------------------
/src/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react95-io/React95/871d5335daebdda1469f66f81266523f4191a595/src/assets/images/logo.png
--------------------------------------------------------------------------------
/src/assets/images/logo.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react95-io/React95/871d5335daebdda1469f66f81266523f4191a595/src/assets/images/logo.psd
--------------------------------------------------------------------------------
/src/common/SwitchBase.ts:
--------------------------------------------------------------------------------
1 | import styled, { css } from 'styled-components';
2 |
3 | import { createDisabledTextStyles, focusOutline } from '.';
4 | import { StyledMenuListItem } from '../MenuList/MenuList';
5 |
6 | export const size = 20;
7 |
8 | export const StyledInput = styled.input`
9 | position: absolute;
10 | left: 0;
11 | margin: 0;
12 | width: ${size}px;
13 | height: ${size}px;
14 | opacity: 0;
15 | z-index: -1;
16 | `;
17 |
18 | export const StyledLabel = styled.label<{ $disabled: boolean }>`
19 | display: inline-flex;
20 | align-items: center;
21 | position: relative;
22 | margin: 8px 0;
23 | cursor: ${({ $disabled }) => (!$disabled ? 'pointer' : 'auto')};
24 | user-select: none;
25 | font-size: 1rem;
26 | color: ${({ theme }) => theme.materialText};
27 | ${props => props.$disabled && createDisabledTextStyles()}
28 |
29 | ${StyledMenuListItem} & {
30 | margin: 0;
31 | height: 100%;
32 | }
33 | ${StyledMenuListItem}:hover & {
34 | ${({ $disabled, theme }) =>
35 | !$disabled &&
36 | css`
37 | color: ${theme.materialTextInvert};
38 | `};
39 | }
40 | `;
41 |
42 | // TODO how to handle focus styles in 'menu' variant of Checkbox/Radio?
43 | export const LabelText = styled.span`
44 | display: inline-block;
45 | line-height: 1;
46 | padding: 2px;
47 | ${StyledInput}:focus ~ & {
48 | ${focusOutline}
49 | }
50 | ${StyledInput}:not(:disabled) ~ &:active {
51 | ${focusOutline}
52 | }
53 | `;
54 |
--------------------------------------------------------------------------------
/src/common/constants.ts:
--------------------------------------------------------------------------------
1 | export const KEYBOARD_KEY_CODES = {
2 | ARROW_DOWN: 'ArrowDown',
3 | ARROW_LEFT: 'ArrowLeft',
4 | ARROW_RIGHT: 'ArrowRight',
5 | ARROW_UP: 'ArrowUp',
6 | END: 'End',
7 | ENTER: 'Enter',
8 | ESC: 'Escape',
9 | HOME: 'Home',
10 | SPACE: 'Space',
11 | TAB: 'Tab'
12 | };
13 |
--------------------------------------------------------------------------------
/src/common/hooks/useControlledOrUncontrolled.ts:
--------------------------------------------------------------------------------
1 | import React, { useState, useCallback } from 'react';
2 |
3 | export default function useControlledOrUncontrolled({
4 | defaultValue,
5 | onChange,
6 | onChangePropName = 'onChange',
7 | readOnly,
8 | value,
9 | valuePropName = 'value'
10 | }: {
11 | defaultValue: T;
12 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
13 | onChange?: (...args: any[]) => void;
14 | onChangePropName?: string;
15 | readOnly?: boolean;
16 | value: T | undefined;
17 | valuePropName?: string;
18 | }): [T, (newValue: React.SetStateAction) => void] {
19 | const isControlled = value !== undefined;
20 | const [controlledValue, setControlledValue] = useState(defaultValue);
21 | const handleChangeIfUncontrolled = useCallback(
22 | (newValue: React.SetStateAction) => {
23 | if (!isControlled) {
24 | setControlledValue(newValue);
25 | }
26 | },
27 | [isControlled]
28 | );
29 |
30 | // Because we provide `onChange` even to uncontrolled components, React's
31 | // default uncontrolled warning must be reimplemented. This also deals with
32 | // props that are different from `value`.
33 | if (isControlled && typeof onChange !== 'function' && !readOnly) {
34 | const message = `Warning: You provided a \`${valuePropName}\` prop to a component without an \`${onChangePropName}\` handler.${
35 | valuePropName === 'value'
36 | ? `This will render a read-only field. If the field should be mutable use \`defaultValue\`. Otherwise, set either \`${onChangePropName}\` or \`readOnly\`.`
37 | : `This breaks the component state. You must provide an \`${onChangePropName}\` function that updates \`${valuePropName}\`.`
38 | }`;
39 |
40 | // eslint-disable-next-line no-console
41 | console.warn(message);
42 | }
43 |
44 | return [isControlled ? value : controlledValue, handleChangeIfUncontrolled];
45 | }
46 |
--------------------------------------------------------------------------------
/src/common/hooks/useEventCallback.ts:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | const useEnhancedEffect =
4 | typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
5 |
6 | /**
7 | * https://github.com/facebook/react/issues/14099#issuecomment-440013892
8 | */
9 | export default function useEventCallback(
10 | fn: (...args: Args) => Return
11 | ): (...args: Args) => Return {
12 | const ref = React.useRef(fn);
13 | useEnhancedEffect(() => {
14 | ref.current = fn;
15 | });
16 | return React.useCallback(
17 | (...args: Args) =>
18 | // @ts-expect-error hide `this`
19 | // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
20 | (0, ref.current!)(...args),
21 | []
22 | );
23 | }
24 |
--------------------------------------------------------------------------------
/src/common/hooks/useForkRef.ts:
--------------------------------------------------------------------------------
1 | // Straight out copied from https://github.com/mui-org/material-ui 😂
2 |
3 | import { useMemo } from 'react';
4 |
5 | function setRef(
6 | ref: React.RefCallback | React.MutableRefObject | null,
7 | value: T
8 | ) {
9 | if (typeof ref === 'function') {
10 | ref(value);
11 | } else if (ref) {
12 | // eslint-disable-next-line no-param-reassign
13 | ref.current = value;
14 | }
15 | }
16 |
17 | export default function useForkRef(
18 | refA: React.RefCallback | React.MutableRefObject | null,
19 | refB: React.RefCallback | React.MutableRefObject | null
20 | ): React.RefCallback | null {
21 | /**
22 | * This will create a new function if the ref props change and are defined.
23 | * This means react will call the old forkRef with `null` and the new forkRef
24 | * with the ref. Cleanup naturally emerges from this behavior
25 | */
26 | return useMemo(() => {
27 | if (refA == null && refB == null) {
28 | return null;
29 | }
30 | return refValue => {
31 | setRef(refA, refValue);
32 | setRef(refB, refValue);
33 | };
34 | }, [refA, refB]);
35 | }
36 |
--------------------------------------------------------------------------------
/src/common/hooks/useId.spec.ts:
--------------------------------------------------------------------------------
1 | import { renderHook } from '@testing-library/react-hooks';
2 | import { useId } from './useId';
3 |
4 | describe(useId, () => {
5 | it('returns a random string of 10 digits', () => {
6 | const { result } = renderHook(() => useId());
7 | expect(result.current).toMatch(/^[0-9a-z]{10}$/i);
8 | });
9 |
10 | it('returns the passed ID', () => {
11 | const { result } = renderHook(() => useId('test'));
12 | expect(result.current).toEqual('test');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/src/common/hooks/useId.ts:
--------------------------------------------------------------------------------
1 | import { useMemo } from 'react';
2 |
3 | function makeId() {
4 | const chars =
5 | '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
6 | let id = '';
7 | for (let i = 0; i < 10; i += 1) {
8 | id += chars[Math.floor(Math.random() * chars.length)];
9 | }
10 | return id;
11 | }
12 |
13 | export const useId = (id?: string) => {
14 | return useMemo(() => id ?? makeId(), [id]);
15 | };
16 |
--------------------------------------------------------------------------------
/src/common/system.ts:
--------------------------------------------------------------------------------
1 | // TODO - implement styled-system
2 |
3 | import { Sizes } from '../types';
4 |
5 | export const blockSizes: Record = {
6 | sm: '28px',
7 | md: '36px',
8 | lg: '44px'
9 | };
10 |
--------------------------------------------------------------------------------
/src/common/themes/aiee.ts:
--------------------------------------------------------------------------------
1 | /* "AIEE" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Aiee-668092636
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'aiee',
9 | anchor: 'rgb(0,0,128)',
10 | anchorVisited: 'rgb(0,0,128)',
11 | borderDark: 'rgb(211,214,217)',
12 | borderDarkest: 'rgb(65,187,241)',
13 | borderLight: 'rgb(238,244,252)',
14 | borderLightest: 'rgb(250,254,255)',
15 | canvas: 'rgb(255,255,255)',
16 | canvasText: 'rgb(0,62,1090)',
17 | canvasTextDisabled: 'rgb(211,214,217)',
18 | canvasTextDisabledShadow: 'rgb(250,254,255)',
19 | canvasTextInvert: 'rgb(0,62,109)',
20 | checkmark: 'rgb(0,62,1090)',
21 | checkmarkDisabled: 'rgb(88,152,231)',
22 | desktopBackground: 'rgb(68,125,183)',
23 | flatDark: 'rgb(211,214,217)',
24 | flatLight: 'rgb(238,244,252)',
25 | focusSecondary: 'rgb(250,254,255)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(4,118,180), rgb(251,211,61))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(0,159,223), rgb(0,207,247))',
30 | headerNotActiveText: 'rgb(0,62,109)',
31 | headerText: 'rgb(255,255,255)',
32 | hoverBackground: 'rgb(251,211,61)',
33 | material: 'rgb(227,238,251)',
34 | materialDark: 'rgb(0,159,223)',
35 | materialText: 'rgb(0,62,109)',
36 | materialTextDisabled: 'rgb(211,214,217)',
37 | materialTextDisabledShadow: 'rgb(250,254,255)',
38 | materialTextInvert: 'rgb(0,62,109)',
39 | progress: 'rgb(251,211,61)',
40 | tooltip: 'rgb(255,243,185)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/ash.ts:
--------------------------------------------------------------------------------
1 | /* "Ash" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Ash-575566643
3 | */
4 | import { Theme } from './types';
5 |
6 | export default {
7 | name: 'ash',
8 | anchor: 'rgb(192, 192, 192)',
9 | anchorVisited: 'rgb(192, 192, 192)',
10 | borderDark: 'rgb(63, 63, 63)',
11 | borderDarkest: 'rgb(0, 0, 0)',
12 | borderLight: 'rgb(115, 115, 115)',
13 | borderLightest: 'rgb(175, 175, 175)',
14 | canvas: 'rgb(64, 64, 64)',
15 | canvasText: 'rgb(0, 0, 0)',
16 | canvasTextDisabled: 'rgb(63, 63, 63)',
17 | canvasTextDisabledShadow: 'rgb(175, 175, 175)',
18 | canvasTextInvert: 'rgb(255, 255, 255)',
19 | checkmark: 'rgb(0, 0, 0)',
20 | checkmarkDisabled: 'rgb(128, 128, 128)',
21 | desktopBackground: 'rgb(0, 0, 0)',
22 | flatDark: 'rgb(63, 63, 63)',
23 | flatLight: 'rgb(96, 96, 96)',
24 | focusSecondary: 'rgb(175, 175, 175)',
25 | headerBackground: 'linear-gradient(to right, rgb(0, 0, 0), rgb(0, 0, 0))',
26 | headerNotActiveBackground:
27 | 'linear-gradient(to right, rgb(63, 63, 63), rgb(0, 0, 0))',
28 | headerNotActiveText: 'rgb(128, 128, 128)',
29 | headerText: 'rgb(255, 255, 255)',
30 | hoverBackground: 'rgb(0, 0, 0)',
31 | material: 'rgb(96, 96, 96)',
32 | materialDark: 'rgb(63, 63, 63)',
33 | materialText: 'rgb(0, 0, 0)',
34 | materialTextDisabled: 'rgb(63, 63, 63)',
35 | materialTextDisabledShadow: 'rgb(175, 175, 175)',
36 | materialTextInvert: 'rgb(255, 255, 255)',
37 | progress: 'rgb(0, 0, 0)',
38 | tooltip: 'rgb(0, 0, 0)'
39 | } as Theme;
40 |
--------------------------------------------------------------------------------
/src/common/themes/azureOrange.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'azureOrange',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#05427f',
9 | borderDarkest: '#000000',
10 | borderLight: '#2b8fff',
11 | borderLightest: '#7ebfff',
12 | canvas: '#ffffff',
13 | canvasText: '#000000',
14 | canvasTextDisabled: '#05427f',
15 | canvasTextDisabledShadow: '#7ebfff',
16 | canvasTextInvert: '#000000',
17 | checkmark: '#000000',
18 | checkmarkDisabled: '#05427f',
19 | desktopBackground: '#ff7d01',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#171123',
23 | headerBackground: '#171123',
24 | headerNotActiveBackground: '#4E6766',
25 | headerNotActiveText: '#0180ff',
26 | headerText: '#ffffff',
27 | hoverBackground: '#F46036',
28 | material: '#0180ff',
29 | materialDark: '#9a9e9c',
30 | materialText: '#000000',
31 | materialTextDisabled: '#05427f',
32 | materialTextDisabledShadow: '#7ebfff',
33 | materialTextInvert: '#000000',
34 | progress: '#F46036',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/bee.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'bee',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#846d06',
9 | borderDarkest: '#0C1618',
10 | borderLight: '#e7c221',
11 | borderLightest: '#f8df6e',
12 | canvas: '#ffffff',
13 | canvasText: '#0C1618',
14 | canvasTextDisabled: '#846d06',
15 | canvasTextDisabledShadow: '#f8df6e',
16 | canvasTextInvert: '#ffffff',
17 | checkmark: '#0C1618',
18 | checkmarkDisabled: '#846d06',
19 | desktopBackground: '#977800',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#0C1618',
24 | headerNotActiveBackground: '#7F7B82',
25 | headerNotActiveText: '#e5bd03',
26 | headerText: '#f8df6e',
27 | hoverBackground: '#0C1618',
28 | material: '#e5bd03',
29 | materialDark: '#7F7B82',
30 | materialText: '#0C1618',
31 | materialTextDisabled: '#846d06',
32 | materialTextDisabledShadow: '#f8df6e',
33 | materialTextInvert: '#ffffff',
34 | progress: '#0C1618',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/blackAndWhite.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'blackAndWhite',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#888c8f',
9 | borderDarkest: '#000000',
10 | borderLight: '#dfe0e3',
11 | borderLightest: '#888c8f',
12 | canvas: '#ffffff',
13 | canvasText: '#000000',
14 | canvasTextDisabled: '#888c8f',
15 | canvasTextDisabledShadow: '#ffffff',
16 | canvasTextInvert: '#ffffff',
17 | checkmark: '#000000',
18 | checkmarkDisabled: '#888c8f',
19 | desktopBackground: '#ffffff',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#000000',
24 | headerNotActiveBackground: '#ffffff',
25 | headerNotActiveText: '#000000',
26 | headerText: '#ffffff',
27 | hoverBackground: '#000000',
28 | material: '#ffffff',
29 | materialDark: '#9a9e9c',
30 | materialText: '#000000',
31 | materialTextDisabled: '#888c8f',
32 | materialTextDisabledShadow: '#ffffff',
33 | materialTextInvert: '#ffffff',
34 | progress: '#000000',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/blue.ts:
--------------------------------------------------------------------------------
1 | /* "Blue" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Blue-525167751
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'blue',
9 | anchor: 'rgb(0, 0, 128)',
10 | anchorVisited: 'rgb(0, 0, 128)',
11 | borderDark: 'rgb(49, 131, 221)',
12 | borderDarkest: 'rgb(0, 0, 0)',
13 | borderLight: 'rgb(166, 202, 240)',
14 | borderLightest: 'rgb(211, 228, 248)',
15 | canvas: 'rgb(255, 255, 255)',
16 | canvasText: 'rgb(0, 0, 0)',
17 | canvasTextDisabled: 'rgb(49, 131, 221)',
18 | canvasTextDisabledShadow: 'rgb(211, 228, 248)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(0, 0, 0)',
21 | checkmarkDisabled: 'rgb(49, 131, 221)',
22 | desktopBackground: 'rgb(58, 110, 165)',
23 | flatDark: 'rgb(49, 131, 221)',
24 | flatLight: 'rgb(166, 202, 240)',
25 | focusSecondary: 'rgb(211, 228, 248)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(0, 0, 128), rgb(16, 132, 208))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(49, 131, 221), rgb(49, 131, 221))',
30 | headerNotActiveText: 'rgb(0, 0, 128)',
31 | headerText: 'rgb(255, 255, 255)',
32 | hoverBackground: 'rgb(51, 153, 255)',
33 | material: 'rgb(166, 202, 240)',
34 | materialDark: 'rgb(49, 131, 221)',
35 | materialText: 'rgb(0, 0, 0)',
36 | materialTextDisabled: 'rgb(49, 131, 221)',
37 | materialTextDisabledShadow: 'rgb(211, 228, 248)',
38 | materialTextInvert: 'rgb(255, 255, 255)',
39 | progress: 'rgb(51, 153, 255)',
40 | tooltip: 'rgb(225, 225, 255)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/brick.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'brick',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#6c684b',
9 | borderDarkest: '#020000',
10 | borderLight: '#e2ddc9',
11 | borderLightest: '#ffffff',
12 | canvas: '#ffffff',
13 | canvasText: '#020000',
14 | canvasTextDisabled: '#6c684b',
15 | canvasTextDisabledShadow: '#ffffff',
16 | canvasTextInvert: '#ffffff',
17 | checkmark: '#020000',
18 | checkmarkDisabled: '#6c684b',
19 | desktopBackground: '#420000',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#8e0101',
24 | headerNotActiveBackground: '#90885c',
25 | headerNotActiveText: '#c2bfa3',
26 | headerText: '#ffffff',
27 | hoverBackground: '#8e0101',
28 | material: '#c2bfa3',
29 | materialDark: '#9a9e9c',
30 | materialText: '#020000',
31 | materialTextDisabled: '#6c684b',
32 | materialTextDisabledShadow: '#ffffff',
33 | materialTextInvert: '#ffffff',
34 | progress: '#8e0101',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/candy.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'candy',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#d1579e',
9 | borderDarkest: '#44132f',
10 | borderLight: '#f1acd5',
11 | borderLightest: '#EFF1F3',
12 | canvas: '#EFF1F3',
13 | canvasText: '#000000',
14 | canvasTextDisabled: '#d1579e',
15 | canvasTextDisabledShadow: '#EFF1F3',
16 | canvasTextInvert: '#EFF1F3',
17 | checkmark: '#000000',
18 | checkmarkDisabled: '#d1579e',
19 | desktopBackground: '#b477bd',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#87255B',
24 | headerNotActiveBackground: '#a08796',
25 | headerNotActiveText: '#EBD2BE',
26 | headerText: '#EFF1F3',
27 | hoverBackground: '#256EFF',
28 | material: '#E5A4CB',
29 | materialDark: '#9a9e9c',
30 | materialText: '#000000',
31 | materialTextDisabled: '#d1579e',
32 | materialTextDisabledShadow: '#EFF1F3',
33 | materialTextInvert: '#EFF1F3',
34 | progress: '#256EFF',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/cherry.ts:
--------------------------------------------------------------------------------
1 | /* "Cherry" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Cherry-747961418
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'cherry',
9 | anchor: 'rgb(128, 0, 1)',
10 | anchorVisited: 'rgb(128, 0, 1)',
11 | borderDark: 'rgb(128, 128, 128)',
12 | borderDarkest: 'rgb(64, 64, 64)',
13 | borderLight: 'rgb(200, 212, 208)',
14 | borderLightest: 'rgb(255, 255, 255)',
15 | canvas: 'rgb(255, 255, 255)',
16 | canvasText: 'rgb(0, 0, 0)',
17 | canvasTextDisabled: 'rgb(128, 128, 128)',
18 | canvasTextDisabledShadow: 'rgb(255, 255, 255)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(0, 0, 0)',
21 | checkmarkDisabled: 'rgb(128, 128, 128)',
22 | desktopBackground: 'rgb(165, 58, 109)',
23 | flatDark: 'rgb(128, 128, 128)',
24 | flatLight: 'rgb(200, 212, 208)',
25 | focusSecondary: 'rgb(255, 255, 255)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(106, 10, 36), rgb(240, 166, 202))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(128, 128, 128), rgb(192, 192, 192))',
30 | headerNotActiveText: 'rgb(212, 208, 200)',
31 | headerText: 'rgb(255, 255, 255)',
32 | hoverBackground: 'rgb(106, 10, 36)',
33 | material: 'rgb(200, 212, 208)',
34 | materialDark: 'rgb(128, 128, 128)',
35 | materialText: 'rgb(0, 0, 0)',
36 | materialTextDisabled: 'rgb(128, 128, 128)',
37 | materialTextDisabledShadow: 'rgb(255, 255, 255)',
38 | materialTextInvert: 'rgb(255, 255, 255)',
39 | progress: 'rgb(106, 10, 36)',
40 | tooltip: 'rgb(225, 254, 255)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/coldGray.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'coldGray',
5 |
6 | anchor: '#8d88c2',
7 | anchorVisited: '#440381',
8 | background: '#4C6663',
9 | borderDark: '#5b57a1',
10 | borderDarkest: '#010601',
11 | borderLight: '#a4a7c8',
12 | borderLightest: '#c7c7df',
13 | canvas: '#c7c7df',
14 | canvasText: '#050608',
15 | canvasTextDisabled: '#888c8f',
16 | canvasTextDisabledShadow: '#ffffff',
17 | canvasTextInvert: '#ffffff',
18 | checkmark: '#010601',
19 | checkmarkDisabled: '#5b57a1',
20 | desktopBackground: '#606286',
21 | flatDark: '#5b57a1',
22 | flatLight: '#a4a7c8',
23 | focusSecondary: '#fefe03',
24 | headerBackground: '#3B3D64',
25 | headerNotActiveBackground: '#6063a5',
26 | headerNotActiveText: '#a1a3ca',
27 | headerText: '#010601',
28 | hoverBackground: '#8d88c2',
29 | material: '#a1a3ca',
30 | materialDark: '#6063a5',
31 | materialText: '#010601',
32 | materialTextDisabled: '#5b57a1',
33 | materialTextDisabledShadow: '#c7c7df',
34 | materialTextInvert: '#c7c7df',
35 | progress: '#8d88c2',
36 | tooltip: '#fefbcc'
37 | } as Theme;
38 |
--------------------------------------------------------------------------------
/src/common/themes/counterStrike.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'counterStrike',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#2c3125',
9 | borderDarkest: '#0a0a0a',
10 | borderLight: '#5d6d54',
11 | borderLightest: '#788475',
12 | canvas: '#3e4639',
13 | canvasText: '#f6fbf5',
14 | canvasTextDisabled: '#2c3125',
15 | canvasTextDisabledShadow: '#788475',
16 | canvasTextInvert: '#f6fbf5',
17 | checkmark: '#f6fbf5',
18 | checkmarkDisabled: '#2c3125',
19 | desktopBackground: '#bcbd52',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#4b5844',
24 | headerNotActiveBackground: '#4b5844',
25 | headerNotActiveText: '#74806e',
26 | headerText: '#fefefe',
27 | hoverBackground: '#978830',
28 | material: '#4b5844',
29 | materialDark: '#2f3428',
30 | materialText: '#f6fbf5',
31 | materialTextDisabled: '#2c3125',
32 | materialTextDisabledShadow: '#788475',
33 | materialTextInvert: '#fefefe',
34 | progress: '#978830',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/darkTeal.ts:
--------------------------------------------------------------------------------
1 | /* "Teal for Shelbi - Dark" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Teal-for-Shelbi-Dark-631177772
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'darkTeal',
9 | anchor: 'rgb(0, 132, 132)',
10 | anchorVisited: 'rgb(0, 132, 132)',
11 | borderDark: 'rgb(21, 43, 43)',
12 | borderDarkest: 'rgb(0, 0, 0)',
13 | borderLight: 'rgb(32, 64, 64)',
14 | borderLightest: 'rgb(88, 139, 139)',
15 | canvas: 'rgb(0, 48, 48)',
16 | canvasText: 'rgb(255, 255, 255)',
17 | canvasTextDisabled: 'rgb(21, 43, 43)',
18 | canvasTextDisabledShadow: 'rgb(88, 139, 139)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(255, 255, 255)',
21 | checkmarkDisabled: 'rgb(64, 128, 128)',
22 | desktopBackground: 'rgb(0, 64, 64)',
23 | flatDark: 'rgb(21, 43, 43)',
24 | flatLight: 'rgb(32, 64, 64)',
25 | focusSecondary: 'rgb(88, 139, 139)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(0, 96, 96), rgb(0, 132, 132))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(24, 50, 50), rgb(92, 112, 112))',
30 | headerNotActiveText: 'rgb(192, 204, 204)',
31 | headerText: 'rgb(255, 255, 255)',
32 | hoverBackground: 'rgb(0, 128, 128)',
33 | material: 'rgb(32, 64, 64)',
34 | materialDark: 'rgb(24, 50, 50)',
35 | materialText: 'rgb(255, 255, 255)',
36 | materialTextDisabled: 'rgb(21, 43, 43)',
37 | materialTextDisabledShadow: 'rgb(88, 139, 139)',
38 | materialTextInvert: 'rgb(255, 255, 255)',
39 | progress: 'rgb(0, 128, 128)',
40 | tooltip: 'rgb(0, 32, 32)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/denim.ts:
--------------------------------------------------------------------------------
1 | /* "Denim" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Denim-870494744
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'denim',
9 | anchor: 'rgb(0, 0, 128)',
10 | anchorVisited: 'rgb(0, 0, 128)',
11 | borderDark: 'rgb(0, 0, 255)',
12 | borderDarkest: 'rgb(64, 64, 64)',
13 | borderLight: 'rgb(128, 128, 255)',
14 | borderLightest: 'rgb(191, 191, 255)',
15 | canvas: 'rgb(255, 255, 255)',
16 | canvasText: 'rgb(0, 0, 0)',
17 | canvasTextDisabled: 'rgb(0, 0, 255)',
18 | canvasTextDisabledShadow: 'rgb(191, 191, 255)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(0, 0, 0)',
21 | checkmarkDisabled: 'rgb(0, 0, 255)',
22 | desktopBackground: 'rgb(0, 64, 128)',
23 | flatDark: 'rgb(0, 0, 255)',
24 | flatLight: 'rgb(128, 128, 255)',
25 | focusSecondary: 'rgb(191, 191, 255)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(10, 36, 106), rgb(148, 190, 237))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(0, 0, 255), rgb(180, 180, 180))',
30 | headerNotActiveText: 'rgb(192, 192, 192)',
31 | headerText: 'rgb(255, 255, 255)',
32 | hoverBackground: 'rgb(10, 36, 106)',
33 | material: 'rgb(128, 128, 255)',
34 | materialDark: 'rgb(0, 0, 255)',
35 | materialText: 'rgb(0, 0, 0)',
36 | materialTextDisabled: 'rgb(0, 0, 255)',
37 | materialTextDisabledShadow: 'rgb(191, 191, 255)',
38 | materialTextInvert: 'rgb(255, 255, 255)',
39 | progress: 'rgb(10, 36, 106)',
40 | tooltip: 'rgb(255, 255, 225)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/eggplant.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'eggplant',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#526d67',
9 | borderDarkest: '#050608',
10 | borderLight: '#a2c7c0',
11 | borderLightest: '#cee8e3',
12 | canvas: '#ffffff',
13 | canvasText: '#050608',
14 | canvasTextDisabled: '#526d67',
15 | canvasTextDisabledShadow: '#cee8e3',
16 | canvasTextInvert: '#cee8e3',
17 | checkmark: '#050608',
18 | checkmarkDisabled: '#526d67',
19 | desktopBackground: '#400040',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#4b8178',
24 | headerNotActiveBackground: '#89b0a8',
25 | headerNotActiveText: '#4b8178',
26 | headerText: '#ffffff',
27 | hoverBackground: '#4b8178',
28 | material: '#89b0a8',
29 | materialDark: '#9a9e9c',
30 | materialText: '#050608',
31 | materialTextDisabled: '#526d67',
32 | materialTextDisabledShadow: '#cee8e3',
33 | materialTextInvert: '#ffffff',
34 | progress: '#4b8178',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/fxDev.ts:
--------------------------------------------------------------------------------
1 | /* "FxDev" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/FxDev-701274128
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'fxDev',
9 | anchor: 'rgb(47, 138, 202)',
10 | anchorVisited: 'rgb(47, 138, 202)',
11 | borderDark: 'rgb(27, 33, 39)',
12 | borderDarkest: 'rgb(7, 9, 10)',
13 | borderLight: 'rgb(69, 82, 94)',
14 | borderLightest: 'rgb(107, 113, 122)',
15 | canvas: 'rgb(23, 27, 31)',
16 | canvasText: 'rgb(245, 247, 250)',
17 | canvasTextDisabled: 'rgb(27, 33, 39)',
18 | canvasTextDisabledShadow: 'rgb(107, 113, 122)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(245, 247, 250)',
21 | checkmarkDisabled: 'rgb(133, 136, 140)',
22 | desktopBackground: 'rgb(26, 58, 99)',
23 | flatDark: 'rgb(27, 33, 39)',
24 | flatLight: 'rgb(57, 66, 77)',
25 | focusSecondary: 'rgb(107, 113, 122)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(26, 70, 102), rgb(26, 70, 102))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(28, 33, 38), rgb(28, 33, 38))',
30 | headerNotActiveText: 'rgb(245, 247, 250)',
31 | headerText: 'rgb(245, 247, 250)',
32 | hoverBackground: 'rgb(7, 77, 117)',
33 | material: 'rgb(57, 66, 77)',
34 | materialDark: 'rgb(28, 33, 38)',
35 | materialText: 'rgb(255, 255, 255)',
36 | materialTextDisabled: 'rgb(27, 33, 39)',
37 | materialTextDisabledShadow: 'rgb(107, 113, 122)',
38 | materialTextInvert: 'rgb(255, 255, 255)',
39 | progress: 'rgb(7, 77, 117)',
40 | tooltip: 'rgb(243, 242, 219)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/highContrast.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'highContrast',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#888c8f',
9 | borderDarkest: '#ffffff',
10 | borderLight: '#dfe0e3',
11 | borderLightest: '#ffffff',
12 | canvas: '#353535',
13 | canvasText: '#ffffff',
14 | canvasTextDisabled: '#888c8f',
15 | canvasTextDisabledShadow: '#ffffff',
16 | canvasTextInvert: '#ffffff',
17 | checkmark: '#ffffff',
18 | checkmarkDisabled: '#888c8f',
19 | desktopBackground: '#000000',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#8e0284',
24 | headerNotActiveBackground: '#7f7f7f',
25 | headerNotActiveText: '#ced0cf',
26 | headerText: '#ffffff',
27 | hoverBackground: '#8e0284',
28 | material: '#000000',
29 | materialDark: '#9a9e9c',
30 | materialText: '#ffffff',
31 | materialTextDisabled: '#888c8f',
32 | materialTextDisabledShadow: '#ffffff',
33 | materialTextInvert: '#ffffff',
34 | progress: '#8e0284',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/honey.ts:
--------------------------------------------------------------------------------
1 | /* "Honey" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Honey-632126512
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'honey',
9 | anchor: 'rgb(128, 128, 0)',
10 | anchorVisited: 'rgb(128, 128, 0)',
11 | borderDark: 'rgb(170, 123, 0)',
12 | borderDarkest: 'rgb(64, 64, 64)',
13 | borderLight: 'rgb(255, 186, 0)',
14 | borderLightest: 'rgb(255, 220, 128)',
15 | canvas: 'rgb(255, 220, 128)',
16 | canvasText: 'rgb(0, 0, 0)',
17 | canvasTextDisabled: 'rgb(170, 123, 0)',
18 | canvasTextDisabledShadow: 'rgb(255, 220, 128)',
19 | canvasTextInvert: 'rgb(255, 255, 0)',
20 | checkmark: 'rgb(0, 0, 0)',
21 | checkmarkDisabled: 'rgb(170, 123, 0)',
22 | desktopBackground: 'rgb(170, 123, 0)',
23 | flatDark: 'rgb(170, 123, 0)',
24 | flatLight: 'rgb(255, 186, 0)',
25 | focusSecondary: 'rgb(255, 220, 128)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(255, 255, 0), rgb(255, 186, 0))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(255, 186, 0), rgb(255, 220, 128))',
30 | headerNotActiveText: 'rgb(170, 123, 0)',
31 | headerText: 'rgb(0, 0, 0)',
32 | hoverBackground: 'rgb(170, 123, 0)',
33 | material: 'rgb(255, 186, 0)',
34 | materialDark: 'rgb(255, 186, 0)',
35 | materialText: 'rgb(0, 0, 0)',
36 | materialTextDisabled: 'rgb(170, 123, 0)',
37 | materialTextDisabledShadow: 'rgb(255, 220, 128)',
38 | materialTextInvert: 'rgb(255, 255, 0)',
39 | progress: 'rgb(170, 123, 0)',
40 | tooltip: 'rgb(255, 220, 128)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/hotChocolate.ts:
--------------------------------------------------------------------------------
1 | /* "Hot Chocolate" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Hot-Chocolate-654380979
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'hotChocolate',
9 | anchor: 'rgb(128, 96, 64)',
10 | anchorVisited: 'rgb(128, 96, 64)',
11 | borderDark: 'rgb(128, 96, 64)',
12 | borderDarkest: 'rgb(64, 64, 64)',
13 | borderLight: 'rgb(181, 143, 106)',
14 | borderLightest: 'rgb(219, 200, 181)',
15 | canvas: 'rgb(219, 200, 181)',
16 | canvasText: 'rgb(57, 43, 28)',
17 | canvasTextDisabled: 'rgb(128, 96, 64)',
18 | canvasTextDisabledShadow: 'rgb(219, 200, 181)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(57, 43, 28)',
21 | checkmarkDisabled: 'rgb(128, 96, 64)',
22 | desktopBackground: 'rgb(109, 82, 54)',
23 | flatDark: 'rgb(128, 96, 64)',
24 | flatLight: 'rgb(181, 143, 106)',
25 | focusSecondary: 'rgb(219, 200, 181)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(128, 96, 64), rgb(208, 183, 157))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(128, 96, 64), rgb(128, 96, 64))',
30 | headerNotActiveText: 'rgb(219, 200, 181)',
31 | headerText: 'rgb(255, 255, 255)',
32 | hoverBackground: 'rgb(128, 96, 64)',
33 | material: 'rgb(181, 143, 106)',
34 | materialDark: 'rgb(128, 96, 64)',
35 | materialText: 'rgb(57, 43, 28)',
36 | materialTextDisabled: 'rgb(128, 96, 64)',
37 | materialTextDisabledShadow: 'rgb(219, 200, 181)',
38 | materialTextInvert: 'rgb(255, 255, 255)',
39 | progress: 'rgb(128, 96, 64)',
40 | tooltip: 'rgb(219, 200, 181)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/hotdogStand.ts:
--------------------------------------------------------------------------------
1 | /* "Hotdog Stand" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Hotdog-Stand-525606846
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'hotdogStand',
9 | anchor: 'rgb(255, 255, 0)',
10 | anchorVisited: 'rgb(255, 255, 0)',
11 | borderDark: 'rgb(0, 0, 0)',
12 | borderDarkest: 'rgb(0, 0, 0)',
13 | borderLight: 'rgb(0, 0, 0)',
14 | borderLightest: 'rgb(0, 0, 0)',
15 | canvas: 'rgb(255, 0, 0)',
16 | canvasText: 'rgb(255, 255, 255)',
17 | canvasTextDisabled: 'rgb(0, 0, 0)',
18 | canvasTextDisabledShadow: 'rgb(0, 0, 0)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(255, 255, 255)',
21 | checkmarkDisabled: 'rgb(128, 128, 128)',
22 | desktopBackground: 'rgb(255, 255, 0)',
23 | flatDark: 'rgb(0, 0, 0)',
24 | flatLight: 'rgb(0, 0, 0)',
25 | focusSecondary: 'rgb(0, 0, 0)',
26 | headerBackground: 'linear-gradient(to right, rgb(0, 0, 0), rgb(0, 0, 0))',
27 | headerNotActiveBackground:
28 | 'linear-gradient(to right, rgb(255, 0, 0), rgb(255, 0, 0))',
29 | headerNotActiveText: 'rgb(255, 255, 255)',
30 | headerText: 'rgb(255, 255, 255)',
31 | hoverBackground: 'rgb(0, 0, 0)',
32 | material: 'rgb(255, 0, 0)',
33 | materialDark: 'rgb(255, 0, 0)',
34 | materialText: 'rgb(255, 255, 255)',
35 | materialTextDisabled: 'rgb(0, 0, 0)',
36 | materialTextDisabledShadow: 'rgb(0, 0, 0)',
37 | materialTextInvert: 'rgb(255, 255, 255)',
38 | progress: 'rgb(0, 0, 0)',
39 | tooltip: 'rgb(255, 255, 225)'
40 | } as Theme;
41 |
--------------------------------------------------------------------------------
/src/common/themes/lilac.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'lilac',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#5f549b',
9 | borderDarkest: '#1c1449',
10 | borderLight: '#bcb4e9',
11 | borderLightest: '#d3ccf4',
12 | canvas: '#ffffff',
13 | canvasText: '#050608',
14 | canvasTextDisabled: '#5f549b',
15 | canvasTextDisabledShadow: '#ffffff',
16 | canvasTextInvert: '#ffffff',
17 | checkmark: '#050608',
18 | checkmarkDisabled: '#5f549b',
19 | desktopBackground: '#000000',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#5e4dba',
24 | headerNotActiveBackground: '#7f7f81',
25 | headerNotActiveText: '#ced0cf',
26 | headerText: '#ffffff',
27 | hoverBackground: '#5e4dba',
28 | material: '#b1a7df',
29 | materialDark: '#9a9e9c',
30 | materialText: '#050608',
31 | materialTextDisabled: '#5f549b',
32 | materialTextDisabledShadow: '#ffffff',
33 | materialTextInvert: '#ffffff',
34 | progress: '#5e4dba',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/lilacRoseDark.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'lilacRoseDark',
5 |
6 | anchor: '#a65387',
7 | anchorVisited: '#440381',
8 | background: '#3B3B58',
9 | borderDark: '#7F3163',
10 | borderDarkest: '#190000',
11 | borderLight: '#E597C9',
12 | borderLightest: '#FFCAFC',
13 | canvas: '#dab1c7',
14 | canvasText: '#000000',
15 | canvasTextDisabled: '#000000',
16 | canvasTextDisabledShadow: '#000000',
17 | canvasTextInvert: '#ecbfe3',
18 | checkmark: '#010601',
19 | checkmarkDisabled: '#7F3163',
20 | desktopBackground: '#663956',
21 | flatDark: '#7F3163',
22 | flatLight: '#E597C9',
23 | focusSecondary: '#fefe03',
24 | headerBackground: '#4C0030',
25 | headerNotActiveBackground: '#763a60',
26 | headerNotActiveText: '#b26496',
27 | headerText: '#010601',
28 | hoverBackground: '#713259',
29 | material: '#b26496',
30 | materialDark: '#763a60',
31 | materialText: '#000000',
32 | materialTextDisabled: '#82416d',
33 | materialTextDisabledShadow: '#ecbfe3',
34 | materialTextInvert: '#ecbfe3',
35 | progress: '#713259',
36 | tooltip: '#fefbcc'
37 | } as Theme;
38 |
--------------------------------------------------------------------------------
/src/common/themes/maple.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'maple',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#ab9042',
9 | borderDarkest: '#2a1801',
10 | borderLight: '#f5e2bb',
11 | borderLightest: '#ffffff',
12 | canvas: '#ffffff',
13 | canvasText: '#2a1801',
14 | canvasTextDisabled: '#ab9042',
15 | canvasTextDisabledShadow: '#ffffff',
16 | canvasTextInvert: '#ffffff',
17 | checkmark: '#2a1801',
18 | checkmarkDisabled: '#ab9042',
19 | desktopBackground: '#000000',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#8e0101',
24 | headerNotActiveBackground: '#a1a0a5',
25 | headerNotActiveText: '#f5e2bb',
26 | headerText: '#ffffff',
27 | hoverBackground: '#8e0101',
28 | material: '#e5cc90',
29 | materialDark: '#9a9e9c',
30 | materialText: '#2a1801',
31 | materialTextDisabled: '#ab9042',
32 | materialTextDisabledShadow: '#ffffff',
33 | materialTextInvert: '#ffffff',
34 | progress: '#8e0101',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/marine.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'marine',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#3c8d88',
9 | borderDarkest: '#050608',
10 | borderLight: '#98d2cb',
11 | borderLightest: '#b1dfdf',
12 | canvas: '#c3e2da',
13 | canvasText: '#050608',
14 | canvasTextDisabled: '#3c8d88',
15 | canvasTextDisabledShadow: '#ffffff',
16 | canvasTextInvert: '#ffffff',
17 | checkmark: '#050608',
18 | checkmarkDisabled: '#3c8d88',
19 | desktopBackground: '#2c4e47',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#000080',
24 | headerNotActiveBackground: '#7f7f7f',
25 | headerNotActiveText: '#ced0cf',
26 | headerText: '#ffffff',
27 | hoverBackground: '#000080',
28 | material: '#75c1ba',
29 | materialDark: '#9a9e9c',
30 | materialText: '#050608',
31 | materialTextDisabled: '#3c8d88',
32 | materialTextDisabledShadow: '#ffffff',
33 | materialTextInvert: '#ffffff',
34 | progress: '#000080',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/matrix.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'matrix',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#282828',
9 | borderDarkest: '#000000',
10 | borderLight: '#656565',
11 | borderLightest: '#a7a7a7',
12 | canvas: '#c0c0c0',
13 | canvasText: '#000000',
14 | canvasTextDisabled: '#282828',
15 | canvasTextDisabledShadow: '#ff0000',
16 | canvasTextInvert: '#ffffff',
17 | checkmark: '#000000',
18 | checkmarkDisabled: '#282828',
19 | desktopBackground: '#000000',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#35FF69',
23 | headerBackground: '#000000',
24 | headerNotActiveBackground: '#7f7f7f',
25 | headerNotActiveText: '#535353',
26 | headerText: '#a7a7a7',
27 | hoverBackground: '#000000',
28 | material: '#535353',
29 | materialDark: '#282828',
30 | materialText: '#35FF69',
31 | materialTextDisabled: '#282828',
32 | materialTextDisabledShadow: '#a7a7a7',
33 | materialTextInvert: '#ffffff',
34 | progress: '#000000',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/millenium.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'millenium',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#828282',
9 | borderDarkest: 'black',
10 | borderLight: '#e5e5e5',
11 | borderLightest: '#ffffff',
12 | canvas: '#ffffff',
13 | canvasText: 'black',
14 | canvasTextDisabled: '#828282',
15 | canvasTextDisabledShadow: '#ffffff',
16 | canvasTextInvert: '#ffffff',
17 | checkmark: 'black',
18 | checkmarkDisabled: '#828282',
19 | desktopBackground: '#3a6ea5',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: 'linear-gradient(to right, #012470, #a5c7e7)',
24 | headerNotActiveBackground: '#7f7f7f',
25 | headerNotActiveText: '#d6cfc7',
26 | headerText: '#ffffff',
27 | hoverBackground: '#00256e',
28 | material: '#d6cfc7',
29 | materialDark: '#9a9e9c',
30 | materialText: 'black',
31 | materialTextDisabled: '#828282',
32 | materialTextDisabledShadow: '#ffffff',
33 | materialTextInvert: '#ffffff',
34 | progress: '#00256e',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/modernDark.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'modernDark',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#121317',
9 | borderDarkest: '#000000',
10 | borderLight: '#31323c',
11 | borderLightest: '#4b4d58',
12 | canvas: '#4b4d58',
13 | canvasText: '#000000',
14 | canvasTextDisabled: '#4b4d58',
15 | canvasTextDisabledShadow: '#4b4d58',
16 | canvasTextInvert: '#202127',
17 | checkmark: '#000000',
18 | checkmarkDisabled: '#121317',
19 | desktopBackground: '#000000',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#4b4d58',
24 | headerNotActiveBackground: 'transparent',
25 | headerNotActiveText: '#4b4d58',
26 | headerText: '#202127',
27 | hoverBackground: '#f88702',
28 | material: '#202127',
29 | materialDark: '#9a9e9c',
30 | materialText: '#f88702',
31 | materialTextDisabled: '#4b4d58',
32 | materialTextDisabledShadow: '#121317',
33 | materialTextInvert: '#202127',
34 | progress: '#f88702',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/molecule.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'molecule',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#993845',
9 | borderDarkest: '#4b4d4e',
10 | borderLight: '#dfe0e3',
11 | borderLightest: '#d79099',
12 | canvas: '#f1f5f6',
13 | canvasText: '#020102',
14 | canvasTextDisabled: '#993845',
15 | canvasTextDisabledShadow: '#d79099',
16 | canvasTextInvert: '#f1f5f6',
17 | checkmark: '#020102',
18 | checkmarkDisabled: '#993845',
19 | desktopBackground: '#3a6ea5',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#a03d49',
24 | headerNotActiveBackground: '#7f7f7f',
25 | headerNotActiveText: '#c2c1c2',
26 | headerText: '#f1f5f6',
27 | hoverBackground: '#70a3ce',
28 | material: '#c2c1c2',
29 | materialDark: '#9a9e9c',
30 | materialText: '#020102',
31 | materialTextDisabled: '#993845',
32 | materialTextDisabledShadow: '#d79099',
33 | materialTextInvert: '#f1f5f6',
34 | progress: '#a03d49',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/monochrome.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react95-io/React95/871d5335daebdda1469f66f81266523f4191a595/src/common/themes/monochrome.ts
--------------------------------------------------------------------------------
/src/common/themes/ninjaTurtles.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'ninjaTurtles',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#017401',
9 | borderDarkest: '#000000',
10 | borderLight: '#1dbc1b',
11 | borderLightest: '#55fd55',
12 | canvas: '#ffffff',
13 | canvasText: '#000000',
14 | canvasTextDisabled: '#017401',
15 | canvasTextDisabledShadow: '#55fd55',
16 | canvasTextInvert: '#000000',
17 | checkmark: '#000000',
18 | checkmarkDisabled: '#017401',
19 | desktopBackground: '#045424',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#FF1D15',
24 | headerNotActiveBackground: '#7f7f7f',
25 | headerNotActiveText: '#000000',
26 | headerText: '#ffffff',
27 | hoverBackground: '#FABC3C',
28 | material: '#00a800',
29 | materialDark: '#9a9e9c',
30 | materialText: '#000000',
31 | materialTextDisabled: '#017401',
32 | materialTextDisabledShadow: '#55fd55',
33 | materialTextInvert: '#000000',
34 | progress: '#FF1D15',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/olive.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'olive',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#4f4c02',
9 | borderDarkest: '#000000',
10 | borderLight: '#9d9d11',
11 | borderLightest: '#fcfd3e',
12 | canvas: '#ffffff',
13 | canvasText: '#000000',
14 | canvasTextDisabled: '#4f4c02',
15 | canvasTextDisabledShadow: '#fcfd3e',
16 | canvasTextInvert: '#000000',
17 | checkmark: '#000000',
18 | checkmarkDisabled: '#4f4c02',
19 | desktopBackground: '#666633',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#000000',
23 | headerBackground: '#F3DE2C',
24 | headerNotActiveBackground: '#4f4c02',
25 | headerNotActiveText: '#807f00',
26 | headerText: '#000000',
27 | hoverBackground: '#F3DE2C',
28 | material: '#807f00',
29 | materialDark: '#4f4c02',
30 | materialText: '#000000',
31 | materialTextDisabled: '#4f4c02',
32 | materialTextDisabledShadow: '#fcfd3e',
33 | materialTextInvert: '#000000',
34 | progress: '#F3DE2C',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/original.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'original',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#848584',
9 | borderDarkest: '#0a0a0a',
10 | borderLight: '#dfdfdf',
11 | borderLightest: '#fefefe',
12 | canvas: '#ffffff',
13 | canvasText: '#0a0a0a',
14 | canvasTextDisabled: '#848584',
15 | canvasTextDisabledShadow: '#fefefe',
16 | canvasTextInvert: '#fefefe',
17 | checkmark: '#0a0a0a',
18 | checkmarkDisabled: '#848584',
19 | desktopBackground: '#008080',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#060084',
24 | headerNotActiveBackground: '#7f787f',
25 | headerNotActiveText: '#c6c6c6',
26 | headerText: '#fefefe',
27 | hoverBackground: '#060084',
28 | material: '#c6c6c6',
29 | materialDark: '#9a9e9c',
30 | materialText: '#0a0a0a',
31 | materialTextDisabled: '#848584',
32 | materialTextDisabledShadow: '#fefefe',
33 | materialTextInvert: '#fefefe',
34 | progress: '#060084',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/pamelaAnderson.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'pamelaAnderson',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#7e0541',
9 | borderDarkest: '#000000',
10 | borderLight: '#ff308f',
11 | borderLightest: '#ff7ebf',
12 | canvas: '#F5CCE8',
13 | canvasText: '#000000',
14 | canvasTextDisabled: '#7e0541',
15 | canvasTextDisabledShadow: '#ff7ebf',
16 | canvasTextInvert: '#F1E4E8',
17 | checkmark: '#000000',
18 | checkmarkDisabled: '#7e0541',
19 | desktopBackground: '#000000',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#FF8CC6',
24 | headerNotActiveBackground: '#95818D',
25 | headerNotActiveText: '#ff0080',
26 | headerText: '#000000',
27 | hoverBackground: '#004FFF',
28 | material: '#ff0080',
29 | materialDark: '#95818D',
30 | materialText: '#000000',
31 | materialTextDisabled: '#7e0541',
32 | materialTextDisabledShadow: '#ff7ebf',
33 | materialTextInvert: '#F1E4E8',
34 | progress: '#004FFF',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/peggysPastels.ts:
--------------------------------------------------------------------------------
1 | /* "Peggy's Pastels" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Peggy-s-Pastels-505540096
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'peggysPastels',
9 | anchor: 'rgb(0, 128, 128)',
10 | anchorVisited: 'rgb(0, 128, 128)',
11 | borderDark: 'rgb(222, 69, 96)',
12 | borderDarkest: 'rgb(64, 64, 64)',
13 | borderLight: 'rgb(247, 219, 215)',
14 | borderLightest: 'rgb(250, 224, 228)',
15 | canvas: 'rgb(244, 255, 255)',
16 | canvasText: 'rgb(0, 0, 0)',
17 | canvasTextDisabled: 'rgb(222, 69, 96)',
18 | canvasTextDisabledShadow: 'rgb(250, 224, 228)',
19 | canvasTextInvert: 'rgb(0, 0, 0)',
20 | checkmark: 'rgb(0, 0, 0)',
21 | checkmarkDisabled: 'rgb(222, 69, 96)',
22 | desktopBackground: 'rgb(162, 219, 210)',
23 | flatDark: 'rgb(222, 69, 96)',
24 | flatLight: 'rgb(247, 219, 215)',
25 | focusSecondary: 'rgb(250, 224, 228)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(0, 191, 188), rgb(202, 156, 185))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(0, 187, 169), rgb(236, 145, 162))',
30 | headerNotActiveText: 'rgb(0, 85, 77)',
31 | headerText: 'rgb(255, 255, 255)',
32 | hoverBackground: 'rgb(162, 219, 210)',
33 | material: 'rgb(244, 193, 202)',
34 | materialDark: 'rgb(0, 187, 169)',
35 | materialText: 'rgb(0, 0, 0)',
36 | materialTextDisabled: 'rgb(222, 69, 96)',
37 | materialTextDisabledShadow: 'rgb(250, 224, 228)',
38 | materialTextInvert: 'rgb(0, 0, 0)',
39 | progress: 'rgb(162, 219, 210)',
40 | tooltip: 'rgb(204, 255, 255)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/plum.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'plum',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#7b5f5b',
9 | borderDarkest: '#050608',
10 | borderLight: '#c3b1aa',
11 | borderLightest: '#e8dad6',
12 | canvas: '#dad0c7',
13 | canvasText: '#050608',
14 | canvasTextDisabled: '#7b5f5b',
15 | canvasTextDisabledShadow: '#e8dad6',
16 | canvasTextInvert: '#e8dad6',
17 | checkmark: '#050608',
18 | checkmarkDisabled: '#7b5f5b',
19 | desktopBackground: '#402840',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#483f63',
24 | headerNotActiveBackground: '#7d5e58',
25 | headerNotActiveText: '#e8dad6',
26 | headerText: '#ffffff',
27 | hoverBackground: '#483f63',
28 | material: '#ac978f',
29 | materialDark: '#9a9e9c',
30 | materialText: '#050608',
31 | materialTextDisabled: '#7b5f5b',
32 | materialTextDisabledShadow: '#e8dad6',
33 | materialTextInvert: '#ffffff',
34 | progress: '#483f63',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/polarized.ts:
--------------------------------------------------------------------------------
1 | /* "Polarized" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Polarized-557712217
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'polarized',
9 | anchor: 'rgb(160, 160, 128)',
10 | anchorVisited: 'rgb(160, 160, 128)',
11 | borderDark: 'rgb(60, 60, 194)',
12 | borderDarkest: 'rgb(60, 60, 194)',
13 | borderLight: 'rgb(60, 60, 194)',
14 | borderLightest: 'rgb(60, 60, 194)',
15 | canvas: 'rgb(52, 52, 204)',
16 | canvasText: 'rgb(255, 255, 0)',
17 | canvasTextDisabled: 'rgb(60, 60, 194)',
18 | canvasTextDisabledShadow: 'rgb(60, 60, 194)',
19 | canvasTextInvert: 'rgb(0, 0, 255)',
20 | checkmark: 'rgb(255, 255, 0)',
21 | checkmarkDisabled: 'rgb(101, 101, 154)',
22 | desktopBackground: 'rgb(180, 180, 76)',
23 | flatDark: 'rgb(60, 60, 194)',
24 | flatLight: 'rgb(60, 60, 194)',
25 | focusSecondary: 'rgb(60, 60, 194)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(192, 192, 64), rgb(192, 192, 64))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(64, 64, 192), rgb(170, 170, 84))',
30 | headerNotActiveText: 'rgb(192, 192, 192)',
31 | headerText: 'rgb(0, 0, 255)',
32 | hoverBackground: 'rgb(192, 192, 64)',
33 | material: 'rgb(120, 120, 136)',
34 | materialDark: 'rgb(64, 64, 192)',
35 | materialText: 'rgb(255, 255, 0)',
36 | materialTextDisabled: 'rgb(60, 60, 194)',
37 | materialTextDisabledShadow: 'rgb(60, 60, 194)',
38 | materialTextInvert: 'rgb(0, 0, 255)',
39 | progress: 'rgb(192, 192, 64)',
40 | tooltip: 'rgb(16, 16, 240)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/powerShell.ts:
--------------------------------------------------------------------------------
1 | /* "PowerShell" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/PowerShell-646065752
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'powerShell',
9 | anchor: 'rgb(0, 192, 0)',
10 | anchorVisited: 'rgb(0, 192, 0)',
11 | borderDark: 'rgb(128, 128, 128)',
12 | borderDarkest: 'rgb(128, 128, 128)',
13 | borderLight: 'rgb(128, 128, 128)',
14 | borderLightest: 'rgb(128, 128, 128)',
15 | canvas: 'rgb(1, 36, 86)',
16 | canvasText: 'rgb(238, 237, 240)',
17 | canvasTextDisabled: 'rgb(128, 128, 128)',
18 | canvasTextDisabledShadow: 'rgb(128, 128, 128)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(238, 237, 240)',
21 | checkmarkDisabled: 'rgb(180, 180, 180)',
22 | desktopBackground: 'rgb(1, 36, 86)',
23 | flatDark: 'rgb(128, 128, 128)',
24 | flatLight: 'rgb(128, 128, 128)',
25 | focusSecondary: 'rgb(128, 128, 128)',
26 | headerBackground: 'linear-gradient(to right, rgb(1, 36, 86), rgb(1, 36, 86))',
27 | headerNotActiveBackground:
28 | 'linear-gradient(to right, rgb(1, 36, 86), rgb(1, 36, 86))',
29 | headerNotActiveText: 'rgb(192, 192, 192)',
30 | headerText: 'rgb(255, 255, 255)',
31 | hoverBackground: 'rgb(0, 128, 128)',
32 | material: 'rgb(1, 36, 86)',
33 | materialDark: 'rgb(1, 36, 86)',
34 | materialText: 'rgb(255, 255, 255)',
35 | materialTextDisabled: 'rgb(128, 128, 128)',
36 | materialTextDisabledShadow: 'rgb(128, 128, 128)',
37 | materialTextInvert: 'rgb(255, 255, 255)',
38 | progress: 'rgb(0, 128, 128)',
39 | tooltip: 'rgb(255, 255, 225)'
40 | } as Theme;
41 |
--------------------------------------------------------------------------------
/src/common/themes/rainyDay.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'rainyDay',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#3d5367',
9 | borderDarkest: '#16233b',
10 | borderLight: '#91abc2',
11 | borderLightest: '#b7cee5',
12 | canvas: '#ffffff',
13 | canvasText: '#050608',
14 | canvasTextDisabled: '#3d5367',
15 | canvasTextDisabledShadow: '#b7cee5',
16 | canvasTextInvert: '#ffffff',
17 | checkmark: '#050608',
18 | checkmarkDisabled: '#3d5367',
19 | desktopBackground: '#000000',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#4b6480',
24 | headerNotActiveBackground: '#7f7f81',
25 | headerNotActiveText: '#ced0d9',
26 | headerText: '#ffffff',
27 | hoverBackground: '#4b6480',
28 | material: '#7a99b3',
29 | materialDark: '#9a9e9c',
30 | materialText: '#050608',
31 | materialTextDisabled: '#3d5367',
32 | materialTextDisabledShadow: '#b7cee5',
33 | materialTextInvert: '#ffffff',
34 | progress: '#4b6480',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/raspberry.ts:
--------------------------------------------------------------------------------
1 | /* "Raspberry" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Raspberry-539289720
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'raspberry',
9 | anchor: 'rgb(10, 36, 106)',
10 | anchorVisited: 'rgb(10, 36, 106)',
11 | borderDark: 'rgb(92, 101, 107)',
12 | borderDarkest: 'rgb(64, 64, 64)',
13 | borderLight: 'rgb(142, 151, 157)',
14 | borderLightest: 'rgb(200, 204, 206)',
15 | canvas: 'rgb(255, 255, 255)',
16 | canvasText: 'rgb(0, 0, 0)',
17 | canvasTextDisabled: 'rgb(92, 101, 107)',
18 | canvasTextDisabledShadow: 'rgb(200, 204, 206)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(0, 0, 0)',
21 | checkmarkDisabled: 'rgb(92, 101, 107)',
22 | desktopBackground: 'rgb(0, 64, 128)',
23 | flatDark: 'rgb(92, 101, 107)',
24 | flatLight: 'rgb(142, 151, 157)',
25 | focusSecondary: 'rgb(200, 204, 206)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(10, 36, 106), rgb(153, 0, 51))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(92, 101, 107), rgb(92, 101, 107))',
30 | headerNotActiveText: 'rgb(212, 208, 200)',
31 | headerText: 'rgb(255, 255, 255)',
32 | hoverBackground: 'rgb(10, 36, 106)',
33 | material: 'rgb(142, 151, 157)',
34 | materialDark: 'rgb(92, 101, 107)',
35 | materialText: 'rgb(0, 0, 0)',
36 | materialTextDisabled: 'rgb(92, 101, 107)',
37 | materialTextDisabledShadow: 'rgb(200, 204, 206)',
38 | materialTextInvert: 'rgb(255, 255, 255)',
39 | progress: 'rgb(10, 36, 106)',
40 | tooltip: 'rgb(255, 255, 225)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/redWine.ts:
--------------------------------------------------------------------------------
1 | /* "Red Wine" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Red-Wine-545729607
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'redWine',
9 | anchor: 'rgb(255, 0, 0)',
10 | anchorVisited: 'rgb(255, 0, 0)',
11 | borderDark: 'rgb(67, 9, 5)',
12 | borderDarkest: 'rgb(64, 32, 32)',
13 | borderLight: 'rgb(102, 12, 8)',
14 | borderLightest: 'rgb(192, 64, 56)',
15 | canvas: 'rgb(64, 0, 0)',
16 | canvasText: 'rgb(255, 255, 255)',
17 | canvasTextDisabled: 'rgb(67, 9, 5)',
18 | canvasTextDisabledShadow: 'rgb(192, 64, 56)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(255, 255, 255)',
21 | checkmarkDisabled: 'rgb(192, 64, 64)',
22 | desktopBackground: 'rgb(147, 9, 0)',
23 | flatDark: 'rgb(67, 9, 5)',
24 | flatLight: 'rgb(102, 12, 8)',
25 | focusSecondary: 'rgb(192, 64, 56)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(64, 0, 12), rgb(217, 11, 0))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(0, 0, 0), rgb(134, 4, 2))',
30 | headerNotActiveText: 'rgb(239, 44, 33)',
31 | headerText: 'rgb(255, 255, 255)',
32 | hoverBackground: 'rgb(192, 0, 0)',
33 | material: 'rgb(102, 12, 8)',
34 | materialDark: 'rgb(0, 0, 0)',
35 | materialText: 'rgb(255, 255, 255)',
36 | materialTextDisabled: 'rgb(67, 9, 5)',
37 | materialTextDisabledShadow: 'rgb(192, 64, 56)',
38 | materialTextInvert: 'rgb(255, 255, 255)',
39 | progress: 'rgb(192, 0, 0)',
40 | tooltip: 'rgb(64, 0, 0)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/rose.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'rose',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#8a5b68',
9 | borderDarkest: '#26030b',
10 | borderLight: '#e5bec8',
11 | borderLightest: '#f1d4dc',
12 | canvas: '#ffffff',
13 | canvasText: '#050608',
14 | canvasTextDisabled: '#8a5b68',
15 | canvasTextDisabledShadow: '#f1d4dc',
16 | canvasTextInvert: '#ffffff',
17 | checkmark: '#050608',
18 | checkmarkDisabled: '#8a5b68',
19 | desktopBackground: '#808080',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#ab5a71',
24 | headerNotActiveBackground: '#a19fa5',
25 | headerNotActiveText: '#615f68',
26 | headerText: '#ffffff',
27 | hoverBackground: '#ab5a71',
28 | material: '#d6adb8',
29 | materialDark: '#9a9e9c',
30 | materialText: '#050608',
31 | materialTextDisabled: '#8a5b68',
32 | materialTextDisabledShadow: '#f1d4dc',
33 | materialTextInvert: '#ffffff',
34 | progress: '#ab5a71',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/seawater.ts:
--------------------------------------------------------------------------------
1 | /* "Seawater" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Seawater-736002425
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'seawater',
9 | anchor: 'rgb(0, 0, 128)',
10 | anchorVisited: 'rgb(0, 0, 128)',
11 | borderDark: 'rgb(167, 194, 224)',
12 | borderDarkest: 'rgb(167, 194, 224)',
13 | borderLight: 'rgb(167, 194, 224)',
14 | borderLightest: 'rgb(167, 194, 224)',
15 | canvas: 'rgb(255, 255, 255)',
16 | canvasText: 'rgb(0, 0, 0)',
17 | canvasTextDisabled: 'rgb(167, 194, 224)',
18 | canvasTextDisabledShadow: 'rgb(167, 194, 224)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(0, 0, 0)',
21 | checkmarkDisabled: 'rgb(47, 88, 134)',
22 | desktopBackground: 'rgb(0, 128, 128)',
23 | flatDark: 'rgb(167, 194, 224)',
24 | flatLight: 'rgb(167, 194, 224)',
25 | focusSecondary: 'rgb(167, 194, 224)',
26 | headerBackground: 'linear-gradient(to right, rgb(0, 0, 128), rgb(0, 0, 128))',
27 | headerNotActiveBackground:
28 | 'linear-gradient(to right, rgb(0, 85, 170), rgb(0, 85, 170))',
29 | headerNotActiveText: 'rgb(192, 192, 192)',
30 | headerText: 'rgb(255, 255, 255)',
31 | hoverBackground: 'rgb(0, 128, 128)',
32 | material: 'rgb(79, 133, 193)',
33 | materialDark: 'rgb(0, 85, 170)',
34 | materialText: 'rgb(0, 0, 0)',
35 | materialTextDisabled: 'rgb(167, 194, 224)',
36 | materialTextDisabledShadow: 'rgb(167, 194, 224)',
37 | materialTextInvert: 'rgb(255, 255, 255)',
38 | progress: 'rgb(0, 128, 128)',
39 | tooltip: 'rgb(255, 255, 225)'
40 | } as Theme;
41 |
--------------------------------------------------------------------------------
/src/common/themes/shelbiTeal.ts:
--------------------------------------------------------------------------------
1 | /* "Teal for Shelbi" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Teal-for-Shelbi-506118460
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'shelbiTeal',
9 | anchor: 'rgb(0, 128, 128)',
10 | anchorVisited: 'rgb(0, 128, 128)',
11 | borderDark: 'rgb(96, 128, 128)',
12 | borderDarkest: 'rgb(0, 0, 0)',
13 | borderLight: 'rgb(192, 204, 204)',
14 | borderLightest: 'rgb(204, 224, 224)',
15 | canvas: 'rgb(255, 255, 255)',
16 | canvasText: 'rgb(0, 0, 0)',
17 | canvasTextDisabled: 'rgb(96, 128, 128)',
18 | canvasTextDisabledShadow: 'rgb(204, 224, 224)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(0, 0, 0)',
21 | checkmarkDisabled: 'rgb(96, 128, 128)',
22 | desktopBackground: 'rgb(0, 128, 128)',
23 | flatDark: 'rgb(96, 128, 128)',
24 | flatLight: 'rgb(192, 204, 204)',
25 | focusSecondary: 'rgb(204, 224, 224)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(0, 128, 128), rgb(0, 204, 204))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(96, 128, 128), rgb(160, 192, 192))',
30 | headerNotActiveText: 'rgb(192, 204, 204)',
31 | headerText: 'rgb(255, 255, 255)',
32 | hoverBackground: 'rgb(0, 128, 128)',
33 | material: 'rgb(168, 192, 192)',
34 | materialDark: 'rgb(96, 128, 128)',
35 | materialText: 'rgb(0, 0, 0)',
36 | materialTextDisabled: 'rgb(96, 128, 128)',
37 | materialTextDisabledShadow: 'rgb(204, 224, 224)',
38 | materialTextInvert: 'rgb(255, 255, 255)',
39 | progress: 'rgb(0, 128, 128)',
40 | tooltip: 'rgb(224, 255, 255)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/slate.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'slate',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#446b7c',
9 | borderDarkest: '#000814',
10 | borderLight: '#adc8da',
11 | borderLightest: '#c3d9e9',
12 | canvas: '#f2ffff',
13 | canvasText: '#00010f',
14 | canvasTextDisabled: '#446b7c',
15 | canvasTextDisabledShadow: '#c3d9e9',
16 | canvasTextInvert: '#f2ffff',
17 | checkmark: '#00010f',
18 | checkmarkDisabled: '#446b7c',
19 | desktopBackground: '#414141',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#448199',
24 | headerNotActiveBackground: '#807f80',
25 | headerNotActiveText: '#c2c1c2',
26 | headerText: '#f2ffff',
27 | hoverBackground: '#448199',
28 | material: '#97b9cb',
29 | materialDark: '#9a9e9c',
30 | materialText: '#00010f',
31 | materialTextDisabled: '#446b7c',
32 | materialTextDisabledShadow: '#c3d9e9',
33 | materialTextInvert: '#f2ffff',
34 | progress: '#448199',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/solarizedDark.ts:
--------------------------------------------------------------------------------
1 | /* "Solarized Dark" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Solarized-Dark-592122068
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'solarizedDark',
9 | anchor: 'rgb(38, 139, 210)',
10 | anchorVisited: 'rgb(38, 139, 210)',
11 | borderDark: 'rgb(0, 43, 54)',
12 | borderDarkest: 'rgb(0, 43, 54)',
13 | borderLight: 'rgb(0, 43, 54)',
14 | borderLightest: 'rgb(0, 43, 54)',
15 | canvas: 'rgb(0, 43, 54)',
16 | canvasText: 'rgb(131, 148, 150)',
17 | canvasTextDisabled: 'rgb(0, 43, 54)',
18 | canvasTextDisabledShadow: 'rgb(0, 43, 54)',
19 | canvasTextInvert: 'rgb(238, 232, 213)',
20 | checkmark: 'rgb(131, 148, 150)',
21 | checkmarkDisabled: 'rgb(88, 110, 117)',
22 | desktopBackground: 'rgb(0, 43, 54)',
23 | flatDark: 'rgb(0, 43, 54)',
24 | flatLight: 'rgb(0, 43, 54)',
25 | focusSecondary: 'rgb(0, 43, 54)',
26 | headerBackground: 'linear-gradient(to right, rgb(0, 43, 54), rgb(0, 43, 54))',
27 | headerNotActiveBackground:
28 | 'linear-gradient(to right, rgb(7, 54, 66), rgb(7, 54, 66))',
29 | headerNotActiveText: 'rgb(131, 148, 150)',
30 | headerText: 'rgb(108, 113, 196)',
31 | hoverBackground: 'rgb(211, 54, 130)',
32 | material: 'rgb(7, 54, 66)',
33 | materialDark: 'rgb(7, 54, 66)',
34 | materialText: 'rgb(131, 148, 150)',
35 | materialTextDisabled: 'rgb(0, 43, 54)',
36 | materialTextDisabledShadow: 'rgb(0, 43, 54)',
37 | materialTextInvert: 'rgb(238, 232, 213)',
38 | progress: 'rgb(211, 54, 130)',
39 | tooltip: 'rgb(253, 246, 227)'
40 | } as Theme;
41 |
--------------------------------------------------------------------------------
/src/common/themes/solarizedLight.ts:
--------------------------------------------------------------------------------
1 | /* "Solarized Light" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Solarized-Light-592124935
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'solarizedLight',
9 | anchor: 'rgb(38, 139, 210)',
10 | anchorVisited: 'rgb(38, 139, 210)',
11 | borderDark: 'rgb(253, 246, 227)',
12 | borderDarkest: 'rgb(253, 246, 227)',
13 | borderLight: 'rgb(253, 246, 227)',
14 | borderLightest: 'rgb(253, 246, 227)',
15 | canvas: 'rgb(253, 246, 227)',
16 | canvasText: 'rgb(101, 123, 131)',
17 | canvasTextDisabled: 'rgb(253, 246, 227)',
18 | canvasTextDisabledShadow: 'rgb(253, 246, 227)',
19 | canvasTextInvert: 'rgb(238, 232, 213)',
20 | checkmark: 'rgb(101, 123, 131)',
21 | checkmarkDisabled: 'rgb(88, 110, 117)',
22 | desktopBackground: 'rgb(253, 246, 227)',
23 | flatDark: 'rgb(253, 246, 227)',
24 | flatLight: 'rgb(253, 246, 227)',
25 | focusSecondary: 'rgb(253, 246, 227)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(253, 246, 227), rgb(253, 246, 227))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(238, 232, 213), rgb(238, 232, 213))',
30 | headerNotActiveText: 'rgb(101, 123, 131)',
31 | headerText: 'rgb(108, 113, 196)',
32 | hoverBackground: 'rgb(211, 54, 130)',
33 | material: 'rgb(238, 232, 213)',
34 | materialDark: 'rgb(238, 232, 213)',
35 | materialText: 'rgb(101, 123, 131)',
36 | materialTextDisabled: 'rgb(253, 246, 227)',
37 | materialTextDisabledShadow: 'rgb(253, 246, 227)',
38 | materialTextInvert: 'rgb(238, 232, 213)',
39 | progress: 'rgb(211, 54, 130)',
40 | tooltip: 'rgb(253, 246, 227)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/spruce.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'spruce',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#477b5e',
9 | borderDarkest: '#001004',
10 | borderLight: '#b0d2bb',
11 | borderLightest: '#cdead2',
12 | canvas: '#fcfff6',
13 | canvasText: '#050608',
14 | canvasTextDisabled: '#3d5367',
15 | canvasTextDisabledShadow: '#cdead2',
16 | canvasTextInvert: '#fcfff6',
17 | checkmark: '#050608',
18 | checkmarkDisabled: '#477b5e',
19 | desktopBackground: '#213f21',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#3d9961',
24 | headerNotActiveBackground: '#807f80',
25 | headerNotActiveText: '#d4deda',
26 | headerText: '#fcfff6',
27 | hoverBackground: '#3d9961',
28 | material: '#99c9a8',
29 | materialDark: '#9a9e9c',
30 | materialText: '#050608',
31 | materialTextDisabled: '#3d5367',
32 | materialTextDisabledShadow: '#cdead2',
33 | materialTextInvert: '#fcfff6',
34 | progress: '#3d9961',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/stormClouds.ts:
--------------------------------------------------------------------------------
1 | /* "Storm Clouds" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Storm-Clouds-613198674
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'stormClouds',
9 | anchor: 'rgb(64, 64, 255)',
10 | anchorVisited: 'rgb(64, 64, 255)',
11 | borderDark: 'rgb(47, 52, 53)',
12 | borderDarkest: 'rgb(0, 0, 0)',
13 | borderLight: 'rgb(70, 80, 81)',
14 | borderLightest: 'rgb(159, 171, 172)',
15 | canvas: 'rgb(47, 52, 53)',
16 | canvasText: 'rgb(255, 255, 255)',
17 | canvasTextDisabled: 'rgb(47, 52, 53)',
18 | canvasTextDisabledShadow: 'rgb(159, 171, 172)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(255, 255, 255)',
21 | checkmarkDisabled: 'rgb(128, 128, 128)',
22 | desktopBackground: 'rgb(45, 87, 87)',
23 | flatDark: 'rgb(47, 52, 53)',
24 | flatLight: 'rgb(70, 80, 81)',
25 | focusSecondary: 'rgb(159, 171, 172)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(0, 0, 168), rgb(16, 132, 208))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(47, 52, 53), rgb(128, 128, 128))',
30 | headerNotActiveText: 'rgb(192, 199, 200)',
31 | headerText: 'rgb(255, 255, 255)',
32 | hoverBackground: 'rgb(128, 128, 0)',
33 | material: 'rgb(70, 80, 81)',
34 | materialDark: 'rgb(47, 52, 53)',
35 | materialText: 'rgb(255, 255, 255)',
36 | materialTextDisabled: 'rgb(47, 52, 53)',
37 | materialTextDisabledShadow: 'rgb(159, 171, 172)',
38 | materialTextInvert: 'rgb(255, 255, 255)',
39 | progress: 'rgb(128, 128, 0)',
40 | tooltip: 'rgb(48, 64, 80)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/theSixtiesUSA.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'theSixtiesUSA',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#6c1f71',
9 | borderDarkest: '#010001',
10 | borderLight: '#d982de',
11 | borderLightest: '#df9be7',
12 | canvas: '#ffffff',
13 | canvasText: '#010001',
14 | canvasTextDisabled: '#6c1f71',
15 | canvasTextDisabledShadow: '#df9be7',
16 | canvasTextInvert: '#010001',
17 | checkmark: '#010001',
18 | checkmarkDisabled: '#6c1f71',
19 | desktopBackground: '#92458a', // original: #000000
20 | flatDark: '#d067d7',
21 | flatLight: '#df9be7',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#050080',
24 | headerNotActiveBackground: '#a130a9',
25 | headerNotActiveText: '#df9be7',
26 | headerText: '#ffffff',
27 | hoverBackground: '#0f0',
28 | material: '#d067d7',
29 | materialDark: '#9a9e9c',
30 | materialText: '#010001',
31 | materialTextDisabled: '#6c1f71',
32 | materialTextDisabledShadow: '#df9be7',
33 | materialTextInvert: '#010001',
34 | progress: '#0f0',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/tokyoDark.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'tokyoDark',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#1f2223',
9 | borderDarkest: '#070809',
10 | borderLight: '#5e696a',
11 | borderLightest: '#93a0a1',
12 | canvas: '#2f3435',
13 | canvasText: '#F4F4ED',
14 | canvasTextDisabled: '#1f2223',
15 | canvasTextDisabledShadow: '#93a0a1',
16 | canvasTextInvert: '#ffffff',
17 | checkmark: '#F4F4ED',
18 | checkmarkDisabled: '#1f2223',
19 | desktopBackground: '#181a1b',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#20FC8F',
23 | headerBackground: '#1f2223',
24 | headerNotActiveBackground: '#5e696a',
25 | headerNotActiveText: '#F4F4ED',
26 | headerText: '#F4F4ED',
27 | hoverBackground: '#F61067',
28 | material: '#465051',
29 | materialDark: '#1f2223',
30 | materialText: '#F4F4ED',
31 | materialTextDisabled: '#1f2223',
32 | materialTextDisabledShadow: '#93a0a1',
33 | materialTextInvert: '#ffffff',
34 | progress: '#F61067',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/toner.ts:
--------------------------------------------------------------------------------
1 | /* "Toner" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Toner-871968986
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'toner',
9 | anchor: 'rgb(0, 0, 128)',
10 | anchorVisited: 'rgb(0, 0, 128)',
11 | borderDark: 'rgb(0, 0, 0)',
12 | borderDarkest: 'rgb(128, 128, 128)',
13 | borderLight: 'rgb(0, 0, 0)',
14 | borderLightest: 'rgb(127, 127, 127)',
15 | canvas: 'rgb(128, 128, 128)',
16 | canvasText: 'rgb(255, 255, 255)',
17 | canvasTextDisabled: 'rgb(0, 0, 0)',
18 | canvasTextDisabledShadow: 'rgb(127, 127, 127)',
19 | canvasTextInvert: 'rgb(0, 0, 0)',
20 | checkmark: 'rgb(255, 255, 255)',
21 | checkmarkDisabled: 'rgb(64, 64, 64)',
22 | desktopBackground: 'rgb(128, 128, 128)',
23 | flatDark: 'rgb(0, 0, 0)',
24 | flatLight: 'rgb(0, 0, 0)',
25 | focusSecondary: 'rgb(127, 127, 127)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(128, 128, 128), rgb(128, 128, 128))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(0, 0, 0), rgb(128, 128, 128))',
30 | headerNotActiveText: 'rgb(128, 128, 128)',
31 | headerText: 'rgb(0, 0, 0)',
32 | hoverBackground: 'rgb(255, 255, 255)',
33 | material: 'rgb(0, 0, 0)',
34 | materialDark: 'rgb(0, 0, 0)',
35 | materialText: 'rgb(255, 255, 255)',
36 | materialTextDisabled: 'rgb(0, 0, 0)',
37 | materialTextDisabledShadow: 'rgb(127, 127, 127)',
38 | materialTextInvert: 'rgb(0, 0, 0)',
39 | progress: 'rgb(255, 255, 255)',
40 | tooltip: 'rgb(128, 128, 128)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/tooSexy.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'tooSexy',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#5a0302',
9 | borderDarkest: '#000000',
10 | borderLight: '#c81d19',
11 | borderLightest: '#fe5757',
12 | canvas: '#FFF1D0',
13 | canvasText: '#000000',
14 | canvasTextDisabled: '#5a0302',
15 | canvasTextDisabledShadow: '#FFF1D0',
16 | canvasTextInvert: '#ffffff',
17 | checkmark: '#000000',
18 | checkmarkDisabled: '#5a0302',
19 | desktopBackground: '#000000',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#161B33',
24 | headerNotActiveBackground: '#5a0302',
25 | headerNotActiveText: '#B80100',
26 | headerText: '#FFF1D0',
27 | hoverBackground: '#474973',
28 | material: '#B80100',
29 | materialDark: '#9a9e9c',
30 | materialText: '#000000',
31 | materialTextDisabled: '#5a0302',
32 | materialTextDisabledShadow: '#fe5757',
33 | materialTextInvert: '#ffffff',
34 | progress: '#474973',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/travel.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'travel',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#695f50',
9 | borderDarkest: '#28251e',
10 | borderLight: '#9d8f80',
11 | borderLightest: '#baae9f',
12 | canvas: '#d8d0c8',
13 | canvasText: '#28251e',
14 | canvasTextDisabled: '#695f50',
15 | canvasTextDisabledShadow: '#baae9f',
16 | canvasTextInvert: '#ffffff',
17 | checkmark: '#28251e',
18 | checkmarkDisabled: '#695f50',
19 | desktopBackground: '#7c654c', // original: #000000
20 | flatDark: '#695f50',
21 | flatLight: '#9d8f80',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#404878',
24 | headerNotActiveBackground: '#605848',
25 | headerNotActiveText: '#908070',
26 | headerText: '#d8d0c8',
27 | hoverBackground: '#48604f',
28 | material: '#908070',
29 | materialDark: '#9a9e9c',
30 | materialText: '#28251e',
31 | materialTextDisabled: '#695f50',
32 | materialTextDisabledShadow: '#baae9f',
33 | materialTextInvert: '#ffffff',
34 | progress: '#48604f',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/types.ts:
--------------------------------------------------------------------------------
1 | export type Color = string;
2 |
3 | export type Theme = {
4 | name: string;
5 | anchor: Color;
6 | anchorVisited: Color;
7 | borderDark: Color;
8 | borderDarkest: Color;
9 | borderLight: Color;
10 | borderLightest: Color;
11 | canvas: Color;
12 | canvasText: Color;
13 | canvasTextDisabled: Color;
14 | canvasTextDisabledShadow: Color;
15 | canvasTextInvert: Color;
16 | checkmark: Color;
17 | checkmarkDisabled: Color;
18 | desktopBackground: Color;
19 | flatDark: Color;
20 | flatLight: Color;
21 | focusSecondary: Color;
22 | headerBackground: Color;
23 | headerNotActiveBackground: Color;
24 | headerNotActiveText: Color;
25 | headerText: Color;
26 | hoverBackground: Color;
27 | material: Color;
28 | materialDark: Color;
29 | materialText: Color;
30 | materialTextDisabled: Color;
31 | materialTextDisabledShadow: Color;
32 | materialTextInvert: Color;
33 | progress: Color;
34 | tooltip: Color;
35 | };
36 |
37 | export type WindowsTheme = {
38 | ActiveBorder: Color;
39 | ActiveTitle: Color;
40 | AppWorkspace: Color;
41 | Background: Color;
42 | ButtonAlternateFace: Color;
43 | ButtonDkShadow: Color;
44 | ButtonFace: Color;
45 | ButtonHilight: Color;
46 | ButtonLight: Color;
47 | ButtonShadow: Color;
48 | ButtonText: Color;
49 | GradientActiveTitle: Color;
50 | GradientInactiveTitle: Color;
51 | GrayText: Color;
52 | Hilight: Color;
53 | HilightText: Color;
54 | HotTrackingColor: Color;
55 | InactiveBorder: Color;
56 | InactiveTitle: Color;
57 | InactiveTitleText: Color;
58 | InfoText: Color;
59 | InfoWindow: Color;
60 | Menu: Color;
61 | MenuBar: Color;
62 | MenuHilight: Color;
63 | MenuText: Color;
64 | Scrollbar: Color;
65 | TitleText: Color;
66 | Window: Color;
67 | WindowFrame: Color;
68 | WindowText: Color;
69 | };
70 |
--------------------------------------------------------------------------------
/src/common/themes/vaporTeal.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'vaporTeal',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#00706f',
9 | borderDarkest: '#000000',
10 | borderLight: '#2fcecd',
11 | borderLightest: '#58ffff',
12 | canvas: '#98DFEA',
13 | canvasText: '#000000',
14 | canvasTextDisabled: '#00706f',
15 | canvasTextDisabledShadow: '#58ffff',
16 | canvasTextInvert: '#000000',
17 | checkmark: '#000000',
18 | checkmarkDisabled: '#00706f',
19 | desktopBackground: '#008080',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#FCF6BD',
23 | headerBackground: '#246A73',
24 | headerNotActiveBackground: '#2fcecd',
25 | headerNotActiveText: '#246A73',
26 | headerText: '#58ffff',
27 | hoverBackground: '#FF99C8',
28 | material: '#01a8a8',
29 | materialDark: '#246A73',
30 | materialText: '#000000',
31 | materialTextDisabled: '#00706f',
32 | materialTextDisabledShadow: '#58ffff',
33 | materialTextInvert: '#000000',
34 | progress: '#FF99C8',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/vermillion.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'vermillion',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#7f2120',
9 | borderDarkest: '#130405',
10 | borderLight: '#d25051',
11 | borderLightest: '#e59697',
12 | canvas: '#EFE9F4',
13 | canvasText: '#130405',
14 | canvasTextDisabled: '#7f2120',
15 | canvasTextDisabledShadow: '#e59697',
16 | canvasTextInvert: '#EFE9F4',
17 | checkmark: '#130405',
18 | checkmarkDisabled: '#7f2120',
19 | desktopBackground: '#b22930',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#000103',
24 | headerNotActiveBackground: '#7f2120',
25 | headerNotActiveText: '#EFE9F4',
26 | headerText: '#EFE9F4',
27 | hoverBackground: '#000103',
28 | material: '#cf4545',
29 | materialDark: '#7f2120',
30 | materialText: '#130405',
31 | materialTextDisabled: '#7f2120',
32 | materialTextDisabledShadow: '#e59697',
33 | materialTextInvert: '#EFE9F4',
34 | progress: '#000103',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/violetDark.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'violetDark',
5 |
6 | anchor: '#1034a6',
7 | anchorVisited: '#440381',
8 | borderDark: '#3c1f3e',
9 | borderDarkest: '#18051a',
10 | borderLight: '#945b9b',
11 | borderLightest: '#c47bcc',
12 | canvas: '#c47bcc',
13 | canvasText: '#18051a',
14 | canvasTextDisabled: '#000000',
15 | canvasTextDisabledShadow: '#000000',
16 | canvasTextInvert: '#c57ece',
17 | checkmark: '#000000',
18 | checkmarkDisabled: '#3c1f3e',
19 | desktopBackground: '#3b1940',
20 | flatDark: '#3c1f3e',
21 | flatLight: '#945b9b',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#1034a6',
24 | headerNotActiveBackground: '#210e23',
25 | headerNotActiveText: '#652a6d',
26 | headerText: '#010601',
27 | hoverBackground: '#512155',
28 | material: '#652a6d',
29 | materialDark: '#210e23',
30 | materialText: '#c57ece',
31 | materialTextDisabled: '#3c1f3e',
32 | materialTextDisabledShadow: '#c47bcc',
33 | materialTextInvert: '#c47bcc',
34 | progress: '#000080',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/vistaesqueMidnight.ts:
--------------------------------------------------------------------------------
1 | /* "Vista-esque Midnight" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Vista-esque-Midnight-557498234
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'vistaesqueMidnight',
9 | anchor: 'rgb(64, 64, 192)',
10 | anchorVisited: 'rgb(64, 64, 192)',
11 | borderDark: 'rgb(21, 21, 21)',
12 | borderDarkest: 'rgb(0, 0, 0)',
13 | borderLight: 'rgb(32, 32, 32)',
14 | borderLightest: 'rgb(128, 128, 128)',
15 | canvas: 'rgb(0, 0, 0)',
16 | canvasText: 'rgb(255, 255, 255)',
17 | canvasTextDisabled: 'rgb(21, 21, 21)',
18 | canvasTextDisabledShadow: 'rgb(128, 128, 128)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(255, 255, 255)',
21 | checkmarkDisabled: 'rgb(32, 32, 32)',
22 | desktopBackground: 'rgb(31, 60, 89)',
23 | flatDark: 'rgb(21, 21, 21)',
24 | flatLight: 'rgb(32, 32, 32)',
25 | focusSecondary: 'rgb(128, 128, 128)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(81, 132, 188), rgb(100, 168, 60))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(22, 46, 101), rgb(18, 91, 30))',
30 | headerNotActiveText: 'rgb(192, 192, 192)',
31 | headerText: 'rgb(255, 255, 255)',
32 | hoverBackground: 'rgb(49, 106, 197)',
33 | material: 'rgb(32, 32, 32)',
34 | materialDark: 'rgb(22, 46, 101)',
35 | materialText: 'rgb(255, 255, 255)',
36 | materialTextDisabled: 'rgb(21, 21, 21)',
37 | materialTextDisabledShadow: 'rgb(128, 128, 128)',
38 | materialTextInvert: 'rgb(255, 255, 255)',
39 | progress: 'rgb(49, 106, 197)',
40 | tooltip: 'rgb(0, 0, 30)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/themes/water.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from './types';
2 |
3 | export default {
4 | name: 'water',
5 |
6 | anchor: '#72b3b4',
7 | anchorVisited: '#440381',
8 | borderDark: '#888c8f',
9 | borderDarkest: '#050608',
10 | borderLight: '#dfe0e3',
11 | borderLightest: '#ffffff',
12 | canvas: '#ffffff',
13 | canvasText: '#050608',
14 | canvasTextDisabled: '#888c8f',
15 | canvasTextDisabledShadow: '#ffffff',
16 | canvasTextInvert: '#ffffff',
17 | checkmark: '#050608',
18 | checkmarkDisabled: '#888c8f',
19 | desktopBackground: '#3a6ea5',
20 | flatDark: '#9e9e9e',
21 | flatLight: '#d8d8d8',
22 | focusSecondary: '#fefe03',
23 | headerBackground: '#72b3b4',
24 | headerNotActiveBackground: '#9a9e9c',
25 | headerNotActiveText: '#ced0cf',
26 | headerText: '#ffffff',
27 | hoverBackground: '#72b3b4',
28 | material: '#ced0cf',
29 | materialDark: '#9a9e9c',
30 | materialText: '#050608',
31 | materialTextDisabled: '#888c8f',
32 | materialTextDisabledShadow: '#ffffff',
33 | materialTextInvert: '#ffffff',
34 | progress: '#72b3b4',
35 | tooltip: '#fefbcc'
36 | } as Theme;
37 |
--------------------------------------------------------------------------------
/src/common/themes/white.ts:
--------------------------------------------------------------------------------
1 | /* "White" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/White-870495714
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'white',
9 | anchor: 'rgb(0, 0, 128)',
10 | anchorVisited: 'rgb(0, 0, 128)',
11 | borderDark: 'rgb(0, 0, 0)',
12 | borderDarkest: 'rgb(255, 255, 255)',
13 | borderLight: 'rgb(0, 0, 0)',
14 | borderLightest: 'rgb(255, 255, 255)',
15 | canvas: 'rgb(255, 255, 255)',
16 | canvasText: 'rgb(0, 0, 0)',
17 | canvasTextDisabled: 'rgb(0, 0, 0)',
18 | canvasTextDisabledShadow: 'rgb(255, 255, 255)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(0, 0, 0)',
21 | checkmarkDisabled: 'rgb(128, 128, 128)',
22 | desktopBackground: 'rgb(0, 128, 128)',
23 | flatDark: 'rgb(0, 0, 0)',
24 | flatLight: 'rgb(0, 0, 0)',
25 | focusSecondary: 'rgb(255, 255, 255)',
26 | headerBackground: 'linear-gradient(to right, rgb(0, 0, 128), rgb(0, 0, 128))',
27 | headerNotActiveBackground:
28 | 'linear-gradient(to right, rgb(128, 128, 128), rgb(128, 128, 128))',
29 | headerNotActiveText: 'rgb(192, 192, 192)',
30 | headerText: 'rgb(255, 255, 255)',
31 | hoverBackground: 'rgb(0, 0, 128)',
32 | material: 'rgb(255, 255, 255)',
33 | materialDark: 'rgb(128, 128, 128)',
34 | materialText: 'rgb(0, 0, 0)',
35 | materialTextDisabled: 'rgb(0, 0, 0)',
36 | materialTextDisabledShadow: 'rgb(255, 255, 255)',
37 | materialTextInvert: 'rgb(255, 255, 255)',
38 | progress: 'rgb(0, 0, 128)',
39 | tooltip: 'rgb(255, 255, 128)'
40 | } as Theme;
41 |
--------------------------------------------------------------------------------
/src/common/themes/windows1.ts:
--------------------------------------------------------------------------------
1 | /* "Windows 1" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/Windows-1-573195578
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'windows1',
9 | anchor: 'rgb(0, 0, 85)',
10 | anchorVisited: 'rgb(0, 0, 85)',
11 | borderDark: 'rgb(0, 0, 0)',
12 | borderDarkest: 'rgb(255, 255, 255)',
13 | borderLight: 'rgb(0, 0, 0)',
14 | borderLightest: 'rgb(255, 255, 255)',
15 | canvas: 'rgb(255, 255, 255)',
16 | canvasText: 'rgb(0, 0, 0)',
17 | canvasTextDisabled: 'rgb(0, 0, 0)',
18 | canvasTextDisabledShadow: 'rgb(255, 255, 255)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(0, 0, 0)',
21 | checkmarkDisabled: 'rgb(85, 85, 85)',
22 | desktopBackground: 'rgb(85, 254, 120)',
23 | flatDark: 'rgb(0, 0, 0)',
24 | flatLight: 'rgb(0, 0, 0)',
25 | focusSecondary: 'rgb(255, 255, 255)',
26 | headerBackground: 'linear-gradient(to right, rgb(0, 0, 0), rgb(85, 85, 255))',
27 | headerNotActiveBackground:
28 | 'linear-gradient(to right, rgb(0, 0, 0), rgb(109, 109, 199))',
29 | headerNotActiveText: 'rgb(255, 255, 255)',
30 | headerText: 'rgb(255, 255, 255)',
31 | hoverBackground: 'rgb(0, 0, 0)',
32 | material: 'rgb(255, 255, 255)',
33 | materialDark: 'rgb(0, 0, 0)',
34 | materialText: 'rgb(0, 0, 0)',
35 | materialTextDisabled: 'rgb(0, 0, 0)',
36 | materialTextDisabledShadow: 'rgb(255, 255, 255)',
37 | materialTextInvert: 'rgb(255, 255, 255)',
38 | progress: 'rgb(0, 0, 0)',
39 | tooltip: 'rgb(255, 255, 85)'
40 | } as Theme;
41 |
--------------------------------------------------------------------------------
/src/common/themes/wmii.ts:
--------------------------------------------------------------------------------
1 | /* "WMII" by tPenguinLTG
2 | * https://www.deviantart.com/tpenguinltg/art/wmii-683233676
3 | */
4 |
5 | import { Theme } from './types';
6 |
7 | export default {
8 | name: 'wmii',
9 | anchor: 'rgb(129, 101, 79)',
10 | anchorVisited: 'rgb(129, 101, 79)',
11 | borderDark: 'rgb(145, 148, 75)',
12 | borderDarkest: 'rgb(64, 64, 64)',
13 | borderLight: 'rgb(193, 196, 139)',
14 | borderLightest: 'rgb(224, 225, 198)',
15 | canvas: 'rgb(255, 255, 255)',
16 | canvasText: 'rgb(0, 0, 0)',
17 | canvasTextDisabled: 'rgb(145, 148, 75)',
18 | canvasTextDisabledShadow: 'rgb(224, 225, 198)',
19 | canvasTextInvert: 'rgb(255, 255, 255)',
20 | checkmark: 'rgb(0, 0, 0)',
21 | checkmarkDisabled: 'rgb(145, 148, 75)',
22 | desktopBackground: 'rgb(51, 51, 51)',
23 | flatDark: 'rgb(145, 148, 75)',
24 | flatLight: 'rgb(193, 196, 139)',
25 | focusSecondary: 'rgb(224, 225, 198)',
26 | headerBackground:
27 | 'linear-gradient(to right, rgb(129, 101, 79), rgb(129, 101, 79))',
28 | headerNotActiveBackground:
29 | 'linear-gradient(to right, rgb(145, 148, 75), rgb(145, 148, 75))',
30 | headerNotActiveText: 'rgb(193, 196, 139)',
31 | headerText: 'rgb(255, 255, 255)',
32 | hoverBackground: 'rgb(0, 0, 0)',
33 | material: 'rgb(193, 196, 139)',
34 | materialDark: 'rgb(145, 148, 75)',
35 | materialText: 'rgb(0, 0, 0)',
36 | materialTextDisabled: 'rgb(145, 148, 75)',
37 | materialTextDisabledShadow: 'rgb(224, 225, 198)',
38 | materialTextInvert: 'rgb(255, 255, 255)',
39 | progress: 'rgb(0, 0, 0)',
40 | tooltip: 'rgb(255, 255, 225)'
41 | } as Theme;
42 |
--------------------------------------------------------------------------------
/src/common/utils/events.ts:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export const focusEventTypes = ['blur', 'focus'];
4 |
5 | export const keyboardEventTypes = ['keydown', 'keypress', 'keyup'];
6 |
7 | export const mouseEventTypes = [
8 | 'click',
9 | 'contextmenu',
10 | 'doubleclick',
11 | 'drag',
12 | 'dragend',
13 | 'dragenter',
14 | 'dragexit',
15 | 'dragleave',
16 | 'dragover',
17 | 'dragstart',
18 | 'drop',
19 | 'mousedown',
20 | 'mouseenter',
21 | 'mouseleave',
22 | 'mousemove',
23 | 'mouseout',
24 | 'mouseover',
25 | 'mouseup'
26 | ];
27 |
28 | export function isReactFocusEvent(
29 | event: React.SyntheticEvent | Event
30 | ): event is React.FocusEvent {
31 | return 'nativeEvent' in event && focusEventTypes.includes(event.type);
32 | }
33 |
34 | export function isReactKeyboardEvent(
35 | event: React.SyntheticEvent | Event
36 | ): event is React.KeyboardEvent {
37 | return 'nativeEvent' in event && keyboardEventTypes.includes(event.type);
38 | }
39 |
40 | export function isReactMouseEvent(
41 | event: React.SyntheticEvent | Event
42 | ): event is React.MouseEvent {
43 | return 'nativeEvent' in event && mouseEventTypes.includes(event.type);
44 | }
45 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | /* common */
2 | export { default as styleReset } from './common/styleReset';
3 | export { createScrollbars } from './common/index';
4 |
5 | /* components */
6 | export * from './Anchor/Anchor';
7 | export * from './AppBar/AppBar';
8 | export * from './Avatar/Avatar';
9 | export * from './Button/Button';
10 | export * from './Checkbox/Checkbox';
11 | export * from './ColorInput/ColorInput';
12 | export * from './Counter/Counter';
13 | export * from './DatePicker/DatePicker';
14 | export * from './Frame/Frame';
15 | export * from './GroupBox/GroupBox';
16 | export * from './Handle/Handle';
17 | export * from './Hourglass/Hourglass';
18 | export * from './MenuList/MenuList';
19 | export * from './Monitor/Monitor';
20 | export * from './NumberInput/NumberInput';
21 | export * from './ProgressBar/ProgressBar';
22 | export * from './Radio/Radio';
23 | export * from './ScrollView/ScrollView';
24 | export * from './Select/Select';
25 | export * from './Separator/Separator';
26 | export * from './Slider/Slider';
27 | export * from './Table/Table';
28 | export * from './Tabs/Tabs';
29 | export * from './TextInput/TextInput';
30 | export * from './Toolbar/Toolbar';
31 | export * from './Tooltip/Tooltip';
32 | export * from './TreeView/TreeView';
33 | export * from './Window/Window';
34 |
35 | /* deprecated components */
36 | export * from './legacy/Bar';
37 | export * from './legacy/Cutout';
38 | export * from './legacy/Desktop';
39 | export * from './legacy/Divider';
40 | export * from './legacy/Fieldset';
41 | export * from './legacy/List';
42 | export * from './legacy/ListItem';
43 | export * from './legacy/NumberField';
44 | export * from './legacy/Panel';
45 | export * from './legacy/Progress';
46 | export * from './legacy/TextField';
47 | export * from './legacy/Tree';
48 |
--------------------------------------------------------------------------------
/src/legacy/Bar.tsx:
--------------------------------------------------------------------------------
1 | import { Handle, HandleProps } from '../Handle/Handle';
2 |
3 | /** @deprecated Use `HandleProps` */
4 | export type BarProps = HandleProps;
5 |
6 | /** @deprecated Use `Handle` */
7 | export const Bar = Handle;
8 |
--------------------------------------------------------------------------------
/src/legacy/Cutout.tsx:
--------------------------------------------------------------------------------
1 | import { ScrollView, ScrollViewProps } from '../ScrollView/ScrollView';
2 |
3 | /** @deprecated Use `ScrollViewProps` */
4 | export type CutoutProps = ScrollViewProps;
5 |
6 | /** @deprecated Use `ScrollView` */
7 | export const Cutout = ScrollView;
8 |
--------------------------------------------------------------------------------
/src/legacy/Desktop.tsx:
--------------------------------------------------------------------------------
1 | import { Monitor, MonitorProps } from '../Monitor/Monitor';
2 |
3 | /** @deprecated Use `MonitorProps` */
4 | export type DesktopProps = MonitorProps;
5 |
6 | /** @deprecated Use `Monitor` */
7 | export const Desktop = Monitor;
8 |
--------------------------------------------------------------------------------
/src/legacy/Divider.tsx:
--------------------------------------------------------------------------------
1 | import { Separator, SeparatorProps } from '../Separator/Separator';
2 |
3 | /** @deprecated Use `SeparatorProps` */
4 | export type DividerProps = SeparatorProps;
5 |
6 | /** @deprecated Use `Separator` */
7 | export const Divider = Separator;
8 |
--------------------------------------------------------------------------------
/src/legacy/Fieldset.tsx:
--------------------------------------------------------------------------------
1 | import { GroupBox, GroupBoxProps } from '../GroupBox/GroupBox';
2 |
3 | /** @deprecated Use `GroupBoxProps` */
4 | export type FieldsetProps = GroupBoxProps;
5 |
6 | /** @deprecated Use `GroupBox` */
7 | export const Fieldset = GroupBox;
8 |
--------------------------------------------------------------------------------
/src/legacy/List.tsx:
--------------------------------------------------------------------------------
1 | import { MenuList, MenuListProps } from '../MenuList/MenuList';
2 |
3 | /** @deprecated Use `MenuListProps` */
4 | export type ListProps = MenuListProps;
5 |
6 | /** @deprecated Use `MenuList` */
7 | export const List = MenuList;
8 |
--------------------------------------------------------------------------------
/src/legacy/ListItem.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | MenuListItem,
3 | MenuListItemProps,
4 | StyledMenuListItem
5 | } from '../MenuList/MenuList';
6 |
7 | /** @deprecated Use `MenuListItemProps` */
8 | export type ListItemProps = MenuListItemProps;
9 |
10 | /** @deprecated Use `MenuListItem` */
11 | export const ListItem = MenuListItem;
12 |
13 | /** @deprecated Use `StyledMenuListItem` */
14 | export const StyledListItem = StyledMenuListItem;
15 |
--------------------------------------------------------------------------------
/src/legacy/NumberField.tsx:
--------------------------------------------------------------------------------
1 | import { NumberInput, NumberInputProps } from '../NumberInput/NumberInput';
2 |
3 | /** @deprecated Use `NumberInputProps` */
4 | export type NumberFieldProps = NumberInputProps;
5 |
6 | /** @deprecated Use `NumberInput` */
7 | export const NumberField = NumberInput;
8 |
--------------------------------------------------------------------------------
/src/legacy/Panel.tsx:
--------------------------------------------------------------------------------
1 | import { Frame, FrameProps } from '../Frame/Frame';
2 |
3 | /** @deprecated Use `FrameProps` */
4 | export type PanelProps = FrameProps;
5 |
6 | /** @deprecated Use `Frame` */
7 | export const Panel = Frame;
8 |
--------------------------------------------------------------------------------
/src/legacy/Progress.tsx:
--------------------------------------------------------------------------------
1 | import { ProgressBar, ProgressBarProps } from '../ProgressBar/ProgressBar';
2 |
3 | /** @deprecated Use `ProgressBarProps` */
4 | export type ProgressProps = ProgressBarProps;
5 |
6 | /** @deprecated Use `ProgressBar` */
7 | export const Progress = ProgressBar;
8 |
--------------------------------------------------------------------------------
/src/legacy/TextField.tsx:
--------------------------------------------------------------------------------
1 | import { TextInput, TextInputProps } from '../TextInput/TextInput';
2 |
3 | /** @deprecated Use `TextInputProps` */
4 | export type TextFieldProps = TextInputProps;
5 |
6 | /** @deprecated Use `TextInput` */
7 | export const TextField = TextInput;
8 |
--------------------------------------------------------------------------------
/src/legacy/Tree.tsx:
--------------------------------------------------------------------------------
1 | import { TreeView, TreeViewProps } from '../TreeView/TreeView';
2 |
3 | /** @deprecated Use `TreeViewProps` */
4 | export type TreeProps = TreeViewProps;
5 |
6 | /** @deprecated Use `TreeView` */
7 | export const Tree = TreeView;
8 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | import { ComponentType } from 'react';
2 |
3 | import { Color, Theme, WindowsTheme } from './common/themes/types';
4 |
5 | export type Sizes = 'sm' | 'md' | 'lg';
6 |
7 | export type Orientation = 'horizontal' | 'vertical';
8 |
9 | export type Direction = 'up' | 'down' | 'left' | 'right';
10 |
11 | export type DimensionValue = undefined | number | string;
12 |
13 | export type CommonStyledProps = {
14 | /**
15 | * "as" polymorphic prop allows to render a different HTML element or React component
16 | * @see {@link https://styled-components.com/docs/api#as-polymorphic-prop}
17 | */
18 | as?: string | ComponentType; // eslint-disable-line @typescript-eslint/no-explicit-any
19 | };
20 |
21 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
22 | export type HTMLDataAttributes = Record<`data-${string}`, any>;
23 |
24 | export type CommonThemeProps = {
25 | 'data-testid'?: string;
26 | $disabled?: boolean;
27 | shadow?: boolean;
28 | };
29 |
30 | export { Color, Theme, WindowsTheme };
31 |
--------------------------------------------------------------------------------
/test/setup-test.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom';
2 | import 'jest-styled-components';
3 |
--------------------------------------------------------------------------------
/test/utils.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react';
2 | import React from 'react';
3 | import { ThemeProvider } from 'styled-components';
4 |
5 | import themes from '../src/common/themes';
6 |
7 | export const theme = themes.original;
8 |
9 | export const renderWithTheme = (component: React.ReactNode) =>
10 | render({component} );
11 |
12 | export class Touch {
13 | #identifier: number;
14 |
15 | #clientX = 0;
16 |
17 | #clientY = 0;
18 |
19 | #pageX = 0;
20 |
21 | #pageY = 0;
22 |
23 | constructor({
24 | identifier,
25 | clientX = 0,
26 | clientY = 0,
27 | pageX = 0,
28 | pageY = 0
29 | }: {
30 | identifier: number;
31 | clientX?: number;
32 | clientY?: number;
33 | pageX?: number;
34 | pageY?: number;
35 | }) {
36 | this.#identifier = identifier;
37 | this.#clientX = clientX;
38 | this.#clientY = clientY;
39 | this.#pageX = pageX;
40 | this.#pageY = pageY;
41 | }
42 |
43 | get identifier() {
44 | return this.#identifier;
45 | }
46 |
47 | get pageX() {
48 | return this.#pageX;
49 | }
50 |
51 | get pageY() {
52 | return this.#pageY;
53 | }
54 |
55 | get clientX() {
56 | return this.#clientX;
57 | }
58 |
59 | get clientY() {
60 | return this.#clientY;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/tsconfig.build.index.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "emitDeclarationOnly": true,
5 | "outDir": "./dist",
6 | "rootDir": "./src",
7 | "sourceMap": false
8 | },
9 | "include": [
10 | "types/global.d.ts",
11 | "types/themes.d.ts",
12 | "src/**/*.ts",
13 | "src/*/*.tsx"
14 | ],
15 | "exclude": [
16 | "**/*.spec.ts",
17 | "**/*.spec.tsx",
18 | "**/*.stories.ts",
19 | "**/*.stories.tsx",
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/tsconfig.build.themes.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "emitDeclarationOnly": true,
5 | "outDir": "./dist/themes",
6 | "rootDir": "./src/common/themes",
7 | "sourceMap": false
8 | },
9 | "include": [
10 | "src/common/themes/*.ts",
11 | "src/common/themes/*.tsx"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowJs": true,
4 | "alwaysStrict": true,
5 | "declaration": true,
6 | "declarationMap": true,
7 | "esModuleInterop": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "importHelpers": true,
10 | "jsx": "react",
11 | "lib": [
12 | "ESNext",
13 | "DOM"
14 | ],
15 | "module": "Node16",
16 | "moduleResolution": "Node",
17 | "noEmitOnError": true,
18 | "noFallthroughCasesInSwitch": true,
19 | "noImplicitAny": true,
20 | "noImplicitReturns": true,
21 | "noImplicitThis": true,
22 | "noUnusedLocals": true,
23 | "noUnusedParameters": true,
24 | "outDir": "./lib",
25 | "paths": {
26 | "react95": [
27 | "./src"
28 | ]
29 | },
30 | "resolveJsonModule": true,
31 | "rootDir": "./",
32 | "skipLibCheck": true,
33 | "sourceMap": true,
34 | "strict": true,
35 | "strictFunctionTypes": true,
36 | "strictNullChecks": true,
37 | "strictPropertyInitialization": true,
38 | "target": "ES2018"
39 | },
40 | "include": [
41 | "**/*.ts",
42 | "**/*.tsx"
43 | ],
44 | "exclude": [
45 | "coverage",
46 | "dist",
47 | "node_modules",
48 | "storybook"
49 | ]
50 | }
51 |
--------------------------------------------------------------------------------
/types/globals.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.png' {
2 | const value: string;
3 | export = value;
4 | }
5 |
6 | declare module '*.woff2' {
7 | const value: string;
8 | export = value;
9 | }
10 |
--------------------------------------------------------------------------------
/types/themes.d.ts:
--------------------------------------------------------------------------------
1 | // import original module declarations
2 | import { Theme } from '../src/types';
3 | import 'styled-components';
4 |
5 | // and extend them!
6 | declare module 'styled-components' {
7 | export interface DefaultTheme extends Theme {}
8 | }
9 |
--------------------------------------------------------------------------------