@stack-spot/citric-react 0.38.0 → 0.39.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 (191) hide show
  1. package/CHANGELOG.md +13 -13
  2. package/dist/citric.css +2844 -2844
  3. package/dist/components/Accordion.d.ts +1 -1
  4. package/dist/components/Accordion.js +1 -1
  5. package/dist/components/Alert.d.ts +1 -1
  6. package/dist/components/Alert.js +1 -1
  7. package/dist/components/AsyncContent.d.ts +1 -1
  8. package/dist/components/AsyncContent.js +1 -1
  9. package/dist/components/Avatar.d.ts +1 -1
  10. package/dist/components/Avatar.js +1 -1
  11. package/dist/components/AvatarGroup.d.ts +1 -1
  12. package/dist/components/AvatarGroup.js +1 -1
  13. package/dist/components/Badge.d.ts +1 -1
  14. package/dist/components/Badge.js +1 -1
  15. package/dist/components/Blockquote.d.ts +1 -1
  16. package/dist/components/Blockquote.js +1 -1
  17. package/dist/components/Breadcrumb.d.ts +1 -1
  18. package/dist/components/Breadcrumb.js +1 -1
  19. package/dist/components/Button.d.ts +1 -1
  20. package/dist/components/Button.js +1 -1
  21. package/dist/components/ButtonLink.d.ts +1 -1
  22. package/dist/components/ButtonLink.js +1 -1
  23. package/dist/components/Card.d.ts +1 -1
  24. package/dist/components/Card.js +1 -1
  25. package/dist/components/Checkbox.d.ts +1 -1
  26. package/dist/components/Checkbox.js +1 -1
  27. package/dist/components/CheckboxGroup.d.ts +1 -1
  28. package/dist/components/CheckboxGroup.d.ts.map +1 -1
  29. package/dist/components/CheckboxGroup.js +2 -2
  30. package/dist/components/CheckboxGroup.js.map +1 -1
  31. package/dist/components/Circle.d.ts +1 -1
  32. package/dist/components/Circle.js +1 -1
  33. package/dist/components/Divider.d.ts +1 -1
  34. package/dist/components/Divider.js +1 -1
  35. package/dist/components/ErrorBoundary.d.ts +1 -1
  36. package/dist/components/ErrorBoundary.js +1 -1
  37. package/dist/components/ErrorMessage.d.ts +1 -1
  38. package/dist/components/ErrorMessage.js +1 -1
  39. package/dist/components/FallbackBoundary.d.ts +1 -1
  40. package/dist/components/FallbackBoundary.js +1 -1
  41. package/dist/components/Favorite.d.ts +1 -1
  42. package/dist/components/Favorite.js +1 -1
  43. package/dist/components/FieldGroup.d.ts +1 -1
  44. package/dist/components/FieldGroup.js +1 -1
  45. package/dist/components/Form.d.ts +2 -2
  46. package/dist/components/Form.js +1 -1
  47. package/dist/components/FormGroup.d.ts +1 -1
  48. package/dist/components/FormGroup.js +1 -1
  49. package/dist/components/Icon.d.ts +1 -1
  50. package/dist/components/Icon.js +1 -1
  51. package/dist/components/IconBox.d.ts +3 -3
  52. package/dist/components/IconBox.js +1 -1
  53. package/dist/components/ImageBox.d.ts +3 -3
  54. package/dist/components/ImageBox.js +1 -1
  55. package/dist/components/ImageWithFallback.d.ts +1 -1
  56. package/dist/components/ImageWithFallback.js +1 -1
  57. package/dist/components/Input.d.ts +1 -1
  58. package/dist/components/Input.js +1 -1
  59. package/dist/components/Link.d.ts +1 -1
  60. package/dist/components/Link.js +1 -1
  61. package/dist/components/LoadingPanel.d.ts +1 -1
  62. package/dist/components/LoadingPanel.js +1 -1
  63. package/dist/components/MenuOverlay/Menu.d.ts +1 -1
  64. package/dist/components/MenuOverlay/Menu.js +1 -1
  65. package/dist/components/MenuOverlay/index.d.ts +1 -1
  66. package/dist/components/MenuOverlay/index.js +1 -1
  67. package/dist/components/Overlay/index.d.ts +4 -1
  68. package/dist/components/Overlay/index.d.ts.map +1 -1
  69. package/dist/components/Overlay/index.js +4 -1
  70. package/dist/components/Overlay/index.js.map +1 -1
  71. package/dist/components/Pagination.d.ts +1 -1
  72. package/dist/components/Pagination.js +1 -1
  73. package/dist/components/ProgressBar.d.ts +1 -1
  74. package/dist/components/ProgressBar.js +1 -1
  75. package/dist/components/ProgressCircular.d.ts +1 -1
  76. package/dist/components/ProgressCircular.js +1 -1
  77. package/dist/components/RadioGroup.d.ts +1 -1
  78. package/dist/components/RadioGroup.d.ts.map +1 -1
  79. package/dist/components/RadioGroup.js +2 -2
  80. package/dist/components/RadioGroup.js.map +1 -1
  81. package/dist/components/Rating.d.ts +1 -1
  82. package/dist/components/Rating.js +1 -1
  83. package/dist/components/Select/MultiSelect.d.ts +1 -1
  84. package/dist/components/Select/MultiSelect.js +1 -1
  85. package/dist/components/Select/RichSelect.d.ts +1 -1
  86. package/dist/components/Select/RichSelect.js +1 -1
  87. package/dist/components/Select/SimpleSelect.d.ts +1 -1
  88. package/dist/components/Select/SimpleSelect.js +1 -1
  89. package/dist/components/Select/index.d.ts +1 -1
  90. package/dist/components/Select/index.js +1 -1
  91. package/dist/components/SelectBox.d.ts +1 -1
  92. package/dist/components/SelectBox.js +1 -1
  93. package/dist/components/Skeleton.d.ts +1 -1
  94. package/dist/components/Skeleton.js +1 -1
  95. package/dist/components/Slider.d.ts +1 -1
  96. package/dist/components/Slider.js +1 -1
  97. package/dist/components/SmartTable.d.ts +1 -1
  98. package/dist/components/SmartTable.js +1 -1
  99. package/dist/components/Stepper.d.ts +1 -1
  100. package/dist/components/Stepper.js +1 -1
  101. package/dist/components/Table.d.ts +3 -3
  102. package/dist/components/Table.js +1 -1
  103. package/dist/components/Tabs/index.d.ts +1 -1
  104. package/dist/components/Tabs/index.js +1 -1
  105. package/dist/components/Textarea.d.ts +1 -1
  106. package/dist/components/Textarea.js +1 -1
  107. package/dist/components/Tooltip.d.ts +1 -1
  108. package/dist/components/Tooltip.js +1 -1
  109. package/dist/context/CitricProvider.d.ts +1 -1
  110. package/dist/context/CitricProvider.js +1 -1
  111. package/dist/overlay.js +1 -1
  112. package/dist/theme.css +415 -415
  113. package/package.json +1 -1
  114. package/scripts/build-css.ts +49 -49
  115. package/src/components/Accordion.tsx +130 -130
  116. package/src/components/Alert.tsx +24 -24
  117. package/src/components/AsyncContent.tsx +70 -70
  118. package/src/components/Avatar.tsx +45 -45
  119. package/src/components/AvatarGroup.tsx +49 -49
  120. package/src/components/Badge.tsx +47 -47
  121. package/src/components/Blockquote.tsx +18 -18
  122. package/src/components/Breadcrumb.tsx +33 -33
  123. package/src/components/Button.tsx +105 -105
  124. package/src/components/ButtonLink.tsx +45 -45
  125. package/src/components/Card.tsx +68 -68
  126. package/src/components/Checkbox.tsx +51 -51
  127. package/src/components/CheckboxGroup.tsx +153 -152
  128. package/src/components/Circle.tsx +43 -43
  129. package/src/components/CitricComponent.ts +47 -47
  130. package/src/components/Divider.tsx +24 -24
  131. package/src/components/ErrorBoundary.tsx +75 -75
  132. package/src/components/ErrorMessage.tsx +11 -11
  133. package/src/components/FallbackBoundary.tsx +40 -40
  134. package/src/components/Favorite.tsx +57 -57
  135. package/src/components/FieldGroup.tsx +46 -46
  136. package/src/components/Form.tsx +36 -36
  137. package/src/components/FormGroup.tsx +57 -57
  138. package/src/components/Icon.tsx +35 -35
  139. package/src/components/IconBox.tsx +134 -134
  140. package/src/components/ImageBox.tsx +125 -125
  141. package/src/components/ImageWithFallback.tsx +65 -65
  142. package/src/components/Input.tsx +49 -49
  143. package/src/components/Link.tsx +55 -55
  144. package/src/components/LoadingPanel.tsx +8 -8
  145. package/src/components/MenuOverlay/Menu.tsx +158 -158
  146. package/src/components/MenuOverlay/context.ts +20 -20
  147. package/src/components/MenuOverlay/index.tsx +55 -55
  148. package/src/components/MenuOverlay/keyboard.ts +60 -60
  149. package/src/components/MenuOverlay/types.ts +171 -171
  150. package/src/components/Overlay/context.ts +10 -10
  151. package/src/components/Overlay/index.tsx +167 -164
  152. package/src/components/Overlay/types.ts +70 -70
  153. package/src/components/Pagination.tsx +133 -133
  154. package/src/components/ProgressBar.tsx +45 -45
  155. package/src/components/ProgressCircular.tsx +45 -45
  156. package/src/components/RadioGroup.tsx +147 -146
  157. package/src/components/Rating.tsx +98 -98
  158. package/src/components/Select/MultiSelect.tsx +217 -217
  159. package/src/components/Select/RichSelect.tsx +128 -128
  160. package/src/components/Select/SimpleSelect.tsx +73 -73
  161. package/src/components/Select/hooks.ts +133 -133
  162. package/src/components/Select/index.tsx +35 -35
  163. package/src/components/Select/types.ts +134 -134
  164. package/src/components/SelectBox.tsx +167 -167
  165. package/src/components/Skeleton.tsx +53 -53
  166. package/src/components/Slider.tsx +89 -89
  167. package/src/components/SmartTable.tsx +227 -227
  168. package/src/components/Stepper.tsx +163 -163
  169. package/src/components/Table.tsx +234 -234
  170. package/src/components/Tabs/TabController.ts +54 -54
  171. package/src/components/Tabs/index.tsx +87 -87
  172. package/src/components/Tabs/types.ts +54 -54
  173. package/src/components/Tabs/utils.ts +6 -6
  174. package/src/components/Text.ts +111 -111
  175. package/src/components/Textarea.tsx +27 -27
  176. package/src/components/Tooltip.tsx +72 -72
  177. package/src/components/layout.tsx +101 -101
  178. package/src/context/CitricContext.tsx +4 -4
  179. package/src/context/CitricProvider.tsx +14 -14
  180. package/src/context/hooks.ts +6 -6
  181. package/src/index.ts +58 -58
  182. package/src/overlay.ts +341 -341
  183. package/src/types.ts +216 -216
  184. package/src/utils/ValueController.ts +28 -28
  185. package/src/utils/acessibility.ts +92 -92
  186. package/src/utils/checkbox.ts +121 -121
  187. package/src/utils/css.ts +119 -119
  188. package/src/utils/options.ts +9 -9
  189. package/src/utils/radio.ts +93 -93
  190. package/src/utils/react.ts +6 -6
  191. package/tsconfig.json +10 -10
