@redocly/theme 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/LICENSE +1 -0
  2. package/lib/package.json +91 -0
  3. package/lib/src/Button/Button.tsx +122 -0
  4. package/lib/src/Button/index.ts +1 -0
  5. package/lib/src/CodeBlock/CodeBlock.ts +125 -0
  6. package/lib/src/CodeBlock/index.ts +1 -0
  7. package/lib/src/CopyButton/CopyButton.tsx +26 -0
  8. package/lib/src/CopyButton/CopyButtonWrapper.tsx +52 -0
  9. package/lib/src/CopyButton/index.ts +2 -0
  10. package/lib/src/Headings/Headings.ts +23 -0
  11. package/lib/src/Headings/index.ts +1 -0
  12. package/lib/src/JsonViewer/JsonViewer.tsx +130 -0
  13. package/lib/src/JsonViewer/index.ts +1 -0
  14. package/lib/src/JsonViewer/styled.ts +103 -0
  15. package/lib/src/Logo/Logo.tsx +23 -0
  16. package/lib/src/Navbar/Navbar.tsx +60 -0
  17. package/lib/src/Navbar/NavbarItem.tsx +90 -0
  18. package/lib/src/Navbar/NavbarMenu.tsx +29 -0
  19. package/lib/src/Panel/CodePanel.ts +31 -0
  20. package/lib/src/Panel/ContentPanel.ts +43 -0
  21. package/lib/src/Panel/DarkHeader.ts +8 -0
  22. package/lib/src/Panel/Panel.ts +18 -0
  23. package/lib/src/Panel/PanelBody.ts +30 -0
  24. package/lib/src/Panel/PanelComponent.tsx +73 -0
  25. package/lib/src/Panel/PanelHeader.ts +25 -0
  26. package/lib/src/Panel/PanelHeaderTitle.ts +11 -0
  27. package/lib/src/Panel/index.ts +7 -0
  28. package/lib/src/SamplesPanelControls/SamplesPanelControls.ts +70 -0
  29. package/lib/src/SamplesPanelControls/index.ts +1 -0
  30. package/lib/src/SidebarLogo/SidebarLogo.tsx +47 -0
  31. package/lib/src/SidebarLogo/index.ts +1 -0
  32. package/lib/src/SourceCode/SourceCode.tsx +67 -0
  33. package/lib/src/SourceCode/index.ts +1 -0
  34. package/lib/src/Tooltip/Tooltip.tsx +171 -0
  35. package/lib/src/Tooltip/index.ts +1 -0
  36. package/lib/src/globalStyle.ts +512 -0
  37. package/lib/src/hooks/index.ts +3 -0
  38. package/lib/src/hooks/useControl.ts +20 -0
  39. package/lib/src/hooks/useMount.ts +8 -0
  40. package/lib/src/hooks/useUnmount.ts +10 -0
  41. package/lib/src/icons/ShelfIcon/ShelfIcon.tsx +45 -0
  42. package/lib/src/icons/ShelfIcon/index.ts +2 -0
  43. package/lib/src/icons/index.ts +1 -0
  44. package/lib/src/index.ts +14 -0
  45. package/lib/src/mocks/Link.tsx +7 -0
  46. package/lib/src/mocks/utils.ts +3 -0
  47. package/lib/src/utils/ClipboardService.ts +92 -0
  48. package/lib/src/utils/css-variables.ts +2 -0
  49. package/lib/src/utils/highlight.ts +81 -0
  50. package/lib/src/utils/index.ts +6 -0
  51. package/lib/src/utils/jsonToHtml.ts +122 -0
  52. package/lib/src/utils/media-css.ts +16 -0
  53. package/lib/src/utils/theme-helpers.ts +34 -0
  54. package/package.json +91 -0
