@edvisor/product-language 0.1.0

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 (150) hide show
  1. package/.babelrc +12 -0
  2. package/.eslintrc.json +139 -0
  3. package/.storybook/main.js +57 -0
  4. package/.storybook/manager.js +7 -0
  5. package/.storybook/preview-head.html +1 -0
  6. package/.storybook/preview.js +15 -0
  7. package/.storybook/tsconfig.json +30 -0
  8. package/README.md +33 -0
  9. package/jest.config.ts +15 -0
  10. package/jest.setup.ts +2 -0
  11. package/package.json +30 -0
  12. package/project.json +75 -0
  13. package/src/assets/svg/example_icon.svg +3 -0
  14. package/src/assets/svg/example_icon_white.svg +3 -0
  15. package/src/assets/svg/spinner.svg +3 -0
  16. package/src/assets/svg/spinner_white.svg +3 -0
  17. package/src/helpers/index.ts +3 -0
  18. package/src/helpers/talesOf.tsx +42 -0
  19. package/src/index.ts +2 -0
  20. package/src/lib/components/README.md +49 -0
  21. package/src/lib/components/alert-banner/alert-banner.tsx +34 -0
  22. package/src/lib/components/alert-banner/alert-level-flags.ts +77 -0
  23. package/src/lib/components/alert-banner/index.ts +1 -0
  24. package/src/lib/components/badge/badge-type-flags.ts +72 -0
  25. package/src/lib/components/badge/badge.stories.tsx +16 -0
  26. package/src/lib/components/badge/badge.test.tsx +29 -0
  27. package/src/lib/components/badge/badge.tsx +31 -0
  28. package/src/lib/components/badge/index.ts +1 -0
  29. package/src/lib/components/card/atoms/card-frame.tsx +17 -0
  30. package/src/lib/components/card/atoms/index.ts +1 -0
  31. package/src/lib/components/card/card.test.tsx +163 -0
  32. package/src/lib/components/card/card.tsx +78 -0
  33. package/src/lib/components/card/components/card-alert-banner-slot.tsx +16 -0
  34. package/src/lib/components/card/components/card-controls-slot.tsx +19 -0
  35. package/src/lib/components/card/components/card-section-slot.tsx +51 -0
  36. package/src/lib/components/card/components/index.ts +3 -0
  37. package/src/lib/components/card/index.ts +2 -0
  38. package/src/lib/components/card/molecules/index.ts +1 -0
  39. package/src/lib/components/card/molecules/left-right-card.test.tsx +89 -0
  40. package/src/lib/components/card/molecules/left-right-card.tsx +63 -0
  41. package/src/lib/components/card/storybook/card.stories.mdx +100 -0
  42. package/src/lib/components/card/storybook/components.tsx +240 -0
  43. package/src/lib/components/checkbox/checkbox.test.tsx +39 -0
  44. package/src/lib/components/checkbox/checkbox.tsx +124 -0
  45. package/src/lib/components/checkbox/components/components.tsx +59 -0
  46. package/src/lib/components/checkbox/index.tsx +1 -0
  47. package/src/lib/components/checkbox/stories/checkbox.stories.mdx +54 -0
  48. package/src/lib/components/checkbox/stories/components.tsx +36 -0
  49. package/src/lib/components/checkbox/stories/index.tsx +1 -0
  50. package/src/lib/components/divider/divider-type-flags.tsx +37 -0
  51. package/src/lib/components/divider/divider.test.tsx +34 -0
  52. package/src/lib/components/divider/divider.tsx +37 -0
  53. package/src/lib/components/divider/index.tsx +1 -0
  54. package/src/lib/components/divider/stories/components.tsx +13 -0
  55. package/src/lib/components/divider/stories/divider.stories.mdx +50 -0
  56. package/src/lib/components/index.ts +14 -0
  57. package/src/lib/components/input-field/components/index.ts +2 -0
  58. package/src/lib/components/input-field/components/labeled-input.tsx +61 -0
  59. package/src/lib/components/input-field/components/stepper.tsx +59 -0
  60. package/src/lib/components/input-field/index.ts +6 -0
  61. package/src/lib/components/input-field/input-field.test.tsx +108 -0
  62. package/src/lib/components/input-field/input-field.tsx +126 -0
  63. package/src/lib/components/input-field/input-number.tsx +41 -0
  64. package/src/lib/components/input-field/input-text.tsx +30 -0
  65. package/src/lib/components/input-field/storybook/components.tsx +334 -0
  66. package/src/lib/components/input-field/storybook/input-field.stories.mdx +113 -0
  67. package/src/lib/components/layout/flex.tsx +22 -0
  68. package/src/lib/components/layout/grid-layout.tsx +40 -0
  69. package/src/lib/components/layout/index.ts +3 -0
  70. package/src/lib/components/layout/left-right-layout.tsx +67 -0
  71. package/src/lib/components/link/index.ts +1 -0
  72. package/src/lib/components/link/link.test.tsx +29 -0
  73. package/src/lib/components/link/link.tsx +56 -0
  74. package/src/lib/components/link/storybook/link.stories.mdx +51 -0
  75. package/src/lib/components/molecules/avatar/avatar-size-flags.tsx +55 -0
  76. package/src/lib/components/molecules/avatar/avatar.test.tsx +114 -0
  77. package/src/lib/components/molecules/avatar/avatar.tsx +80 -0
  78. package/src/lib/components/molecules/avatar/index.tsx +1 -0
  79. package/src/lib/components/molecules/avatar/stories/avatar.stories.mdx +55 -0
  80. package/src/lib/components/molecules/avatar/stories/components.tsx +36 -0
  81. package/src/lib/components/molecules/button/button-flags.tsx +235 -0
  82. package/src/lib/components/molecules/button/button.test.tsx +77 -0
  83. package/src/lib/components/molecules/button/button.tsx +231 -0
  84. package/src/lib/components/molecules/button/index.tsx +1 -0
  85. package/src/lib/components/molecules/button/stories/button.stories.mdx +104 -0
  86. package/src/lib/components/molecules/button/stories/components.tsx +86 -0
  87. package/src/lib/components/molecules/index.ts +3 -0
  88. package/src/lib/components/molecules/input-checkbox/index.tsx +1 -0
  89. package/src/lib/components/molecules/input-checkbox/input-checkbox.test.tsx +34 -0
  90. package/src/lib/components/molecules/input-checkbox/input-checkbox.tsx +50 -0
  91. package/src/lib/components/molecules/input-checkbox/stories/components.tsx +36 -0
  92. package/src/lib/components/molecules/input-checkbox/stories/index.tsx +1 -0
  93. package/src/lib/components/molecules/input-checkbox/stories/input-checkbox.stories.mdx +51 -0
  94. package/src/lib/components/organisms/index.ts +1 -0
  95. package/src/lib/components/organisms/multi-choice-list/index.tsx +1 -0
  96. package/src/lib/components/organisms/multi-choice-list/multi-choice-list.test.tsx +33 -0
  97. package/src/lib/components/organisms/multi-choice-list/multi-choice-list.tsx +53 -0
  98. package/src/lib/components/organisms/multi-choice-list/stories/components.tsx +126 -0
  99. package/src/lib/components/organisms/multi-choice-list/stories/index.tsx +1 -0
  100. package/src/lib/components/organisms/multi-choice-list/stories/multi-choice-list.stories.mdx +99 -0
  101. package/src/lib/components/spinner/index.tsx +1 -0
  102. package/src/lib/components/spinner/spinner-size-flags.tsx +39 -0
  103. package/src/lib/components/spinner/spinner.test.tsx +31 -0
  104. package/src/lib/components/spinner/spinner.tsx +67 -0
  105. package/src/lib/components/spinner/stories/components.tsx +8 -0
  106. package/src/lib/components/spinner/stories/spinner.stories.mdx +42 -0
  107. package/src/lib/components/thumbnail/index.tsx +1 -0
  108. package/src/lib/components/thumbnail/stories/thumbnail.stories.mdx +34 -0
  109. package/src/lib/components/thumbnail/thumbnail-size-flags.tsx +41 -0
  110. package/src/lib/components/thumbnail/thumbnail.test.tsx +51 -0
  111. package/src/lib/components/thumbnail/thumbnail.tsx +40 -0
  112. package/src/lib/components/typography/index.ts +1 -0
  113. package/src/lib/components/typography/storybook/components.tsx +256 -0
  114. package/src/lib/components/typography/storybook/typography.stories.mdx +88 -0
  115. package/src/lib/components/typography/typography.test.tsx +93 -0
  116. package/src/lib/components/typography/typography.tsx +57 -0
  117. package/src/lib/foundations/color-system/base-palette/base-palette.stories.tsx +123 -0
  118. package/src/lib/foundations/color-system/base-palette/base-palette.ts +94 -0
  119. package/src/lib/foundations/color-system/base-palette/index.ts +1 -0
  120. package/src/lib/foundations/color-system/color-guidelines/color-guidelines.stories.mdx +85 -0
  121. package/src/lib/foundations/color-system/color-guidelines/color-guidelines.stories.tsx +231 -0
  122. package/src/lib/foundations/color-system/color-guidelines/color-guidelines.ts +159 -0
  123. package/src/lib/foundations/color-system/color-guidelines/index.ts +1 -0
  124. package/src/lib/foundations/color-system/components/color-sample.tsx +99 -0
  125. package/src/lib/foundations/color-system/components/index.ts +1 -0
  126. package/src/lib/foundations/color-system/index.ts +1 -0
  127. package/src/lib/foundations/index.ts +4 -0
  128. package/src/lib/foundations/shadows/components.tsx +59 -0
  129. package/src/lib/foundations/shadows/index.ts +1 -0
  130. package/src/lib/foundations/shadows/shadows.stories.mdx +71 -0
  131. package/src/lib/foundations/shadows/shadows.tsx +47 -0
  132. package/src/lib/foundations/spacing/index.ts +1 -0
  133. package/src/lib/foundations/spacing/spacing-guidelines.ts +24 -0
  134. package/src/lib/foundations/spacing/spacing.stories.mdx +51 -0
  135. package/src/lib/foundations/spacing/spacing.ts +18 -0
  136. package/src/lib/foundations/typography/constants.ts +25 -0
  137. package/src/lib/foundations/typography/index.tsx +1 -0
  138. package/src/lib/foundations/typography/text-aspect-flags.ts +54 -0
  139. package/src/lib/foundations/typography/typography.tsx +97 -0
  140. package/src/lib/helpers/generic-types.ts +44 -0
  141. package/src/lib/helpers/index.ts +6 -0
  142. package/src/lib/helpers/nothing.tsx +18 -0
  143. package/src/lib/helpers/numbers.ts +53 -0
  144. package/src/lib/helpers/safe-navigation.ts +34 -0
  145. package/src/lib/helpers/slots.tsx +76 -0
  146. package/src/lib/helpers/strings.test.ts +47 -0
  147. package/src/lib/helpers/strings.ts +16 -0
  148. package/tsconfig.json +35 -0
  149. package/tsconfig.lib.json +28 -0
  150. package/tsconfig.spec.json +21 -0