@@ -1,87 +1,87 @@
1
- import { listToClass } from '@stack-spot/portal-theme'
2
- import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
3
- import { createContext, Suspense, useContext, useEffect, useMemo, useState } from 'react'
4
- import { withRef } from '../../utils/react'
5
- import { CitricComponent } from '../CitricComponent'
6
- import { ErrorBoundary } from '../ErrorBoundary'
7
- import { ProgressCircular } from '../ProgressCircular'
8
- import { Center } from '../layout'
9
- import { TabController } from './TabController'
10
- import { TabsProps } from './types'
11
- import { findSelectedIndex } from './utils'
12
-
13
- const ctx = createContext<TabController<any> | undefined>(undefined)
14
-
15
- /**
16
- * Builds a Tab selector. The content of a tab is a React component and it can suspend, i.e. tabs can be asynchronously loaded.
17
- *
18
- * @example
19
- *
20
- * ```
21
- * const tabs: Tab[] = useMemo(() => [
22
- * { key: 'tab1', label: 'Tab 1', content: <><h1>First tab</h1><p>Content of the first tab</p></> },
23
- * { key: 'tab2', label: 'Tab 2', content: <><h1>Second tab</h1><p>Content of the second tab</p></> },
24
- * { key: 'tab3', label: 'Tab 3', content: <><h1>Third tab</h1><p>Content of the third tab</p></> },
25
- * ], [])
26
- *
27
- * return <Tabs tabs={tabs} />
28
- * ```
29
- */
30
- export const Tabs = withRef(
31
- function Tabs<Key extends string>({ tabs, value, equallySized, onChange, controller: ctrl, className, ...props }: TabsProps<Key>) {
32
- const controller = useMemo(() => ctrl ?? new TabController<Key>(tabs.map(t => t.key), value || tabs[0]?.key), [])
33
- const t = useTranslate(dictionary)
34
- const [selectedIndex, setSelectedIndex] = useState(findSelectedIndex(tabs, controller.getValue()))
35
-
36
- useEffect(() => {
37
- if (value) controller.setValue(value)
38
- }, [value])
39
-
40
- useEffect(() => controller.onChange((v) => {
41
- setSelectedIndex(findSelectedIndex(tabs, v))
42
- onChange?.(v)
43
- }), [tabs])
44
-
45
- const nav = useMemo(
46
- () => tabs.map(({ key, label, disabled }, index) => (
47
- <label key={key}>
48
- <input type="radio" role="tab" checked={index === selectedIndex} onChange={() => controller.setValue(key)} disabled={disabled} />
49
- {label || key}
50
- </label>
51
- )),
52
- [tabs, selectedIndex],
53
- )
54
-
55
- return (
56
- <ctx.Provider value={controller}>
57
- <CitricComponent tag="div" component="tabs" className={listToClass([className, equallySized && 'equally-sized'])} {...props}>
58
- <nav>{nav}</nav>
59
- <section>
60
- <ErrorBoundary key={selectedIndex} message={t.error}>
61
- <Suspense fallback={<Center style={{ padding: '20px' }}><ProgressCircular /></Center>}>
62
- {selectedIndex === -1 ? null : tabs[selectedIndex]?.content}
63
- </Suspense>
64
- </ErrorBoundary>
65
- </section>
66
- </CitricComponent>
67
- </ctx.Provider>
68
- )
69
- },
70
- )
71
-
72
- /**
73
- * Request the tab controller of the current context. Use this to control the tabs in the parent components. This returns undefined when
74
- * no tab context is found.
75
- */
76
- export function useTabController<Key extends string = string>(): TabController<Key> | undefined {
77
- return useContext(ctx)
78
- }
79
-
80
- const dictionary = {
81
- en: {
82
- error: 'Error while loading the tab.',
83
- },
84
- pt: {
85
- error: 'Ocorreu um erro ao carregar a aba.',
86
- },
87
- } satisfies Dictionary
1
+ import { listToClass } from '@stack-spot/portal-theme'
2
+ import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
3
+ import { createContext, Suspense, useContext, useEffect, useMemo, useState } from 'react'
4
+ import { withRef } from '../../utils/react'
5
+ import { CitricComponent } from '../CitricComponent'
6
+ import { ErrorBoundary } from '../ErrorBoundary'
7
+ import { ProgressCircular } from '../ProgressCircular'
8
+ import { Center } from '../layout'
9
+ import { TabController } from './TabController'
10
+ import { TabsProps } from './types'
11
+ import { findSelectedIndex } from './utils'
12
+
13
+ const ctx = createContext<TabController<any> | undefined>(undefined)
14
+
15
+ /**
16
+ * Builds a Tab selector. The content of a tab is a React component and it can suspend, i.e. tabs can be asynchronously loaded.
17
+ *
18
+ * @example
19
+ *
20
+ * ```
21
+ * const tabs: Tab[] = useMemo(() => [
22
+ * { key: 'tab1', label: 'Tab 1', content: <><h1>First tab</h1><p>Content of the first tab</p></> },
23
+ * { key: 'tab2', label: 'Tab 2', content: <><h1>Second tab</h1><p>Content of the second tab</p></> },
24
+ * { key: 'tab3', label: 'Tab 3', content: <><h1>Third tab</h1><p>Content of the third tab</p></> },
25
+ * ], [])
26
+ *
27
+ * return <Tabs tabs={tabs} />
28
+ * ```
29
+ */
30
+ export const Tabs = withRef(
31
+ function Tabs<Key extends string>({ tabs, value, equallySized, onChange, controller: ctrl, className, ...props }: TabsProps<Key>) {
32
+ const controller = useMemo(() => ctrl ?? new TabController<Key>(tabs.map(t => t.key), value || tabs[0]?.key), [])
33
+ const t = useTranslate(dictionary)
34
+ const [selectedIndex, setSelectedIndex] = useState(findSelectedIndex(tabs, controller.getValue()))
35
+
36
+ useEffect(() => {
37
+ if (value) controller.setValue(value)
38
+ }, [value])
39
+
40
+ useEffect(() => controller.onChange((v) => {
41
+ setSelectedIndex(findSelectedIndex(tabs, v))
42
+ onChange?.(v)
43
+ }), [tabs])
44
+
45
+ const nav = useMemo(
46
+ () => tabs.map(({ key, label, disabled }, index) => (
47
+ <label key={key}>
48
+ <input type="radio" role="tab" checked={index === selectedIndex} onChange={() => controller.setValue(key)} disabled={disabled} />
49
+ {label || key}
50
+ </label>
51
+ )),
52
+ [tabs, selectedIndex],
53
+ )
54
+
55
+ return (
56
+ <ctx.Provider value={controller}>
57
+ <CitricComponent tag="div" component="tabs" className={listToClass([className, equallySized && 'equally-sized'])} {...props}>
58
+ <nav>{nav}</nav>
59
+ <section>
60
+ <ErrorBoundary key={selectedIndex} message={t.error}>
61
+ <Suspense fallback={<Center style={{ padding: '20px' }}><ProgressCircular /></Center>}>
62
+ {selectedIndex === -1 ? null : tabs[selectedIndex]?.content}
63
+ </Suspense>
64
+ </ErrorBoundary>
65
+ </section>
66
+ </CitricComponent>
67
+ </ctx.Provider>
68
+ )
69
+ },
70
+ )
71
+
72
+ /**
73
+ * Request the tab controller of the current context. Use this to control the tabs in the parent components. This returns undefined when
74
+ * no tab context is found.
75
+ */
76
+ export function useTabController<Key extends string = string>(): TabController<Key> | undefined {
77
+ return useContext(ctx)
78
+ }
79
+
80
+ const dictionary = {
81
+ en: {
82
+ error: 'Error while loading the tab.',
83
+ },
84
+ pt: {
85
+ error: 'Ocorreu um erro ao carregar a aba.',
86
+ },
87
+ } satisfies Dictionary
@@ -1,54 +1,54 @@
1
- import { WithColorPalette, WithColorScheme } from '../../types'
2
- import { TabController } from './TabController'
3
-
4
- export interface Tab<Key extends string = string> {
5
- /**
6
- * A unique identifier for the tab.
7
- */
8
- key: Key,
9
- /**
10
- * The tab's label. Will be the "key" if not provided.
11
- */
12
- label?: string,
13
- /**
14
- * The tab's content. This can be a suspended component.
15
- *
16
- * Attention: consider using React's lazy loading to render the tab view.
17
- */
18
- content: React.ReactNode,
19
- /**
20
- * Whether or not this tab is disabled.
21
- *
22
- * @default false
23
- */
24
- disabled?: boolean,
25
- }
26
-
27
- export interface BaseTabsProps<Key extends string> extends WithColorScheme, WithColorPalette {
28
- /**
29
- * The tabs to render.
30
- */
31
- tabs: Tab<Key>[],
32
- /**
33
- * The key of the current tab. Use this only if you intend to control the tabs from the outside.
34
- */
35
- value?: Key,
36
- /**
37
- * What to do when the tab changes. Use this only if you intend to control the tabs from the outside.
38
- *
39
- * @param key the key of the selected tab.
40
- */
41
- onChange?: (key: Key) => void,
42
- /**
43
- * A tab-controller, useful if you want to control the tabs outside the component context.
44
- */
45
- controller?: TabController<Key>,
46
- /**
47
- * Instead of each tab occupying only the space it needs, all tabs will have their sizes equally distributed.
48
- *
49
- * @default false
50
- */
51
- equallySized?: boolean,
52
- }
53
-
54
- export type TabsProps<Key extends string> = Omit<React.JSX.IntrinsicElements['div'], 'onChange' | 'children'> & BaseTabsProps<Key>
1
+ import { WithColorPalette, WithColorScheme } from '../../types'
2
+ import { TabController } from './TabController'
3
+
4
+ export interface Tab<Key extends string = string> {
5
+ /**
6
+ * A unique identifier for the tab.
7
+ */
8
+ key: Key,
9
+ /**
10
+ * The tab's label. Will be the "key" if not provided.
11
+ */
12
+ label?: string,
13
+ /**
14
+ * The tab's content. This can be a suspended component.
15
+ *
16
+ * Attention: consider using React's lazy loading to render the tab view.
17
+ */
18
+ content: React.ReactNode,
19
+ /**
20
+ * Whether or not this tab is disabled.
21
+ *
22
+ * @default false
23
+ */
24
+ disabled?: boolean,
25
+ }
26
+
27
+ export interface BaseTabsProps<Key extends string> extends WithColorScheme, WithColorPalette {
28
+ /**
29
+ * The tabs to render.
30
+ */
31
+ tabs: Tab<Key>[],
32
+ /**
33
+ * The key of the current tab. Use this only if you intend to control the tabs from the outside.
34
+ */
35
+ value?: Key,
36
+ /**
37
+ * What to do when the tab changes. Use this only if you intend to control the tabs from the outside.
38
+ *
39
+ * @param key the key of the selected tab.
40
+ */
41
+ onChange?: (key: Key) => void,
42
+ /**
43
+ * A tab-controller, useful if you want to control the tabs outside the component context.
44
+ */
45
+ controller?: TabController<Key>,
46
+ /**
47
+ * Instead of each tab occupying only the space it needs, all tabs will have their sizes equally distributed.
48
+ *
49
+ * @default false
50
+ */
51
+ equallySized?: boolean,
52
+ }
53
+
54
+ export type TabsProps<Key extends string> = Omit<React.JSX.IntrinsicElements['div'], 'onChange' | 'children'> & BaseTabsProps<Key>
@@ -1,6 +1,6 @@
1
- import { Tab } from './types'
2
-
3
- export function findSelectedIndex<Key extends string>(tabs: Tab<Key>[], selectedTabKey: Key) {
4
- const index = tabs.findIndex(t => t.key === selectedTabKey)
5
- return index === -1 ? 0 : index
6
- }
1
+ import { Tab } from './types'
2
+
3
+ export function findSelectedIndex<Key extends string>(tabs: Tab<Key>[], selectedTabKey: Key) {
4
+ const index = tabs.findIndex(t => t.key === selectedTabKey)
5
+ return index === -1 ? 0 : index
6
+ }
@@ -1,111 +1,111 @@
1
- import { listToClass } from '@stack-spot/portal-theme'
2
- import { createElement } from 'react'
3
- import { HTMLTag, TextAppearance, WithColor } from '../types'
4
- import { applyColor, applyTextAppearance } from '../utils/css'
5
- import { withRef } from '../utils/react'
6
-
7
- type SupportedTags = 'span' | 'small' | 'p' | `h${1|2|3|4|5|6}` | 'pre'
8
-
9
- export interface BaseTextProps<T extends SupportedTags = SupportedTags> extends WithColor {
10
- /**
11
- * If "tag" is not defined, it will be based on the value of "appearance".
12
- * If neither "appearance" or "tag" are defined, the tag will be "p".
13
- */
14
- tag?: T,
15
- /**
16
- * If "appearance" is not defined, it will be based on the value of "tag".
17
- * If neither "appearance" or "tag" are defined, the appearance will be inherited from the parent HTML element.
18
- */
19
- appearance?: TextAppearance,
20
- /**
21
- * Add default margins to the text.
22
- *
23
- * @default false
24
- */
25
- showMargins?: boolean,
26
- /**
27
- * Shortcut to `style.fontWeight`.
28
- */
29
- weight?: React.CSSProperties['fontWeight'],
30
- /**
31
- * Shortcut to `style.textAlign`.
32
- */
33
- align?: React.CSSProperties['textAlign'],
34
- /**
35
- * Shortcut to `style.whiteSpace = 'nowrap'; style.overflow = 'hidden'; style.textOverflow = 'ellipsis'`.
36
- */
37
- nowrapEllipsis?: boolean,
38
- }
39
-
40
- export type TextProps<T extends SupportedTags> = HTMLTag[T] & BaseTextProps<T>
41
-
42
- const tagToAppearance: Record<SupportedTags, TextAppearance | undefined> = {
43
- h1: 'h1',
44
- h2: 'h2',
45
- h3: 'h3',
46
- h4: 'h4',
47
- h5: 'h5',
48
- h6: 'h6',
49
- span: undefined,
50
- small: 'microtext1',
51
- p: 'body2',
52
- pre: 'code2',
53
- }
54
-
55
- const appearanceToTag: Record<TextAppearance, SupportedTags> = {
56
- h1: 'h1',
57
- h2: 'h2',
58
- h3: 'h3',
59
- h4: 'h4',
60
- h5: 'h5',
61
- h6: 'h6',
62
- body1: 'p',
63
- body2: 'p',
64
- code1: 'pre',
65
- code2: 'pre',
66
- display1: 'h1',
67
- microtext1: 'small',
68
- overheader1: 'p',
69
- overheader2: 'p',
70
- subtitle1: 'p',
71
- subtitle2: 'p',
72
- subtitle3: 'p',
73
- subtitle4: 'p',
74
- }
75
-
76
- /**
77
- * Renders a text. The tag can be set by the property "tag". If unset, the tag rendered will be based on the property "appearance". If
78
- * "appearance" is also unset, the tag "p" is rendered.
79
- *
80
- * Texts have no margin by default, to enable margins, use `showMargins = true`.
81
- *
82
- * If the appearance is not set, it will be inherited from the parent.
83
- *
84
- * A font can be applied to a text without this component, just use `{ font: theme.font.$textAppearance }` in your style.
85
- *
86
- * @example
87
- * ```
88
- * <Text appearance="body2">Hello World!</Text>
89
- * ```
90
- */
91
- export const Text = withRef(
92
- function Text<T extends SupportedTags>(
93
- { tag, appearance, color, showMargins, weight, align, nowrapEllipsis, style, className, children, ...props }: TextProps<T>,
94
- ) {
95
- const renderedTag = tag || appearanceToTag[appearance || 'body2']
96
- const renderedAppearance = appearance || (tag ? tagToAppearance[tag] : undefined)
97
- if (!appearance && !showMargins) style = { margin: 0, ...style }
98
- if (weight) style = { fontWeight: weight, ...style }
99
- if (align) style = { textAlign: align, ...style }
100
- if (nowrapEllipsis) style = { whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', ...style }
101
- return createElement(
102
- renderedTag,
103
- {
104
- className: applyTextAppearance(listToClass([className, showMargins && 'text-with-margins']), renderedAppearance),
105
- style: applyColor(style, color),
106
- ...props,
107
- },
108
- children,
109
- )
110
- },
111
- )
1
+ import { listToClass } from '@stack-spot/portal-theme'
2
+ import { createElement } from 'react'
3
+ import { HTMLTag, TextAppearance, WithColor } from '../types'
4
+ import { applyColor, applyTextAppearance } from '../utils/css'
5
+ import { withRef } from '../utils/react'
6
+
7
+ type SupportedTags = 'span' | 'small' | 'p' | `h${1|2|3|4|5|6}` | 'pre'
8
+
9
+ export interface BaseTextProps<T extends SupportedTags = SupportedTags> extends WithColor {
10
+ /**
11
+ * If "tag" is not defined, it will be based on the value of "appearance".
12
+ * If neither "appearance" or "tag" are defined, the tag will be "p".
13
+ */
14
+ tag?: T,
15
+ /**
16
+ * If "appearance" is not defined, it will be based on the value of "tag".
17
+ * If neither "appearance" or "tag" are defined, the appearance will be inherited from the parent HTML element.
18
+ */
19
+ appearance?: TextAppearance,
20
+ /**
21
+ * Add default margins to the text.
22
+ *
23
+ * @default false
24
+ */
25
+ showMargins?: boolean,
26
+ /**
27
+ * Shortcut to `style.fontWeight`.
28
+ */
29
+ weight?: React.CSSProperties['fontWeight'],
30
+ /**
31
+ * Shortcut to `style.textAlign`.
32
+ */
33
+ align?: React.CSSProperties['textAlign'],
34
+ /**
35
+ * Shortcut to `style.whiteSpace = 'nowrap'; style.overflow = 'hidden'; style.textOverflow = 'ellipsis'`.
36
+ */
37
+ nowrapEllipsis?: boolean,
38
+ }
39
+
40
+ export type TextProps<T extends SupportedTags> = HTMLTag[T] & BaseTextProps<T>
41
+
42
+ const tagToAppearance: Record<SupportedTags, TextAppearance | undefined> = {
43
+ h1: 'h1',
44
+ h2: 'h2',
45
+ h3: 'h3',
46
+ h4: 'h4',
47
+ h5: 'h5',
48
+ h6: 'h6',
49
+ span: undefined,
50
+ small: 'microtext1',
51
+ p: 'body2',
52
+ pre: 'code2',
53
+ }
54
+
55
+ const appearanceToTag: Record<TextAppearance, SupportedTags> = {
56
+ h1: 'h1',
57
+ h2: 'h2',
58
+ h3: 'h3',
59
+ h4: 'h4',
60
+ h5: 'h5',
61
+ h6: 'h6',
62
+ body1: 'p',
63
+ body2: 'p',
64
+ code1: 'pre',
65
+ code2: 'pre',
66
+ display1: 'h1',
67
+ microtext1: 'small',
68
+ overheader1: 'p',
69
+ overheader2: 'p',
70
+ subtitle1: 'p',
71
+ subtitle2: 'p',
72
+ subtitle3: 'p',
73
+ subtitle4: 'p',
74
+ }
75
+
76
+ /**
77
+ * Renders a text. The tag can be set by the property "tag". If unset, the tag rendered will be based on the property "appearance". If
78
+ * "appearance" is also unset, the tag "p" is rendered.
79
+ *
80
+ * Texts have no margin by default, to enable margins, use `showMargins = true`.
81
+ *
82
+ * If the appearance is not set, it will be inherited from the parent.
83
+ *
84
+ * A font can be applied to a text without this component, just use `{ font: theme.font.$textAppearance }` in your style.
85
+ *
86
+ * @example
87
+ * ```
88
+ * <Text appearance="body2">Hello World!</Text>
89
+ * ```
90
+ */
91
+ export const Text = withRef(
92
+ function Text<T extends SupportedTags>(
93
+ { tag, appearance, color, showMargins, weight, align, nowrapEllipsis, style, className, children, ...props }: TextProps<T>,
94
+ ) {
95
+ const renderedTag = tag || appearanceToTag[appearance || 'body2']
96
+ const renderedAppearance = appearance || (tag ? tagToAppearance[tag] : undefined)
97
+ if (!appearance && !showMargins) style = { margin: 0, ...style }
98
+ if (weight) style = { fontWeight: weight, ...style }
99
+ if (align) style = { textAlign: align, ...style }
100
+ if (nowrapEllipsis) style = { whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', ...style }
101
+ return createElement(
102
+ renderedTag,
103
+ {
104
+ className: applyTextAppearance(listToClass([className, showMargins && 'text-with-margins']), renderedAppearance),
105
+ style: applyColor(style, color),
106
+ ...props,
107
+ },
108
+ children,
109
+ )
110
+ },
111
+ )
@@ -1,27 +1,27 @@
1
- import React from 'react'
2
- import { ControlledTextarea, WithColorScheme } from '../types'
3
- import { withRef } from '../utils/react'
4
- import { CitricComponent } from './CitricComponent'
5
-
6
- export interface BaseTextareaProps extends WithColorScheme {
7
- value?: string,
8
- onChange?: (value: string) => void,
9
- ref?: React.MutableRefObject<HTMLTextAreaElement | null>,
10
- }
11
-
12
- export type TextareaProps = ControlledTextarea & BaseTextareaProps
13
-
14
- /**
15
- * Renders a textarea HTML element. With the difference that the value is not determined by the children, but the property "value" instead.
16
- *
17
- * Attention: "onChange" receives the new value, not the event.
18
- *
19
- * @example
20
- * ```
21
- * const [value, setValue] = useState('')
22
- * return <Textarea value={value} onChange={setValue} />
23
- * ```
24
- */
25
- export const Textarea = withRef(({ value, onChange, ...props }: TextareaProps) =>
26
- <CitricComponent tag="textarea" component="textarea" value={value} onChange={e => onChange?.(e.target.value)} {...props} />,
27
- )
1
+ import React from 'react'
2
+ import { ControlledTextarea, WithColorScheme } from '../types'
3
+ import { withRef } from '../utils/react'
4
+ import { CitricComponent } from './CitricComponent'
5
+
6
+ export interface BaseTextareaProps extends WithColorScheme {
7
+ value?: string,
8
+ onChange?: (value: string) => void,
9
+ ref?: React.MutableRefObject<HTMLTextAreaElement | null>,
10
+ }
11
+
12
+ export type TextareaProps = ControlledTextarea & BaseTextareaProps
13
+
14
+ /**
15
+ * Renders a textarea HTML element. With the difference that the value is not determined by the children, but the property "value" instead.
16
+ *
17
+ * Attention: "onChange" receives the new value, not the event.
18
+ *
19
+ * @example
20
+ * ```
21
+ * const [value, setValue] = useState('')
22
+ * return <Textarea value={value} onChange={setValue} />
23
+ * ```
24
+ */
25
+ export const Textarea = withRef(({ value, onChange, ...props }: TextareaProps) =>
26
+ <CitricComponent tag="textarea" component="textarea" value={value} onChange={e => onChange?.(e.target.value)} {...props} />,
27
+ )