@stack-spot/citric-react 0.42.0-beta.0 → 0.42.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 (208) hide show
  1. package/CHANGELOG.md +13 -13
  2. package/dist/citric.css +2849 -3081
  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.d.ts.map +1 -1
  27. package/dist/components/Checkbox.js +2 -2
  28. package/dist/components/Checkbox.js.map +1 -1
  29. package/dist/components/CheckboxGroup.d.ts +1 -1
  30. package/dist/components/CheckboxGroup.js +1 -1
  31. package/dist/components/Circle.d.ts +1 -1
  32. package/dist/components/Circle.js +1 -1
  33. package/dist/components/CitricComponent.d.ts +1 -1
  34. package/dist/components/CitricComponent.d.ts.map +1 -1
  35. package/dist/components/Divider.d.ts +1 -1
  36. package/dist/components/Divider.js +1 -1
  37. package/dist/components/ErrorBoundary.d.ts +1 -1
  38. package/dist/components/ErrorBoundary.js +1 -1
  39. package/dist/components/ErrorMessage.d.ts +1 -1
  40. package/dist/components/ErrorMessage.js +1 -1
  41. package/dist/components/FallbackBoundary.d.ts +1 -1
  42. package/dist/components/FallbackBoundary.js +1 -1
  43. package/dist/components/Favorite.d.ts +1 -1
  44. package/dist/components/Favorite.js +1 -1
  45. package/dist/components/FieldGroup.d.ts +1 -1
  46. package/dist/components/FieldGroup.js +1 -1
  47. package/dist/components/Form.d.ts +2 -2
  48. package/dist/components/Form.js +1 -1
  49. package/dist/components/FormGroup.d.ts +1 -1
  50. package/dist/components/FormGroup.js +1 -1
  51. package/dist/components/Icon.d.ts +1 -1
  52. package/dist/components/Icon.js +1 -1
  53. package/dist/components/IconBox.d.ts +3 -3
  54. package/dist/components/IconBox.js +1 -1
  55. package/dist/components/ImageBox.d.ts +3 -3
  56. package/dist/components/ImageBox.js +1 -1
  57. package/dist/components/ImageWithFallback.d.ts +1 -1
  58. package/dist/components/ImageWithFallback.js +1 -1
  59. package/dist/components/Input.d.ts +1 -1
  60. package/dist/components/Input.js +1 -1
  61. package/dist/components/Link.d.ts +1 -1
  62. package/dist/components/Link.js +1 -1
  63. package/dist/components/LoadingPanel.d.ts +1 -1
  64. package/dist/components/LoadingPanel.js +1 -1
  65. package/dist/components/MenuOverlay/Menu.d.ts +1 -1
  66. package/dist/components/MenuOverlay/Menu.js +1 -1
  67. package/dist/components/MenuOverlay/index.d.ts +1 -1
  68. package/dist/components/MenuOverlay/index.js +1 -1
  69. package/dist/components/Overlay/index.d.ts +1 -1
  70. package/dist/components/Overlay/index.js +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.js +1 -1
  79. package/dist/components/Rating.d.ts +1 -1
  80. package/dist/components/Rating.js +1 -1
  81. package/dist/components/Select/MultiSelect.d.ts +1 -1
  82. package/dist/components/Select/MultiSelect.js +1 -1
  83. package/dist/components/Select/RichSelect.d.ts +1 -1
  84. package/dist/components/Select/RichSelect.js +1 -1
  85. package/dist/components/Select/SimpleSelect.d.ts +1 -1
  86. package/dist/components/Select/SimpleSelect.js +1 -1
  87. package/dist/components/Select/index.d.ts +1 -1
  88. package/dist/components/Select/index.js +1 -1
  89. package/dist/components/SelectBox.d.ts +9 -1
  90. package/dist/components/SelectBox.d.ts.map +1 -1
  91. package/dist/components/SelectBox.js +6 -5
  92. package/dist/components/SelectBox.js.map +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/index.d.ts +1 -1
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +1 -1
  114. package/dist/index.js.map +1 -1
  115. package/dist/overlay.js +1 -1
  116. package/dist/theme.css +415 -415
  117. package/dist/utils/css.js +1 -1
  118. package/dist/utils/css.js.map +1 -1
  119. package/package.json +1 -1
  120. package/scripts/build-css.ts +49 -49
  121. package/src/components/Accordion.tsx +130 -130
  122. package/src/components/Alert.tsx +24 -24
  123. package/src/components/AsyncContent.tsx +75 -75
  124. package/src/components/Avatar.tsx +45 -45
  125. package/src/components/AvatarGroup.tsx +49 -49
  126. package/src/components/Badge.tsx +47 -47
  127. package/src/components/Blockquote.tsx +18 -18
  128. package/src/components/Breadcrumb.tsx +33 -33
  129. package/src/components/Button.tsx +105 -105
  130. package/src/components/ButtonLink.tsx +45 -45
  131. package/src/components/Card.tsx +68 -68
  132. package/src/components/Checkbox.tsx +51 -52
  133. package/src/components/CheckboxGroup.tsx +153 -153
  134. package/src/components/Circle.tsx +43 -43
  135. package/src/components/CitricComponent.ts +47 -47
  136. package/src/components/Divider.tsx +24 -24
  137. package/src/components/ErrorBoundary.tsx +75 -75
  138. package/src/components/ErrorMessage.tsx +11 -11
  139. package/src/components/FallbackBoundary.tsx +40 -40
  140. package/src/components/Favorite.tsx +57 -57
  141. package/src/components/FieldGroup.tsx +46 -46
  142. package/src/components/Form.tsx +36 -36
  143. package/src/components/FormGroup.tsx +57 -57
  144. package/src/components/Icon.tsx +35 -35
  145. package/src/components/IconBox.tsx +134 -134
  146. package/src/components/ImageBox.tsx +125 -125
  147. package/src/components/ImageWithFallback.tsx +65 -65
  148. package/src/components/Input.tsx +49 -49
  149. package/src/components/Link.tsx +55 -55
  150. package/src/components/LoadingPanel.tsx +12 -12
  151. package/src/components/MenuOverlay/Menu.tsx +158 -158
  152. package/src/components/MenuOverlay/context.ts +20 -20
  153. package/src/components/MenuOverlay/index.tsx +55 -55
  154. package/src/components/MenuOverlay/keyboard.ts +60 -60
  155. package/src/components/MenuOverlay/types.ts +171 -171
  156. package/src/components/Overlay/context.ts +10 -10
  157. package/src/components/Overlay/index.tsx +182 -182
  158. package/src/components/Overlay/types.ts +75 -75
  159. package/src/components/Pagination.tsx +133 -133
  160. package/src/components/ProgressBar.tsx +45 -45
  161. package/src/components/ProgressCircular.tsx +45 -45
  162. package/src/components/RadioGroup.tsx +147 -147
  163. package/src/components/Rating.tsx +98 -98
  164. package/src/components/Select/MultiSelect.tsx +217 -217
  165. package/src/components/Select/RichSelect.tsx +128 -128
  166. package/src/components/Select/SimpleSelect.tsx +73 -73
  167. package/src/components/Select/hooks.ts +133 -133
  168. package/src/components/Select/index.tsx +35 -35
  169. package/src/components/Select/types.ts +134 -134
  170. package/src/components/SelectBox.tsx +181 -167
  171. package/src/components/Skeleton.tsx +53 -53
  172. package/src/components/Slider.tsx +89 -89
  173. package/src/components/SmartTable.tsx +227 -227
  174. package/src/components/Stepper.tsx +163 -163
  175. package/src/components/Table.tsx +234 -234
  176. package/src/components/Tabs/TabController.ts +54 -54
  177. package/src/components/Tabs/index.tsx +106 -106
  178. package/src/components/Tabs/types.ts +67 -67
  179. package/src/components/Tabs/utils.ts +6 -6
  180. package/src/components/Text.ts +111 -111
  181. package/src/components/Textarea.tsx +27 -27
  182. package/src/components/Tooltip.tsx +83 -83
  183. package/src/components/layout.tsx +101 -101
  184. package/src/context/CitricContext.tsx +4 -4
  185. package/src/context/CitricProvider.tsx +14 -14
  186. package/src/context/hooks.ts +6 -6
  187. package/src/index.ts +58 -59
  188. package/src/overlay.ts +348 -348
  189. package/src/types.ts +235 -235
  190. package/src/utils/ValueController.ts +28 -28
  191. package/src/utils/acessibility.ts +92 -92
  192. package/src/utils/checkbox.ts +121 -121
  193. package/src/utils/css.ts +119 -119
  194. package/src/utils/options.ts +9 -9
  195. package/src/utils/radio.ts +93 -93
  196. package/src/utils/react.ts +6 -6
  197. package/src/utils/time.ts +5 -5
  198. package/tsconfig.json +10 -10
  199. package/dist/components/Autocomplete/Autocomplete.d.ts +0 -211
  200. package/dist/components/Autocomplete/Autocomplete.d.ts.map +0 -1
  201. package/dist/components/Autocomplete/Autocomplete.js +0 -409
  202. package/dist/components/Autocomplete/Autocomplete.js.map +0 -1
  203. package/dist/components/Autocomplete/index.d.ts +0 -3
  204. package/dist/components/Autocomplete/index.d.ts.map +0 -1
  205. package/dist/components/Autocomplete/index.js +0 -2
  206. package/dist/components/Autocomplete/index.js.map +0 -1
  207. package/src/components/Autocomplete/Autocomplete.tsx +0 -794
  208. package/src/components/Autocomplete/index.ts +0 -3