@@ -0,0 +1,8 @@
1
+ import { useEffect } from 'react';
2
+
3
+ export const useMount = (callback: () => void): void => {
4
+ useEffect(() => {
5
+ callback();
6
+ // eslint-disable-next-line react-hooks/exhaustive-deps
7
+ }, []);
8
+ };
@@ -0,0 +1,10 @@
1
+ import { useEffect } from 'react';
2
+
3
+ export const useUnmount = (callback: () => void): void => {
4
+ useEffect(() => {
5
+ return () => {
6
+ callback();
7
+ };
8
+ // eslint-disable-next-line react-hooks/exhaustive-deps
9
+ }, []);
10
+ };
@@ -0,0 +1,45 @@
1
+ import * as React from 'react';
2
+ import styled, { css } from 'styled-components';
3
+
4
+ import { getCssColorVariable } from '../../utils/css-variables';
5
+
6
+ const directionMap = {
7
+ right: '0deg',
8
+ down: '90deg',
9
+ left: '180deg',
10
+ up: '270deg',
11
+ };
12
+
13
+ export interface ShelfIconProps {
14
+ className?: string;
15
+ float?: 'left' | 'right';
16
+ size?: string;
17
+ color?: string;
18
+ direction: 'left' | 'right' | 'up' | 'down';
19
+ style?: React.CSSProperties;
20
+ }
21
+
22
+ const IntShelfIcon = ({ className, style }: ShelfIconProps): JSX.Element => (
23
+ <svg
24
+ className={className}
25
+ style={style}
26
+ viewBox="0 0 4.25 7"
27
+ xmlns="http://www.w3.org/2000/svg"
28
+ aria-hidden="true"
29
+ >
30
+ <path d="M0.205025 1.19467L3.00503 3.99467C3.27839 4.26804 3.72161 4.26804 3.99497 3.99467C4.26834 3.7213 4.26834 3.27809 3.99497 3.00472L1.19497 0.20472C0.921608 -0.0686469 0.478392 -0.0686469 0.205025 0.20472C-0.0683418 0.478087 -0.0683417 0.921303 0.205025 1.19467Z" />
31
+ <path d="M3.00503 3.00501L0.205025 5.80501C-0.0683417 6.07838 -0.0683417 6.5216 0.205025 6.79496C0.478392 7.06833 0.921608 7.06833 1.19497 6.79496L3.99497 3.99496C4.26834 3.7216 4.26834 3.27838 3.99497 3.00501C3.72161 2.73165 3.27839 2.73165 3.00503 3.00501Z" />
32
+ </svg>
33
+ );
34
+
35
+ export const ShelfIcon = styled(IntShelfIcon)`
36
+ ${({ size = '9px', float = '', direction, color }) => css`
37
+ height: ${size};
38
+ width: ${size};
39
+ float: ${float};
40
+ transform: rotateZ(${directionMap[direction]});
41
+ fill: ${getCssColorVariable(color)};
42
+ `}
43
+ vertical-align: middle;
44
+ transition: transform 0.2s ease-out;
45
+ `;
@@ -0,0 +1,2 @@
1
+ export { ShelfIcon } from './ShelfIcon';
2
+ export type { ShelfIconProps } from './ShelfIcon';
@@ -0,0 +1 @@
1
+ export * from './ShelfIcon';
@@ -0,0 +1,14 @@
1
+ export * from './Button';
2
+ export * from './CopyButton';
3
+ export * from './JsonViewer';
4
+ export * from './Headings';
5
+ export * from './SidebarLogo';
6
+ export * from './CodeBlock';
7
+ export * from './SamplesPanelControls';
8
+ export * from './Tooltip';
9
+ export * from './SourceCode';
10
+ export * from './Panel';
11
+ export * from './icons';
12
+ export * from './hooks';
13
+ export * from './utils';
14
+ export * from './globalStyle';
@@ -0,0 +1,7 @@
1
+ import * as React from 'react';
2
+
3
+ // TODO: use real typings here
4
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
5
+ export function Link(props: any): JSX.Element {
6
+ return <a href={props.to} {...props} />;
7
+ }
@@ -0,0 +1,3 @@
1
+ export function withPathPrefix(link: string): string {
2
+ return link;
3
+ }
@@ -0,0 +1,92 @@
1
+ export class ClipboardService {
2
+ static isSupported(): boolean {
3
+ return (
4
+ typeof document !== 'undefined' &&
5
+ !!document.queryCommandSupported &&
6
+ document.queryCommandSupported('copy')
7
+ );
8
+ }
9
+
10
+ static selectElement(element: HTMLDivElement | null): void {
11
+ if (!element) {
12
+ return;
13
+ }
14
+ let range;
15
+ let selection;
16
+ if ((document.body as any).createTextRange) {
17
+ range = (document.body as any).createTextRange();
18
+ range.moveToElementText(element);
19
+ range.select();
20
+ } else if (document.createRange && window.getSelection) {
21
+ selection = window.getSelection();
22
+ range = document.createRange();
23
+ range.selectNodeContents(element);
24
+ selection?.removeAllRanges();
25
+ selection?.addRange(range);
26
+ }
27
+ }
28
+
29
+ static deselect(): void {
30
+ if ((document as any).selection) {
31
+ (document as any).selection.empty();
32
+ } else if (window.getSelection) {
33
+ const selection = window.getSelection();
34
+ if (selection) {
35
+ selection.removeAllRanges();
36
+ }
37
+ }
38
+ }
39
+
40
+ static copySelected(): boolean {
41
+ let result;
42
+ try {
43
+ result = document.execCommand('copy');
44
+ } catch (err) {
45
+ result = false;
46
+ }
47
+ return result;
48
+ }
49
+
50
+ static copyElement(element: HTMLDivElement | null): boolean {
51
+ ClipboardService.selectElement(element);
52
+ const res = ClipboardService.copySelected();
53
+ if (res) {
54
+ ClipboardService.deselect();
55
+ }
56
+ return res;
57
+ }
58
+
59
+ static copyCustom(text: string): boolean {
60
+ const textArea = document.createElement('textarea');
61
+ textArea.style.position = 'fixed';
62
+ textArea.style.top = '0';
63
+ textArea.style.left = '0';
64
+
65
+ // Ensure it has a small width and height. Setting to 1px / 1em
66
+ // doesn't work as this gives a negative w/h on some browsers.
67
+ textArea.style.width = '2em';
68
+ textArea.style.height = '2em';
69
+
70
+ // We don't need padding, reducing the size if it does flash render.
71
+ textArea.style.padding = '0';
72
+
73
+ // Clean up any borders.
74
+ textArea.style.border = 'none';
75
+ textArea.style.outline = 'none';
76
+ textArea.style.boxShadow = 'none';
77
+
78
+ // Avoid flash of white box if rendered for any reason.
79
+ textArea.style.background = 'transparent';
80
+
81
+ textArea.value = text;
82
+
83
+ document.body.appendChild(textArea);
84
+
85
+ textArea.select();
86
+
87
+ const res = ClipboardService.copySelected();
88
+
89
+ document.body.removeChild(textArea);
90
+ return res;
91
+ }
92
+ }
@@ -0,0 +1,2 @@
1
+ export const getCssColorVariable = (color: string | undefined, defaultValue = 'inherit'): string =>
2
+ color?.startsWith('--') ? `var(${color})` : color || defaultValue;
@@ -0,0 +1,81 @@
1
+ import * as Prism from 'prismjs';
2
+ import 'prismjs/components/prism-bash.js';
3
+ import 'prismjs/components/prism-c.js';
4
+ import 'prismjs/components/prism-clike.js';
5
+ import 'prismjs/components/prism-coffeescript.js';
6
+ import 'prismjs/components/prism-cpp.js';
7
+ import 'prismjs/components/prism-csharp.js';
8
+ import 'prismjs/components/prism-go.js';
9
+ import 'prismjs/components/prism-http.js';
10
+ import 'prismjs/components/prism-java.js';
11
+ import 'prismjs/components/prism-lua.js';
12
+ import 'prismjs/components/prism-markup-templating.js'; // dep of php
13
+ import 'prismjs/components/prism-markup.js'; // xml
14
+ import 'prismjs/components/prism-objectivec.js';
15
+ import 'prismjs/components/prism-perl.js';
16
+ import 'prismjs/components/prism-php.js';
17
+ import 'prismjs/components/prism-python.js';
18
+ import 'prismjs/components/prism-ruby.js';
19
+ import 'prismjs/components/prism-scala.js';
20
+ import 'prismjs/components/prism-sql.js';
21
+ import 'prismjs/components/prism-swift.js';
22
+ import 'prismjs/components/prism-graphql.js';
23
+
24
+ const DEFAULT_LANG = 'clike';
25
+
26
+ Prism.languages.insertBefore(
27
+ 'javascript',
28
+ 'string',
29
+ {
30
+ 'property string': {
31
+ pattern: /([{,]\s*)"(?:\\.|[^\\"\r\n])*"(?=\s*:)/i,
32
+ lookbehind: true,
33
+ },
34
+ },
35
+ undefined,
36
+ );
37
+
38
+ Prism.languages.insertBefore(
39
+ 'javascript',
40
+ 'punctuation',
41
+ {
42
+ property: {
43
+ pattern: /([{,]\s*)[a-z]\w*(?=\s*:)/i,
44
+ lookbehind: true,
45
+ },
46
+ },
47
+ undefined,
48
+ );
49
+
50
+ /**
51
+ * map language names to Prism.js names
52
+ */
53
+ export function mapLang(lang: string): string {
54
+ return (
55
+ {
56
+ json: 'js',
57
+ 'c++': 'cpp',
58
+ 'c#': 'csharp',
59
+ 'objective-c': 'objectivec',
60
+ shell: 'bash',
61
+ viml: 'vim',
62
+ curl: 'bash',
63
+ 'node.js': 'js',
64
+ }[lang] || DEFAULT_LANG
65
+ );
66
+ }
67
+
68
+ /**
69
+ * Highlight source code string using Prism.js
70
+ * @param source source code to highlight
71
+ * @param lang highlight language
72
+ * @return highlighted source code as **html string**
73
+ */
74
+ export function highlight(source: string | number | boolean, lang: string = DEFAULT_LANG): string {
75
+ lang = lang.toLowerCase();
76
+ let grammar = Prism.languages[lang];
77
+ if (!grammar) {
78
+ grammar = Prism.languages[mapLang(lang)];
79
+ }
80
+ return Prism.highlight(source.toString(), grammar, lang);
81
+ }
@@ -0,0 +1,6 @@
1
+ export * from './ClipboardService';
2
+ export * from './css-variables';
3
+ export * from './highlight';
4
+ export * from './jsonToHtml';
5
+ export * from './media-css';
6
+ export * from './theme-helpers';
@@ -0,0 +1,122 @@
1
+ // Moved from reference-docs
2
+ let level = 1;
3
+
4
+ export function jsonToHTML(json: JSON | Record<string, unknown>, maxExpandLevel: number): string {
5
+ level = 1;
6
+ let output = '';
7
+ output += '<div data-cy="json-sample" class="redoc-json">';
8
+ output += '<code>';
9
+ output += valueToHTML(json, maxExpandLevel);
10
+ output += '</code>';
11
+ output += '</div>';
12
+ return output;
13
+ }
14
+
15
+ function htmlEncode(t: any) {
16
+ return t !== undefined
17
+ ? t
18
+ .toString()
19
+ .replace(/&/g, '&amp;')
20
+ .replace(/"/g, '&quot;')
21
+ .replace(/</g, '&lt;')
22
+ .replace(/>/g, '&gt;')
23
+ : '';
24
+ }
25
+
26
+ function stringifyStringLiteral(str: string) {
27
+ return JSON.stringify(str).slice(1, -1);
28
+ }
29
+
30
+ function decorateWithSpan(value: any, className: string) {
31
+ return '<span class="' + className + '">' + htmlEncode(value) + '</span>';
32
+ }
33
+
34
+ function punctuation(val: any) {
35
+ return '<span class="token punctuation">' + val + '</span>';
36
+ }
37
+
38
+ function valueToHTML(value: any, maxExpandLevel: number) {
39
+ const valueType = typeof value;
40
+ let output = '';
41
+ if (value === undefined || value === null) {
42
+ output += decorateWithSpan('null', 'token keyword');
43
+ } else if (value && value.constructor === Array) {
44
+ level++;
45
+ output += arrayToHTML(value, maxExpandLevel);
46
+ level--;
47
+ } else if (value && value.constructor === Date) {
48
+ output += decorateWithSpan('"' + value.toISOString() + '"', 'token string');
49
+ } else if (valueType === 'object') {
50
+ level++;
51
+ output += objectToHTML(value, maxExpandLevel);
52
+ level--;
53
+ } else if (valueType === 'number') {
54
+ output += decorateWithSpan(value, 'token number');
55
+ } else if (valueType === 'string') {
56
+ if (/^(http|https):\/\/[^\s]+$/.test(value)) {
57
+ output +=
58
+ decorateWithSpan('"', 'token string') +
59
+ '<a href="' +
60
+ encodeURI(value) +
61
+ '">' +
62
+ htmlEncode(stringifyStringLiteral(value)) +
63
+ '</a>' +
64
+ decorateWithSpan('"', 'token string');
65
+ } else {
66
+ output += decorateWithSpan('"' + stringifyStringLiteral(value) + '"', 'token string');
67
+ }
68
+ } else if (valueType === 'boolean') {
69
+ output += decorateWithSpan(value, 'token boolean');
70
+ }
71
+
72
+ return output;
73
+ }
74
+
75
+ function arrayToHTML(json: any, maxExpandLevel: number) {
76
+ const collapsed = level > maxExpandLevel ? 'collapsed' : '';
77
+ let output = `<button class="collapser" aria-label="${
78
+ level > maxExpandLevel + 1 ? 'expand' : 'collapse'
79
+ }"></button>${punctuation('[')}<span class="ellipsis"></span><ul class="array collapsible">`;
80
+ let hasContents = false;
81
+ const length = json.length;
82
+ for (let i = 0; i < length; i++) {
83
+ hasContents = true;
84
+ output += '<li><div class="hoverable ' + collapsed + '">';
85
+ output += valueToHTML(json[i], maxExpandLevel);
86
+ if (i < length - 1) {
87
+ output += ',';
88
+ }
89
+ output += '</div></li>';
90
+ }
91
+ output += `</ul>${punctuation(']')}`;
92
+ if (!hasContents) {
93
+ output = punctuation('[ ]');
94
+ }
95
+ return output;
96
+ }
97
+
98
+ function objectToHTML(json: any, maxExpandLevel: number) {
99
+ const collapsed = level > maxExpandLevel ? 'collapsed' : '';
100
+ const keys = Object.keys(json);
101
+ const length = keys.length;
102
+ let output = `<button class="collapser" aria-label="${
103
+ level > maxExpandLevel + 1 ? 'expand' : 'collapse'
104
+ }"></button>${punctuation('{')}<span class="ellipsis"></span><ul class="obj collapsible">`;
105
+ let hasContents = false;
106
+ for (let i = 0; i < length; i++) {
107
+ const key = keys[i];
108
+ hasContents = true;
109
+ output += '<li><div class="hoverable ' + collapsed + '">';
110
+ output += '<span class="property token string">"' + htmlEncode(key) + '"</span>: ';
111
+ output += valueToHTML(json[key], maxExpandLevel);
112
+ if (i < length - 1) {
113
+ output += punctuation(',');
114
+ }
115
+ output += '</div></li>';
116
+ }
117
+ output += `</ul>${punctuation('}')}`;
118
+ if (!hasContents) {
119
+ output = punctuation('{ }');
120
+ }
121
+ return output;
122
+ }
@@ -0,0 +1,16 @@
1
+ export type MediaQueries = {
2
+ print: string;
3
+ small: string;
4
+ medium: string;
5
+ large: string;
6
+ };
7
+
8
+ export const breakpoints = { small: '50rem', medium: '85rem', large: '105rem' };
9
+
10
+ export function generateMediaQueries(breakpoints: Omit<MediaQueries, 'print'>): MediaQueries {
11
+ const result = <Record<string, string>>{ print: '@media print' };
12
+ for (const [key, value] of Object.entries(breakpoints)) {
13
+ result[key] = `@media screen and (min-width: ${value})`;
14
+ }
15
+ return result as MediaQueries;
16
+ }
@@ -0,0 +1,34 @@
1
+ import type { FlattenSimpleInterpolation } from 'styled-components';
2
+ import { css } from 'styled-components';
3
+
4
+ const typographyProperties = Object.entries({
5
+ fontSize: 'font-size',
6
+ fontWeight: 'font-weight',
7
+ fontFamily: 'font-family',
8
+ lineHeight: 'line-height',
9
+ color: 'color',
10
+ textTransform: 'text-transform',
11
+ });
12
+
13
+ export function getTypographyCssRulesByComponentName(
14
+ componentName: string,
15
+ fallbackName?: string,
16
+ ): Record<string, string> {
17
+ const result = {} as Record<string, string>;
18
+ for (const [styledPropertyName, cssPropertyName] of typographyProperties) {
19
+ const cssVariable = `--${componentName}-${cssPropertyName}`;
20
+ const fallbackVariable = fallbackName ? `,var(--${fallbackName}-${cssPropertyName})` : '';
21
+
22
+ result[styledPropertyName] = `var(${cssVariable}${fallbackVariable})`;
23
+ }
24
+ return result;
25
+ }
26
+
27
+ export function typography(
28
+ componentName: string,
29
+ fallbackName?: string,
30
+ ): FlattenSimpleInterpolation {
31
+ return css`
32
+ ${getTypographyCssRulesByComponentName(componentName, fallbackName)}
33
+ `;
34
+ }
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "@redocly/theme",
3
+ "version": "0.0.1",
4
+ "description": "Shared UI components",
5
+ "author": "team@redocly.com",
6
+ "license": "SEE LICENSE IN LICENSE",
7
+ "main": "index.js",
8
+ "typings": "index.d.ts",
9
+ "files": [
10
+ "lib"
11
+ ],
12
+ "scripts": {
13
+ "start": "npm run storybook",
14
+ "storybook": "start-storybook -p 6006",
15
+ "build-storybook": "build-storybook",
16
+ "clean": "rm -rf lib",
17
+ "compile": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
18
+ "build:copy": " cp -R src package.json .npmignore lib/",
19
+ "build": "npm run clean && npm run compile && npm run build:copy",
20
+ "build:watch": "npm run build && tsc --watch -p tsconfig.build.json & tsc-alias -w -p tsconfig.build.json",
21
+ "deploy": "npm publish lib",
22
+ "lint": "eslint . --ext .ts,.tsx --cache",
23
+ "lint:fix": "eslint . --ext .ts,.tsx --fix",
24
+ "prettier-base": "prettier \"**/*.{json,js,jsx,ts,tsx,yml,yaml,html,md}\"",
25
+ "prettier": "npm run prettier-base -- --write",
26
+ "prettier:check": "npm run prettier-base -- --check",
27
+ "ts:check": "tsc --noEmit --skipLibCheck",
28
+ "test": "jest",
29
+ "test:watch": "jest --watch",
30
+ "test:coverage": "jest --coverage",
31
+ "prepare": "husky install",
32
+ "chromatic": "chromatic --exit-zero-on-changes"
33
+ },
34
+ "peerDependencies": {
35
+ "prismjs": "^1.28.0",
36
+ "react": "^17.0.2",
37
+ "react-dom": "^17.0.2",
38
+ "styled-components": "^5.3.1"
39
+ },
40
+ "devDependencies": {
41
+ "@storybook/addon-actions": "^6.4.22",
42
+ "@storybook/addon-essentials": "^6.4.22",
43
+ "@storybook/addon-interactions": "^6.4.22",
44
+ "@storybook/addon-links": "^6.4.22",
45
+ "@storybook/builder-webpack5": "^6.4.22",
46
+ "@storybook/core-common": "^6.4.22",
47
+ "@storybook/manager-webpack5": "^6.4.22",
48
+ "@storybook/node-logger": "^6.4.22",
49
+ "@storybook/preset-create-react-app": "^4.1.0",
50
+ "@storybook/react": "^6.4.22",
51
+ "@storybook/testing-library": "^0.0.11",
52
+ "@testing-library/jest-dom": "^5.16.4",
53
+ "@testing-library/react": "^12.1.4",
54
+ "@testing-library/user-event": "^13.5.0",
55
+ "@types/jest": "^27.4.1",
56
+ "@types/node": "^16.11.26",
57
+ "@types/prismjs": "^1.26.0",
58
+ "@types/react": "^17.0.43",
59
+ "@types/react-dom": "^17.0.14",
60
+ "@types/styled-components": "^5.1.25",
61
+ "@typescript-eslint/eslint-plugin": "^5.21.0",
62
+ "@typescript-eslint/parser": "^5.22.0",
63
+ "chromatic": "^6.5.4",
64
+ "esbuild": "^0.14.38",
65
+ "eslint": "^8.13.0",
66
+ "eslint-config-prettier": "^8.5.0",
67
+ "eslint-import-resolver-typescript": "^2.7.1",
68
+ "eslint-plugin-import": "^2.26.0",
69
+ "eslint-plugin-jest": "^26.1.4",
70
+ "eslint-plugin-react": "^7.29.4",
71
+ "eslint-plugin-react-hooks": "^4.5.0",
72
+ "eslint-plugin-storybook": "^0.5.11",
73
+ "husky": "^7.0.4",
74
+ "jest": "^27.5.1",
75
+ "jest-styled-components": "^7.0.8",
76
+ "lint-staged": "^12.4.1",
77
+ "prettier": "2.6.2",
78
+ "react": "^17.0.2",
79
+ "react-dom": "^17.0.2",
80
+ "react-refresh": "^0.13.0",
81
+ "react-scripts": "5.0.1",
82
+ "styled-components": "^5.3.5",
83
+ "ts-jest": "^27.1.4",
84
+ "tsc-alias": "^1.6.7",
85
+ "typescript": "^4.6.3",
86
+ "webpack": "^5.72.0"
87
+ },
88
+ "lint-staged": {
89
+ "**/*": "prettier --write --ignore-unknown"
90
+ }
91
+ }