@@ -0,0 +1,59 @@
1
+ import styled from 'styled-components'
2
+ import { Surface } from '../color-system'
3
+ import { Padding } from '../spacing'
4
+ import {
5
+ shadowSm,
6
+ shadow,
7
+ shadowMd,
8
+ shadowLg,
9
+ shadowXl,
10
+ shadow2Xl,
11
+ shadowInner,
12
+ } from './shadows'
13
+
14
+ const Container = styled.div`
15
+ width: 128px;
16
+ height: 128px;
17
+ background: ${Surface.Default};
18
+ display: flex;
19
+ flex-direction: row;
20
+ justify-content: center;
21
+ align-items: center;
22
+ padding: ${Padding.none};
23
+ `
24
+
25
+ const ShadowSm = styled(Container)`
26
+ ${shadowSm}
27
+ `
28
+ const Shadow = styled(Container)`
29
+ ${shadow}
30
+ `
31
+
32
+ const ShadowMd = styled(Container)`
33
+ ${shadowMd}
34
+ `
35
+ const ShadowLg = styled(Container)`
36
+ ${shadowLg}
37
+ `
38
+
39
+ const ShadowXl = styled(Container)`
40
+ ${shadowXl}
41
+ `
42
+
43
+ const Shadow2Xl = styled(Container)`
44
+ ${shadow2Xl}
45
+ `
46
+
47
+ const ShadowInner = styled(Container)`
48
+ ${shadowInner}
49
+ `
50
+
51
+ export {
52
+ ShadowSm,
53
+ Shadow,
54
+ ShadowLg,
55
+ ShadowMd,
56
+ ShadowXl,
57
+ Shadow2Xl,
58
+ ShadowInner,
59
+ }
@@ -0,0 +1 @@
1
+ export * from './shadows'
@@ -0,0 +1,71 @@
1
+ import { Canvas, Meta } from '@storybook/addon-docs';
2
+ import {
3
+ ShadowSm,
4
+ Shadow,
5
+ Shadow2Xl,
6
+ ShadowInner,
7
+ ShadowMd,
8
+ ShadowLg,
9
+ ShadowXl
10
+ } from './components'
11
+
12
+ <Meta title="Foundations/Shadows"/>
13
+
14
+ # Shadows
15
+
16
+ For more details, check out the guidelines on [Figma](https://www.figma.com/file/ue1CurHfZ426o2T2l8Dk64/UI-Library-(in-progress)?node-id=743%3A7913)
17
+
18
+ ## How to use
19
+
20
+ ```javascript
21
+ // Import the shadow that we'd like to use.
22
+ import {
23
+ shadowSm,
24
+ } from './shadows';
25
+
26
+ import styled from 'styled-components';
27
+
28
+ // Add them to the styled strucute that you'd like to add the shadow
29
+ const ShadowSm = styled.div`
30
+ ${shadowSm}
31
+ `
32
+ ```
33
+
34
+ ## Examples
35
+
36
+ <Canvas>
37
+ <ShadowSm>
38
+ .shadow-sm
39
+ </ShadowSm>
40
+ <Shadow>
41
+ .shadow
42
+ </Shadow>
43
+ <ShadowMd>
44
+ .shadow-md
45
+ </ShadowMd>
46
+ <ShadowLg>
47
+ .shadow-lg
48
+ </ShadowLg>
49
+ <ShadowXl>
50
+ .shadow-xl
51
+ </ShadowXl>
52
+ <Shadow2Xl>
53
+ .shadow-2xl
54
+ </Shadow2Xl>
55
+ <ShadowInner>
56
+ .shadow-inner
57
+ </ShadowInner>
58
+ </Canvas>
59
+
60
+ ## List of Values
61
+
62
+ | Name |
63
+ | ---- |
64
+ | `shadowSm` |
65
+ | `shadow` |
66
+ | `shadowMd` |
67
+ | `shadowLg` |
68
+ | `shadowXl` |
69
+ | `shadow2Xl` |
70
+ | `shadowInner` |
71
+
@@ -0,0 +1,47 @@
1
+ import { css } from 'styled-components'
2
+
3
+ const shadowSm = css`
4
+ box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.05);
5
+ border-radius: 6px;
6
+ `
7
+
8
+ const shadow = css`
9
+ box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1), 0px 1px 2px rgba(0, 0, 0, 0.06);
10
+ border-radius: 6px;
11
+ `
12
+
13
+ const shadowMd = css`
14
+ box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1);
15
+ border-radius: 6px;
16
+ `
17
+
18
+ const shadowLg = css`
19
+ box-shadow: 0px 10px 15px -3px rgba(0, 0, 0, 0.1), 0px 4px 6px -2px rgba(0, 0, 0, 0.05);
20
+ border-radius: 6px;
21
+ `
22
+
23
+ const shadowXl = css`
24
+ box-shadow: 0px 20px 25px -5px rgba(0, 0, 0, 0.1), 0px 10px 10px -5px rgba(0, 0, 0, 0.04);
25
+ border-radius: 6px;
26
+ `
27
+
28
+ const shadow2Xl = css`
29
+ box-shadow: 0px 25px 50px -12px rgba(0, 0, 0, 0.25);
30
+ border-radius: 6px;
31
+ `
32
+
33
+ const shadowInner = css`
34
+ box-shadow: inset 0px 2px 4px rgba(0, 0, 0, 0.06);
35
+ border-radius: 6px;
36
+ `
37
+
38
+ export {
39
+ shadowSm,
40
+ shadow,
41
+ shadowMd,
42
+ shadowLg,
43
+ shadowXl,
44
+ shadow2Xl,
45
+ shadowInner,
46
+ }
47
+
@@ -0,0 +1 @@
1
+ export * from './spacing-guidelines'
@@ -0,0 +1,24 @@
1
+ import { SPACING } from './spacing'
2
+
3
+ export const Padding = {
4
+ none: 0,
5
+ xxxs: SPACING.Size2,
6
+ xxs: SPACING.Size4,
7
+ xs: SPACING.Size8,
8
+ s: SPACING.Size12,
9
+ m: SPACING.Size16,
10
+ l: SPACING.Size24,
11
+ xl: SPACING.Size32,
12
+ } as const
13
+
14
+ export const Margin = {
15
+ none: 0,
16
+ xxxs: SPACING.Size2,
17
+ xxs: SPACING.Size4,
18
+ xs: SPACING.Size8,
19
+ s: SPACING.Size12,
20
+ m: SPACING.Size16,
21
+ l: SPACING.Size24,
22
+ xl: SPACING.Size32,
23
+ xxl: SPACING.Size64,
24
+ } as const
@@ -0,0 +1,51 @@
1
+ import { Meta, Description } from '@storybook/addon-docs';
2
+
3
+
4
+ <Meta title="Foundations/Spacing" />
5
+
6
+ # Spacing System
7
+
8
+ All spacing for components and typography is done in increments of 8 pixels.
9
+ This forms the basic unit of measurement for spacing.
10
+
11
+ For more details, check out the guidelines on [Figma](https://www.figma.com/file/ue1CurHfZ426o2T2l8Dk64/UI-Library-(in-progress)?node-id=388%3A364)
12
+
13
+ ## How to use
14
+
15
+ ```javascript
16
+ import SPACING from './spacing'
17
+
18
+ //get the token value
19
+ SPACING.[`YOUR-VALUE-HERE`]
20
+ ```
21
+
22
+ ## When to use
23
+
24
+ You can set this values from this props:
25
+
26
+ - width
27
+ - heigth
28
+ - margin
29
+ - padding
30
+
31
+
32
+ ## List of Values
33
+
34
+ | Name | Value |
35
+ | ---- | ----- |
36
+ | `Size2` | 2px|
37
+ | `Size4` | 4px|
38
+ | `Size8` | 8px|
39
+ | `Size12` | 12px|
40
+ | `Size16` | 16px|
41
+ | `Size24` | 24px|
42
+ | `Size32` | 32px|
43
+ | `Size64` | 64px|
44
+ | `Size96` | 96px|
45
+ | `Size128` | 128px|
46
+ | `Size192` | 192px|
47
+ | `Size256` | 256px|
48
+ | `Size384` | 384px|
49
+ | `Size512` | 512px|
50
+ | `Size640` | 640px|
51
+ | `Size768` | 768px|
@@ -0,0 +1,18 @@
1
+ export enum SPACING {
2
+ Size2 = '2px',
3
+ Size4 = '4px',
4
+ Size8 = '8px',
5
+ Size12 = '12px',
6
+ Size16 = '16px',
7
+ Size24 = '24px',
8
+ Size32 = '32px',
9
+ Size64 = '64px',
10
+ Size96 = '96px',
11
+ Size128 = '128px',
12
+ Size192 = '192px',
13
+ Size256 = '256px',
14
+ Size384 = '384px',
15
+ Size512 = '512px',
16
+ Size640 = '640px',
17
+ Size768 = '768px',
18
+ }
@@ -0,0 +1,25 @@
1
+
2
+ export const enum FontWeight {
3
+ Regular = '400',
4
+ Medium = '500',
5
+ SemiBold = '600',
6
+ }
7
+
8
+ export const FontSize = {
9
+ a: '13px',
10
+ b: '14px',
11
+ c: '16px',
12
+ d: '18px',
13
+ e: '20px',
14
+ f: '28px',
15
+ g: '36px',
16
+ } as const
17
+
18
+ export const LineHeight = {
19
+ a: '16px',
20
+ b: '20px',
21
+ c: '24px',
22
+ d: '28px',
23
+ e: '32px',
24
+ f: '44px',
25
+ } as const
@@ -0,0 +1 @@
1
+ export * from './typography'
@@ -0,0 +1,54 @@
1
+ import { bitwiseOr, MappedEnum, PropsWithChildren, RequireOnlyOne } from '@helpers'
2
+ import { Text } from '../color-system'
3
+
4
+ export const enum TextAspects {
5
+ default = 1,
6
+ subdued = 2,
7
+ light = 4,
8
+ critical = 8,
9
+ success = 16,
10
+ onPrimary = 32,
11
+ onCritical = 64,
12
+ }
13
+
14
+ type TextOptions<T> = MappedEnum<typeof TextAspects, T>
15
+
16
+ function toTextAspect(n: number): TextAspects {
17
+ switch (n) {
18
+ case TextAspects.subdued: return TextAspects.subdued
19
+ case TextAspects.light: return TextAspects.light
20
+ case TextAspects.critical: return TextAspects.critical
21
+ case TextAspects.success: return TextAspects.success
22
+ case TextAspects.onPrimary: return TextAspects.onPrimary
23
+ case TextAspects.onCritical: return TextAspects.onCritical
24
+ default: return TextAspects.default
25
+ }
26
+ }
27
+
28
+ const TextAspectColors = {
29
+ [TextAspects.default]: Text.Default,
30
+ [TextAspects.subdued]: Text.Subdued,
31
+ [TextAspects.light]: Text.Light,
32
+ [TextAspects.onPrimary]: Text.OnPrimary,
33
+ [TextAspects.onCritical]: Text.OnPrimary,
34
+ [TextAspects.success]: Text.Success,
35
+ [TextAspects.critical]: Text.Critical,
36
+ }
37
+
38
+ export type ITextAspectProps = Partial<RequireOnlyOne<TextOptions<boolean>>> & PropsWithChildren
39
+
40
+ export function getTextAspect(props: ITextAspectProps) {
41
+ return TextAspectColors[
42
+ toTextAspect(
43
+ bitwiseOr([
44
+ props.default,
45
+ props.subdued,
46
+ props.light,
47
+ props.critical,
48
+ props.success,
49
+ props.onPrimary,
50
+ props.onCritical,
51
+ ])
52
+ )
53
+ ]
54
+ }
@@ -0,0 +1,97 @@
1
+ import { css } from 'styled-components'
2
+ import { getTextAspect, ITextAspectProps } from './text-aspect-flags'
3
+ import { FontWeight, FontSize, LineHeight } from './constants'
4
+ import { is } from '@helpers'
5
+
6
+ export type ITextProps = ITextAspectProps & { emphasis?: boolean }
7
+
8
+ const LightText = css`
9
+ color: ${getTextAspect({ light: true })};
10
+ `
11
+
12
+ const Base = css<ITextProps>`
13
+ color: ${(props) => getTextAspect(props)};
14
+ font-family: 'Inter';
15
+ `
16
+
17
+ const Display = css<ITextProps>`
18
+ ${Base}
19
+ font-weight: ${FontWeight.Regular};
20
+ font-size: ${FontSize.g};
21
+ line-height: ${LineHeight.f};
22
+ `
23
+
24
+ const Heading1 = css<ITextProps>`
25
+ ${Base}
26
+ font-weight: ${FontWeight.SemiBold};
27
+ font-size: ${FontSize.f};
28
+ line-height: ${LineHeight.e};
29
+ `
30
+
31
+ const Heading2 = css<ITextProps>`
32
+ ${Heading1}
33
+ font-size: ${FontSize.e};
34
+ line-height: ${LineHeight.d};
35
+ `
36
+
37
+ const Heading3 = css<ITextProps>`
38
+ ${Heading1}
39
+ font-size: ${FontSize.c};
40
+ line-height: ${LineHeight.c};
41
+ `
42
+
43
+ const Heading4 = css<ITextProps>`
44
+ ${Heading1}
45
+ font-size: ${FontSize.b};
46
+ line-height: ${LineHeight.b};
47
+ `
48
+
49
+ const BodyLarge = css<ITextProps>`
50
+ ${Base}
51
+ font-weight: ${({ emphasis }) => is(emphasis) ? FontWeight.SemiBold : FontWeight.Regular};
52
+ font-size: ${FontSize.d};
53
+ line-height: ${LineHeight.d};
54
+ `
55
+
56
+ const Body = css<ITextProps>`
57
+ ${BodyLarge}
58
+ font-weight: ${({ emphasis }) => is(emphasis) ? FontWeight.Medium : FontWeight.Regular};
59
+ font-size: ${FontSize.b};
60
+ line-height: ${LineHeight.b};
61
+ `
62
+
63
+ const Caption = css<ITextProps>`
64
+ ${BodyLarge}
65
+ font-size: ${FontSize.a};
66
+ line-height: ${LineHeight.a};
67
+ `
68
+
69
+ const Label1 = css<ITextProps>`
70
+ ${BodyLarge}
71
+ font-weight: ${({ emphasis }) => is(emphasis) ? FontWeight.Medium : FontWeight.Regular};
72
+ font-size: ${FontSize.b};
73
+ line-height: ${LineHeight.b};
74
+ `
75
+
76
+ const Label2 = css<ITextProps>`
77
+ ${BodyLarge}
78
+ font-size: ${FontSize.a};
79
+ line-height: ${LineHeight.a};
80
+ `
81
+
82
+ export const Typography = {
83
+ Display,
84
+ Heading1,
85
+ Heading2,
86
+ Heading3,
87
+ Heading4,
88
+ BodyLarge,
89
+ Body,
90
+ Caption,
91
+ Label1,
92
+ Label2,
93
+ }
94
+
95
+ export const _Typography = {
96
+ LightText,
97
+ }
@@ -0,0 +1,44 @@
1
+ // eslint-disable-next-line no-restricted-syntax
2
+ import React, { FC as FunctionComponent, ForwardRefExoticComponent, ForwardRefRenderFunction, PropsWithChildren as PWC, PropsWithoutRef, RefAttributes } from 'react'
3
+ import { Slot } from './slots'
4
+
5
+ /** @see https://stackoverflow.com/a/49725198/29182 */
6
+ export type RequireOnlyOne<T, Keys extends keyof T = keyof T> = Pick<
7
+ T,
8
+ Exclude<keyof T, Keys>
9
+ > &
10
+ {
11
+ [K in Keys]-?: Required<Pick<T, K>> &
12
+ Partial<Record<Exclude<Keys, K>, undefined>>;
13
+ }[Keys];
14
+
15
+ export type MappedEnum<E, T> = {
16
+ [key in keyof E]: T;
17
+ }
18
+
19
+ export type Values<T> = T[keyof T];
20
+
21
+ export type PropsWithChildren<T = unknown> = PWC<T>
22
+
23
+ // Our FC type adds the ability to specify sub-components such as Slots
24
+ // also, just good to wrap imports from 3rd parties in general
25
+ export type FC<
26
+ // eslint-disable-next-line @typescript-eslint/ban-types
27
+ P = {},
28
+ // eslint-disable-next-line @typescript-eslint/ban-types
29
+ E extends { [x: symbol]: FunctionComponent<PropsWithChildren> | typeof Slot } = {}
30
+ > = FunctionComponent<P>
31
+ & {
32
+ [key in keyof E]: E[key]
33
+ }
34
+
35
+ // eslint-disable-next-line @typescript-eslint/ban-types
36
+ type ExtensibleForwardRef<T, P = {}, E = {}> = ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>
37
+ & {
38
+ [key in keyof E]: E[key]
39
+ }
40
+
41
+ // eslint-disable-next-line @typescript-eslint/ban-types
42
+ export function forwardRef<T, P = {}, E = {}>(render: ForwardRefRenderFunction<T, P>): ExtensibleForwardRef<T, P, E> {
43
+ return React.forwardRef(render) as ExtensibleForwardRef<T, P, E>
44
+ }
@@ -0,0 +1,6 @@
1
+ export * from './safe-navigation'
2
+ export * from './slots'
3
+ export * from './generic-types'
4
+ export * from './numbers'
5
+ export * from './nothing'
6
+ export * from './strings'
@@ -0,0 +1,18 @@
1
+ import { FC, PropsWithChildren } from './generic-types'
2
+ import { isDefined } from './safe-navigation'
3
+
4
+ // eslint-disable-next-line no-null/no-null
5
+ export const Nothing: FC = () => null
6
+
7
+ export function maybeRender<T>(prop: T, JSX: JSX.Element) {
8
+ return isDefined(prop) && Boolean(prop) ? JSX : <Nothing />
9
+ }
10
+
11
+ interface IIfProps {
12
+ is: unknown
13
+ }
14
+
15
+ export const If: FC<PropsWithChildren<IIfProps>> = (props) => {
16
+ // eslint-disable-next-line react/jsx-no-useless-fragment
17
+ return maybeRender(props.is, <>{props.children}</>)
18
+ }
@@ -0,0 +1,53 @@
1
+ export type Hex = `#${string}`
2
+
3
+ export function clamp(a: number, b: number, c: number) {
4
+ return Math.max(a, Math.min(b, c))
5
+ }
6
+
7
+ export function toHex(n: number, length: number): Hex {
8
+ return `#${n.toString(16).padStart(length, '0').toUpperCase()}`
9
+ }
10
+
11
+ export function concatHex(a: Hex, b: Hex): Hex {
12
+ return `#${a.slice(1) + b.slice(1)}`
13
+ }
14
+
15
+ /** given an array of boolean flags, bitwiseOr interprets them as an unsigned integer
16
+ *
17
+ * ```ts
18
+ * bitwiseOr([false, true, false, true]) => 5 // 0b0101
19
+ * ```
20
+ *
21
+ * This is useful for indexing into an enum:
22
+ *
23
+ * ```ts
24
+ * const enum Level {
25
+ * default = 0,
26
+ * info = 0,
27
+ * danger = 1,
28
+ * warning = 2
29
+ * }
30
+ *
31
+ * interface IProps {
32
+ * info?: boolean
33
+ * danger?: boolean
34
+ * warning?: boolean
35
+ * }
36
+ *
37
+ * function toLevel(n: number): Level {
38
+ * switch (n) {
39
+ * case Level.info: return Level.info
40
+ * case Level.danger: return Level.danger
41
+ * case Level.warning: return Level.warning
42
+ * default: return Level.default
43
+ * }
44
+ * }
45
+ *
46
+ * const level = bitwiseOr([props.info, props.danger, props.warning])
47
+ *
48
+ * const levelEnum = toLevel(level)
49
+ * ```
50
+ */
51
+ export function bitwiseOr(flags: unknown[]): number {
52
+ return flags.reduce((mask: number, flag, i) => mask | (Number(flag) << i), 0)
53
+ }
@@ -0,0 +1,34 @@
1
+
2
+ /** even though we have null disabled in the repo,
3
+ * I still would not want isNil to skip checking null
4
+ * it is for juuuuust in case a third party sends us a null
5
+ * or something, and the types are not correct
6
+ */
7
+
8
+ /* eslint-disable no-null/no-null */
9
+ /* eslint-disable @typescript-eslint/ban-types */
10
+
11
+ export function isNil<T>(value: T | undefined | null): value is undefined | null {
12
+ return value === null || value === undefined
13
+ }
14
+
15
+ export function isDefined<T>(value: T | undefined | null): value is T {
16
+ return !isNil(value)
17
+ }
18
+
19
+ export function defaultTo<T>(value: T | undefined | null, fallback: T): T {
20
+ return isDefined(value) ? value : fallback
21
+ }
22
+
23
+ export function isEmpty<T extends { length: number }>(obj: T) {
24
+ return obj.length < 1
25
+ }
26
+
27
+ /** used for evaluating tri-state logic (true | false | undefined) */
28
+ export function is (pred?: boolean): boolean {
29
+ return isDefined(pred) && pred
30
+ }
31
+
32
+ export function safeArray<T>(arr: T[] | undefined | null): T[] {
33
+ return isDefined(arr) ? arr : []
34
+ }
@@ -0,0 +1,76 @@
1
+ import { Children, PureComponent, ReactElement, ReactNode } from 'react'
2
+ import { PropsWithChildren } from './generic-types'
3
+ import { isDefined, isNil } from './safe-navigation'
4
+
5
+ /**
6
+ * @TODO these aren't quiiiiite right
7
+ *
8
+ * They all say they return ReactNode but I feel like JSX.Element or something
9
+ * is more accurate? The child type needs to include _anything react can render_
10
+ * but it should also allow the caller to cloneElement on the results so that
11
+ * they can do stuff like
12
+ *
13
+ * const sections = getSlots(Section, children)
14
+ * .map((el, i) => i === 0 ? cloneElement(el, { first: true }) : el)
15
+ *
16
+ * Right? I want this...
17
+ * */
18
+
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
+ function isReactElement (obj?: any): obj is ReactElement {
21
+ // eslint-disable-next-line no-prototype-builtins
22
+ return isDefined(obj) && obj.hasOwnProperty('type')
23
+ }
24
+
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
+ const isSlotOfType = <T extends typeof Slot>(type: T) => (obj?: any): obj is T => {
27
+ return isDefined(obj) && isReactElement(obj) && (Object.getPrototypeOf(obj.type) === type || obj.type === type)
28
+ }
29
+
30
+ const findSlotByType = <T extends typeof Slot>(type: T, children?: ReactNode): ReactNode => {
31
+ return Children.toArray(children).find(isSlotOfType(type))
32
+ }
33
+
34
+ const filterSlotByType = <T extends typeof Slot>(type: T, children?: ReactNode): ReactNode[] => {
35
+ return Children.toArray(children).filter(isSlotOfType(type))
36
+ }
37
+
38
+ export class Slot<T = unknown> extends PureComponent<PropsWithChildren<T>> {
39
+ override render () {
40
+ return this.props.children
41
+ }
42
+ }
43
+
44
+ export function getChildren(children?: ReactNode): ReactNode[] {
45
+ return Children.toArray(children).filter((child) => !isSlotOfType(Slot)(child))
46
+ }
47
+
48
+ export function getSlots<T extends typeof Slot>(slot: T, children?: ReactNode): ReactNode[] {
49
+ const result = filterSlotByType(slot, children)
50
+
51
+ if (isNil(result)) {
52
+ return []
53
+ }
54
+
55
+ return result
56
+ }
57
+
58
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
59
+ function hasProps (obj: any): obj is { props: { children: ReactNode }} {
60
+ // eslint-disable-next-line no-prototype-builtins
61
+ return isDefined(obj) && obj.hasOwnProperty('props')
62
+ }
63
+
64
+ export function getSlot<T extends typeof Slot>(slot: T, children?: ReactNode): ReactNode {
65
+ const result = findSlotByType(slot, children)
66
+
67
+ if (isNil(result)) {
68
+ return undefined
69
+ }
70
+
71
+ if (hasProps(result)) {
72
+ return result
73
+ }
74
+
75
+ return result
76
+ }