@@ -1,106 +1,106 @@
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>(
32
- { tabs, value, equallySized, onChange, controller: ctrl, appearance, customRenderer, className, ...props }: TabsProps<Key>,
33
- ) {
34
- const controller = useMemo(() => ctrl ?? new TabController<Key>(tabs.map(t => t.key), value || tabs[0]?.key), [])
35
- const t = useTranslate(dictionary)
36
- const [selectedIndex, setSelectedIndex] = useState(findSelectedIndex(tabs, controller.getValue()))
37
-
38
- useEffect(() => {
39
- if (value) controller.setValue(value)
40
- }, [value])
41
-
42
- useEffect(() => controller.onChange((v) => {
43
- setSelectedIndex(findSelectedIndex(tabs, v))
44
- onChange?.(v)
45
- }), [tabs])
46
-
47
- const tabSelector = useMemo(
48
- () => (
49
- <nav className="tab-selector">
50
- {tabs.map(({ key, label, disabled }, index) => (
51
- <label key={key}>
52
- <input
53
- type="radio"
54
- role="tab"
55
- checked={index === selectedIndex}
56
- onChange={() => controller.setValue(key)} disabled={disabled}
57
- />
58
- {label || key}
59
- </label>
60
- ))}
61
- </nav>
62
- ),
63
- [tabs, selectedIndex],
64
- )
65
-
66
- const content = useMemo(() => (
67
- <section className="tab-content">
68
- <ErrorBoundary key={selectedIndex} message={t.error}>
69
- <Suspense fallback={<Center style={{ padding: '20px' }}><ProgressCircular /></Center>}>
70
- {selectedIndex === -1 ? null : tabs[selectedIndex]?.content}
71
- </Suspense>
72
- </ErrorBoundary>
73
- </section>
74
- ), [selectedIndex, t])
75
-
76
- return (
77
- <ctx.Provider value={controller}>
78
- <CitricComponent
79
- tag="div"
80
- component="tabs"
81
- className={listToClass([className, equallySized && 'equally-sized', appearance])}
82
- {...props}
83
- >
84
- {customRenderer ? customRenderer(tabSelector, content) : <>{tabSelector}{content}</>}
85
- </CitricComponent>
86
- </ctx.Provider>
87
- )
88
- },
89
- )
90
-
91
- /**
92
- * Request the tab controller of the current context. Use this to control the tabs in the parent components. This returns undefined when
93
- * no tab context is found.
94
- */
95
- export function useTabController<Key extends string = string>(): TabController<Key> | undefined {
96
- return useContext(ctx)
97
- }
98
-
99
- const dictionary = {
100
- en: {
101
- error: 'Error while loading the tab.',
102
- },
103
- pt: {
104
- error: 'Ocorreu um erro ao carregar a aba.',
105
- },
106
- } 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>(
32
+ { tabs, value, equallySized, onChange, controller: ctrl, appearance, customRenderer, className, ...props }: TabsProps<Key>,
33
+ ) {
34
+ const controller = useMemo(() => ctrl ?? new TabController<Key>(tabs.map(t => t.key), value || tabs[0]?.key), [])
35
+ const t = useTranslate(dictionary)
36
+ const [selectedIndex, setSelectedIndex] = useState(findSelectedIndex(tabs, controller.getValue()))
37
+
38
+ useEffect(() => {
39
+ if (value) controller.setValue(value)
40
+ }, [value])
41
+
42
+ useEffect(() => controller.onChange((v) => {
43
+ setSelectedIndex(findSelectedIndex(tabs, v))
44
+ onChange?.(v)
45
+ }), [tabs])
46
+
47
+ const tabSelector = useMemo(
48
+ () => (
49
+ <nav className="tab-selector">
50
+ {tabs.map(({ key, label, disabled }, index) => (
51
+ <label key={key}>
52
+ <input
53
+ type="radio"
54
+ role="tab"
55
+ checked={index === selectedIndex}
56
+ onChange={() => controller.setValue(key)} disabled={disabled}
57
+ />
58
+ {label || key}
59
+ </label>
60
+ ))}
61
+ </nav>
62
+ ),
63
+ [tabs, selectedIndex],
64
+ )
65
+
66
+ const content = useMemo(() => (
67
+ <section className="tab-content">
68
+ <ErrorBoundary key={selectedIndex} message={t.error}>
69
+ <Suspense fallback={<Center style={{ padding: '20px' }}><ProgressCircular /></Center>}>
70
+ {selectedIndex === -1 ? null : tabs[selectedIndex]?.content}
71
+ </Suspense>
72
+ </ErrorBoundary>
73
+ </section>
74
+ ), [selectedIndex, t])
75
+
76
+ return (
77
+ <ctx.Provider value={controller}>
78
+ <CitricComponent
79
+ tag="div"
80
+ component="tabs"
81
+ className={listToClass([className, equallySized && 'equally-sized', appearance])}
82
+ {...props}
83
+ >
84
+ {customRenderer ? customRenderer(tabSelector, content) : <>{tabSelector}{content}</>}
85
+ </CitricComponent>
86
+ </ctx.Provider>
87
+ )
88
+ },
89
+ )
90
+
91
+ /**
92
+ * Request the tab controller of the current context. Use this to control the tabs in the parent components. This returns undefined when
93
+ * no tab context is found.
94
+ */
95
+ export function useTabController<Key extends string = string>(): TabController<Key> | undefined {
96
+ return useContext(ctx)
97
+ }
98
+
99
+ const dictionary = {
100
+ en: {
101
+ error: 'Error while loading the tab.',
102
+ },
103
+ pt: {
104
+ error: 'Ocorreu um erro ao carregar a aba.',
105
+ },
106
+ } satisfies Dictionary
@@ -1,67 +1,67 @@
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
- * The appearance of Tabs.
54
- *
55
- * @default 'tabs'
56
- */
57
- appearance?: 'tabs' | 'toggles',
58
- /**
59
- * Allows the use of the tabs component with other elements in the middle of its UI.
60
- * @param tabSelector the UI for changing the current tab.
61
- * @param content the content of the selected tab.
62
- * @returns the customized UI.
63
- */
64
- customRenderer?: (tabSelector: React.ReactElement, content: React.ReactElement) => React.ReactNode,
65
- }
66
-
67
- 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
+ * The appearance of Tabs.
54
+ *
55
+ * @default 'tabs'
56
+ */
57
+ appearance?: 'tabs' | 'toggles',
58
+ /**
59
+ * Allows the use of the tabs component with other elements in the middle of its UI.
60
+ * @param tabSelector the UI for changing the current tab.
61
+ * @param content the content of the selected tab.
62
+ * @returns the customized UI.
63
+ */
64
+ customRenderer?: (tabSelector: React.ReactElement, content: React.ReactElement) => React.ReactNode,
65
+ }
66
+
67
+ 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
+ )