@startupjs-ui/mdx 0.1.3

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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ## [0.1.3](https://github.com/startupjs/startupjs-ui/compare/v0.1.2...v0.1.3) (2025-12-29)
7
+
8
+ **Note:** Version bump only for package @startupjs-ui/mdx
9
+
10
+
11
+
12
+
13
+
14
+ ## [0.1.2](https://github.com/startupjs/startupjs-ui/compare/v0.1.1...v0.1.2) (2025-12-29)
15
+
16
+
17
+ ### Features
18
+
19
+ * add mdx and docs packages. Refactor docs to get rid of any @startupjs/ui usage and use startupjs-ui instead ([703c926](https://github.com/startupjs/startupjs-ui/commit/703c92636efb0421ffd11783f692fc892b74018f))
package/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # MDX components
2
+
3
+ > Components to use during .mdx compilation
4
+
5
+ ## Installation
6
+
7
+ ```sh
8
+ yarn @startupjs-ui/mdx @react-native-clipboard/clipboard
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ This will be used automatically by `@startupjs/bundler` to compile `.mdx` and `.md` files.
14
+
15
+ ## Custom components
16
+
17
+ You can override the default MDX components by setting the custom ones
18
+ using the `overrideMDXComponents` function. Do it once as early as possible
19
+ (for example in the topmost `_layout` file of your Expo project):
20
+
21
+ ```jsx
22
+ // _layout.js
23
+ import { overrideMDXComponents } from '@startupjs/mdx'
24
+
25
+ overrideMDXComponents({
26
+ h1: ({ children }) => <Text style={{ fontSize: 40 }}>{children}</Text>,
27
+ p: ({ children }) => <Text style={{ fontSize: 14 }}>{children}</Text>
28
+ })
29
+ ```
30
+
31
+ For the full list of components check [here](https://mdxjs.com/table-of-components)
32
+
33
+ ## License
34
+
35
+ MIT
@@ -0,0 +1,144 @@
1
+ import React, { useMemo, memo } from 'react'
2
+ import { pug } from 'startupjs'
3
+ import Div from '@startupjs-ui/div'
4
+ import Span from '@startupjs-ui/span'
5
+ import ScrollView from '@startupjs-ui/scroll-view'
6
+ import refractor from 'refractor/core.js'
7
+ // Supported languages
8
+ import languageJsx from 'refractor/lang/jsx.js'
9
+ import languageStyl from 'refractor/lang/stylus.js'
10
+ import languagePug from 'refractor/lang/pug.js'
11
+ import languageMarkdown from 'refractor/lang/markdown.js'
12
+ import languageJson from 'refractor/lang/json.js'
13
+ import languageBash from 'refractor/lang/bash.js'
14
+ import './index.styl'
15
+
16
+ const SUB_LANGUAGE_REGEX = /(^|\W)(pug|styl|css)(`\s*\n)([^`]*\s*\n)(`)/
17
+
18
+ // Register all supported languages
19
+ refractor.register(languageJsx)
20
+ refractor.register(languageStyl)
21
+ refractor.register(languagePug)
22
+ refractor.register(languageMarkdown)
23
+ refractor.register(languageJson)
24
+ refractor.register(languageBash)
25
+
26
+ // Register aliases
27
+ refractor.alias({ stylus: ['styl'] })
28
+ refractor.alias({ bash: ['sh'] })
29
+
30
+ // This method mutates highlighted array to remove the last template
31
+ // backtick symbol and also returns it
32
+ function modifyAndGetLastBacktick (highlighted) {
33
+ if (!(highlighted && highlighted.length)) return []
34
+ const lastLine = highlighted[highlighted.length - 1]
35
+ const lastSymbol = lastLine.children[lastLine.children.length - 1]
36
+
37
+ // check close backtick
38
+ if (lastSymbol?.value !== '`') {
39
+ throw new Error(`
40
+ [@startupjs/mdx] Last symbol is not a backtick.
41
+ This should never happen.
42
+ Maybe refractor got updated or <Code> component is broken.
43
+ `)
44
+ }
45
+
46
+ // remove last line with backtick
47
+ highlighted.pop()
48
+
49
+ return {
50
+ type: 'element',
51
+ tagName: 'span',
52
+ properties: { className: ['line'] },
53
+ children: [{ type: 'text', value: '`' }]
54
+ }
55
+ }
56
+
57
+ function getLines (code, language) {
58
+ const lines = code.split('\n')
59
+ if (lines[lines.length - 1] === '') lines.pop()
60
+
61
+ return lines.reduce((acc, line) => {
62
+ const children = refractor.highlight(line, language)
63
+ const className = ['line']
64
+ const node = {
65
+ type: 'element',
66
+ tagName: 'span',
67
+ properties: { className },
68
+ children
69
+ }
70
+
71
+ acc.push(node)
72
+ return acc
73
+ }, [])
74
+ }
75
+
76
+ function highlight (code, language) {
77
+ if (language === 'jsx') {
78
+ const match = code.match(SUB_LANGUAGE_REGEX)
79
+ if (match) {
80
+ const splitIndex = match.index + match[0].length
81
+ const start = code.slice(0, splitIndex)
82
+ const next = code.slice(splitIndex + 1)
83
+
84
+ const jsx = start.replace(SUB_LANGUAGE_REGEX, '$1$2$3$5')
85
+ const highlightedJsx = getLines(jsx, 'jsx')
86
+
87
+ const subLanguageName = match[2]
88
+ const bodySubLanguage = match[4]
89
+ const closingBacktick = modifyAndGetLastBacktick(highlightedJsx)
90
+
91
+ const merge = [
92
+ ...highlightedJsx, // without trailing ` sign
93
+ ...highlight(bodySubLanguage, subLanguageName),
94
+ closingBacktick // the trailing ` sign
95
+ ]
96
+
97
+ if (next) merge.push(...highlight(next, 'jsx'))
98
+ return merge
99
+ }
100
+ }
101
+ return getLines(code, language)
102
+ }
103
+
104
+ export default memo(function Code ({
105
+ children = '',
106
+ language = 'txt',
107
+ style,
108
+ textStyle,
109
+ ...props
110
+ }) {
111
+ if (typeof children !== 'string') throw Error('[Code] Code must be a string')
112
+ const code = useMemo(() => {
113
+ if (!language) {
114
+ return pug`
115
+ Span= children
116
+ `
117
+ }
118
+
119
+ return renderer(highlight(children, language), textStyle)
120
+ }, [children, language]) // eslint-disable-line react-hooks/exhaustive-deps
121
+
122
+ return pug`
123
+ ScrollView.root(
124
+ ...props
125
+ horizontal
126
+ style=style
127
+ )
128
+ Div= code
129
+ `
130
+ })
131
+
132
+ function renderer (tree, style) {
133
+ if (!(tree && Array.isArray(tree))) return null
134
+ return tree.map((child, index) => {
135
+ if (child.type === 'text') {
136
+ return child.value
137
+ } else {
138
+ const className = (child.properties && child.properties.className) || []
139
+ return pug`
140
+ Span(key=index style=style styleName=className)= renderer(child.children)
141
+ `
142
+ }
143
+ })
144
+ }
@@ -0,0 +1,96 @@
1
+ $bg = var(--color-bg-main)
2
+
3
+ monospace()
4
+ font-family monospace
5
+ +ios()
6
+ font-family Menlo-Regular
7
+
8
+ .root
9
+ padding 2u
10
+ background-color $bg
11
+ border-radius 1u
12
+
13
+ .line
14
+ min-height 2.5u
15
+ monospace()
16
+ +web()
17
+ white-space pre
18
+
19
+ .token
20
+ monospace()
21
+
22
+ // default Prism theme
23
+ // ref: https://github.com/PrismJS/prism/blob/master/themes/prism.css
24
+
25
+ .token.comment,
26
+ .token.prolog,
27
+ .token.doctype,
28
+ .token.cdata {
29
+ color: slategray;
30
+ }
31
+
32
+ .token.punctuation {
33
+ color: #999;
34
+ }
35
+
36
+ .token.namespace {
37
+ opacity: .7;
38
+ }
39
+
40
+ .token.property,
41
+ .token.tag,
42
+ .token.boolean,
43
+ .token.number,
44
+ .token.constant,
45
+ .token.symbol,
46
+ .token.deleted {
47
+ color: #905;
48
+ }
49
+
50
+ .token.selector,
51
+ .token.attr-name,
52
+ .token.string,
53
+ .token.char,
54
+ .token.builtin,
55
+ .token.inserted {
56
+ color: #690;
57
+ }
58
+
59
+ .token.operator,
60
+ .token.entity,
61
+ .token.url,
62
+ .language-css .token.string,
63
+ .style .token.string {
64
+ color: #9a6e3a;
65
+ /* This background color was intended by the author of this theme. */
66
+ background: hsla(0, 0%, 100%, .5);
67
+ }
68
+
69
+ .token.atrule,
70
+ .token.attr-value,
71
+ .token.keyword {
72
+ color: #07a;
73
+ }
74
+
75
+ .token.function,
76
+ .token.class-name {
77
+ color: #DD4A68;
78
+ }
79
+
80
+ .token.regex,
81
+ .token.important,
82
+ .token.variable {
83
+ color: #e90;
84
+ }
85
+
86
+ .token.important,
87
+ .token.bold {
88
+ font-weight: bold;
89
+ }
90
+ .token.italic {
91
+ font-style: italic;
92
+ }
93
+
94
+ .token.entity {
95
+ cursor: help;
96
+ }
@@ -0,0 +1,320 @@
1
+ import React, { useState, useContext } from 'react'
2
+ import { Image, ScrollView, Platform } from 'react-native'
3
+ import Clipboard from '@react-native-clipboard/clipboard'
4
+ import { pug, observer, $, BASE_URL } from 'startupjs'
5
+ import Alert from '@startupjs-ui/alert'
6
+ import Div from '@startupjs-ui/div'
7
+ import Span from '@startupjs-ui/span'
8
+ import Divider from '@startupjs-ui/divider'
9
+ import Br from '@startupjs-ui/br'
10
+ import Link from '@startupjs-ui/link'
11
+ import Icon from '@startupjs-ui/icon'
12
+ import { Table, Tbody, Td, Th, Thead, Tr } from '@startupjs-ui/table'
13
+ import Collapse from '@startupjs-ui/collapse'
14
+ // import { Anchor, scrollTo } from '@startupjs/scrollable-anchors'
15
+ // import { faLink } from '@fortawesome/free-solid-svg-icons/faLink'
16
+ import { faCode } from '@fortawesome/free-solid-svg-icons/faCode'
17
+ import { faCopy } from '@fortawesome/free-solid-svg-icons/faCopy'
18
+ // import _kebabCase from 'lodash/kebabCase'
19
+ // import _get from 'lodash/get'
20
+ import './index.styl'
21
+ import Code from '../Code'
22
+
23
+ // const RowComponent = props => pug`Div(...props row)`
24
+ const ALPHABET = 'abcdefghigklmnopqrstuvwxyz'
25
+ const ListLevelContext = React.createContext()
26
+ const BlockquoteContext = React.createContext()
27
+ const PreContext = React.createContext()
28
+
29
+ function getOrderedListMark (index, level) {
30
+ switch (level) {
31
+ case 1:
32
+ return ALPHABET.charAt(index % ALPHABET.length) + ')'
33
+ default:
34
+ return '' + (index + 1) + '.'
35
+ }
36
+ }
37
+
38
+ function P (props) {
39
+ return pug`
40
+ Span.p(style=props.style ...props)
41
+ `
42
+ }
43
+
44
+ // function getTextChildren (children) {
45
+ // const nestedChildren = _get(children, 'props.children')
46
+ // if (nestedChildren) {
47
+ // return getTextChildren(nestedChildren)
48
+ // }
49
+
50
+ // return children
51
+ // }
52
+
53
+ // function MDXAnchor ({
54
+ // children,
55
+ // style,
56
+ // anchor,
57
+ // size
58
+ // }) {
59
+ // const [hover, setHover] = useState()
60
+ // const anchorKebab = _kebabCase(anchor)
61
+
62
+ // return pug`
63
+ // Anchor.anchor(
64
+ // style=style
65
+ // id=anchorKebab
66
+ // Component=RowComponent
67
+ // vAlign='center'
68
+ // onMouseEnter=() => setHover(true)
69
+ // onMouseLeave=() => setHover()
70
+ // )
71
+ // = children
72
+ // Link.anchor-link(
73
+ // styleName={ hover }
74
+ // to='#' + anchorKebab
75
+ // )
76
+ // Icon(icon=faLink size=size)
77
+ // `
78
+ // }
79
+
80
+ export default {
81
+ wrapper: ({ children }) => pug`
82
+ Div= children
83
+ `,
84
+ // TODO: MDXAnchor(anchor=getTextChildren(children) size='xl')
85
+ h1: ({ children }) => pug`
86
+ Span(h2 bold)
87
+ = children
88
+ `,
89
+ // TODO: MDXAnchor.h2(anchor=getTextChildren(children))
90
+ h2: ({ children }) => pug`
91
+ Span.h2.h2-text(h5)= children
92
+ Div.divider
93
+ `,
94
+ // TODO: MDXAnchor.h3(anchor=getTextChildren(children) size='s')
95
+ h3: ({ children }) => pug`
96
+ Span.h3.h3-text(h6 bold)= children
97
+ `,
98
+ h4: P,
99
+ h5: P,
100
+ h6: P,
101
+ p: ({ children }) => {
102
+ // eslint-disable-next-line react-hooks/rules-of-hooks
103
+ const inBlockquote = useContext(BlockquoteContext)
104
+
105
+ if (inBlockquote) {
106
+ return pug`
107
+ Span.blockquoteP= children
108
+ `
109
+ }
110
+ return pug`
111
+ P= children
112
+ `
113
+ },
114
+ strong: ({ children }) => pug`
115
+ P(bold)= children
116
+ `,
117
+ em: ({ children }) => pug`
118
+ P(italic)= children
119
+ `,
120
+ hr: ({ children }) => pug`
121
+ Divider(size='l')
122
+ `,
123
+ center: ({ children }) => {
124
+ return pug`
125
+ P.center= children
126
+ `
127
+ },
128
+ br: Br,
129
+ thematicBreak: P,
130
+ table: ({ children }) => {
131
+ return pug`
132
+ Table(style={ marginTop: 16 })= children
133
+ `
134
+ },
135
+ thead: Thead,
136
+ tbody: Tbody,
137
+ tr: Tr,
138
+ td: Td,
139
+ th: Th,
140
+ delete: P,
141
+ a: ({ children, href }) => {
142
+ // function onPress (event) {
143
+ // const { url, hash } = $root.get('$render')
144
+ // const [_url, _hash] = href.split('#')
145
+ // if (url === _url && hash === `#${_hash}`) {
146
+ // event.preventDefault()
147
+ // // scrollTo({ anchorId: _hash })
148
+ // }
149
+ // }
150
+
151
+ // TODO: handle Anchor click with onPress
152
+ return pug`
153
+ Link.link(
154
+ to=href
155
+ size='l'
156
+ color='primary'
157
+ )= children
158
+ `
159
+ },
160
+ ul: ({ children }) => children,
161
+ ol: ({ children }) => {
162
+ // eslint-disable-next-line react-hooks/rules-of-hooks
163
+ const currentLevel = useContext(ListLevelContext)
164
+ const nextLevel = currentLevel == null ? 0 : currentLevel + 1
165
+ const filteredChildren = React.Children
166
+ .toArray(children)
167
+ .filter(child => child !== '\n')
168
+ .map((child, index) => React.cloneElement(child, { index }))
169
+ return pug`
170
+ ListLevelContext.Provider(value=nextLevel)
171
+ Div
172
+ = filteredChildren
173
+ `
174
+ },
175
+ li: ({ children, index }) => {
176
+ // eslint-disable-next-line react-hooks/rules-of-hooks
177
+ const level = useContext(ListLevelContext)
178
+ const listIndex = index == null ? '•' : getOrderedListMark(index, level)
179
+ let hasTextChild = false
180
+ children = React.Children
181
+ .toArray(children)
182
+ .filter(child => child !== '\n')
183
+ .map(child => {
184
+ if (typeof child === 'string') {
185
+ hasTextChild = true
186
+ }
187
+ return child
188
+ })
189
+ return pug`
190
+ Div(row)
191
+ Span.listIndex= listIndex
192
+ Div.listContent
193
+ if hasTextChild
194
+ P(size='l')= children
195
+ else
196
+ = children
197
+ `
198
+ },
199
+ blockquote: ({ children }) => {
200
+ const filteredChildren = React.Children
201
+ .toArray(children)
202
+ .filter(child => child !== '\n')
203
+
204
+ return pug`
205
+ BlockquoteContext.Provider(value=true)
206
+ Alert.alert= filteredChildren
207
+ `
208
+ },
209
+ img: ({ src }) => {
210
+ // eslint-disable-next-line react-hooks/rules-of-hooks
211
+ const [style, setStyle] = useState({})
212
+ const isUrl = /^(http|https):\/\//.test(src)
213
+ const isLocalUrl = /^\//.test(src)
214
+
215
+ if (isLocalUrl) {
216
+ src = BASE_URL + src
217
+ } else if (!isUrl) {
218
+ console.warn('[@startupjs/mdx] Need to provide the url for the image')
219
+ return null
220
+ }
221
+
222
+ function onLayout (e) {
223
+ const maxWidth = e.nativeEvent.layout.width
224
+ Image.getSize(src, (width, height) => {
225
+ const coefficient = maxWidth / width
226
+ setStyle({
227
+ width: Math.min(width, maxWidth),
228
+ height: coefficient < 1 ? Math.ceil(height * coefficient) : height
229
+ })
230
+ },
231
+ error => console.warn(`[@startupjs/mdx], ${error}`)
232
+ )
233
+ }
234
+ return pug`
235
+ Div.img(onLayout=onLayout)
236
+ Image(style=style source={ uri: src })
237
+ `
238
+ },
239
+ section: ({ children, noscroll }) => {
240
+ const Wrapper = noscroll
241
+ ? ({ children }) => pug`
242
+ Div.example.padding= children
243
+ `
244
+ : ({ children }) => pug`
245
+ ScrollView.example(
246
+ contentContainerStyleName=['exampleContent', 'padding']
247
+ horizontal
248
+ )= children
249
+ `
250
+
251
+ return pug`
252
+ Wrapper= children
253
+ `
254
+ },
255
+ pre: ({ children }) => {
256
+ return pug`
257
+ PreContext.Provider(value=true)
258
+ = children
259
+ `
260
+ },
261
+ code: observer(({ children, className, ...props }) => {
262
+ // eslint-disable-next-line react-hooks/rules-of-hooks
263
+ const isBlockCode = useContext(PreContext)
264
+
265
+ if (!isBlockCode) {
266
+ return pug`
267
+ Span.inlineCodeWrapper
268
+ Span.inlineCodeSpacer &#160;
269
+ Span.inlineCode(style={
270
+ fontFamily: Platform.OS === 'ios' ? 'Menlo-Regular' : 'monospace'
271
+ })= children
272
+ Span.inlineCodeSpacer &#160;
273
+ `
274
+ }
275
+
276
+ const language = (className || 'language-txt').replace(/language-/, '')
277
+ const [open, setOpen] = useState(false)
278
+ const $copyText = $('Copy code')
279
+
280
+ function copyHandler () {
281
+ Clipboard.setString(children)
282
+ $copyText.set('Copied')
283
+ }
284
+
285
+ function onMouseEnter () {
286
+ // we need to reutrn default text if it was copied
287
+ $copyText.set('Copy code')
288
+ }
289
+
290
+ let example
291
+
292
+ if (typeof children === 'string' && children.includes('[HACK EXAMPLE CODE]')) {
293
+ children = children.replace('[HACK EXAMPLE CODE]', '')
294
+ example = true
295
+ }
296
+
297
+ return pug`
298
+ Div.code(styleName={ 'code-example': example })
299
+ if example
300
+ Collapse.code-collapse(open=open variant='pure')
301
+ Collapse.Header.code-collapse-header(icon=false onPress=null)
302
+ Div.code-actions(align='right' row)
303
+ Div.code-action(
304
+ tooltip=open ? 'Hide code' : 'Show code'
305
+ onPress=()=> setOpen(!open)
306
+ )
307
+ Icon.code-action-collapse(icon=faCode color='error')
308
+ Div.code-action(
309
+ tooltip=$copyText.get()
310
+ onPress=copyHandler
311
+ onMouseEnter=onMouseEnter
312
+ )
313
+ Icon.code-action-copy(icon=faCopy)
314
+ Collapse.Content.code-collapse-content
315
+ Code(language=language)= children
316
+ else
317
+ Code(language=language)= children
318
+ `
319
+ })
320
+ }
@@ -0,0 +1,115 @@
1
+ $codeBg = var(--color-bg-main)
2
+ $exampleBg = var(--color-bg-main)
3
+
4
+ .p
5
+ .blockquoteP
6
+ .link
7
+ .listIndex
8
+ .inlineCode
9
+ .inlineCodeSpacer
10
+ font(body1)
11
+
12
+ .h2
13
+ margin-top 8u
14
+
15
+ &-text
16
+ fontFamily('heading', 600)
17
+
18
+ .h3
19
+ margin-top 6u
20
+
21
+ &-text
22
+ fontFamily('heading', 600)
23
+
24
+ .anchor
25
+ align-self flex-start
26
+ word-break break-word
27
+
28
+ &-link
29
+ margin-left 1u
30
+ opacity 0
31
+
32
+ &.hover
33
+ opacity 1
34
+
35
+ .divider
36
+ height 0.5u
37
+ background-color var(--color-bg-secondary)
38
+ margin-bottom 1.5u
39
+
40
+ .p
41
+ margin-top 2u
42
+
43
+ .center
44
+ text-align center
45
+
46
+ .listIndex
47
+ width 3u
48
+ margin-top 2u
49
+ text-align center
50
+ padding-right 2px
51
+
52
+ .listContent
53
+ flex 1
54
+
55
+ .alert
56
+ margin-top 2u
57
+
58
+ .img
59
+ margin-top 2u
60
+ width 100%
61
+
62
+ .inlineCodeWrapper
63
+ background-color $codeBg
64
+ border-width 1px
65
+ border-color var(--color-border-main)
66
+ border-radius .5u
67
+
68
+
69
+
70
+
71
+
72
+ .example
73
+ margin-top 2u
74
+ background-color $exampleBg
75
+ border-top-left-radius 1u
76
+ border-top-right-radius 1u
77
+
78
+ &Content
79
+ flex-direction column
80
+ flex-grow 1
81
+
82
+ .padding
83
+ padding 2u
84
+
85
+
86
+
87
+ .code
88
+ margin-top 2u
89
+
90
+ &-example
91
+ margin-top 0
92
+
93
+ &-collapse
94
+ background-color $exampleBg
95
+ border-bottom-left-radius 1u
96
+ border-bottom-right-radius 1u
97
+
98
+ &-header
99
+ padding-top 1u
100
+ padding-bottom 2u
101
+ padding-left 2u
102
+ padding-right 2u
103
+
104
+ +tablet()
105
+ padding-top 2u
106
+
107
+ &-content
108
+ padding 2u
109
+
110
+ &-action
111
+ margin-left 2u
112
+
113
+ &-collapse
114
+ &-copy
115
+ color var(--color-text-description)
package/index.js ADDED
@@ -0,0 +1,15 @@
1
+ import defaultMdxComponents from './client/mdxComponents/index.js'
2
+
3
+ const mdxComponents = { ...defaultMdxComponents }
4
+
5
+ // this can be used to override default MDX components globally
6
+ export function overrideMDXComponents (newComponents) {
7
+ Object.assign(mdxComponents, newComponents)
8
+ }
9
+
10
+ // magic named export used by @mdx-js/mdx (in mdxLoader of @startupjs/bundler)
11
+ export function useMDXComponents () {
12
+ return mdxComponents
13
+ }
14
+
15
+ export default mdxComponents
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@startupjs-ui/mdx",
3
+ "description": "MDX provider with a set of custom components for react-native support and syntax highlighting",
4
+ "version": "0.1.3",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "type": "module",
9
+ "exports": {
10
+ ".": "./index.js"
11
+ },
12
+ "dependencies": {
13
+ "@fortawesome/free-solid-svg-icons": "^5.12.0",
14
+ "@mdx-js/react": "^3.0.0",
15
+ "@startupjs-ui/alert": "^0.1.3",
16
+ "@startupjs-ui/br": "^0.1.3",
17
+ "@startupjs-ui/collapse": "^0.1.3",
18
+ "@startupjs-ui/div": "^0.1.3",
19
+ "@startupjs-ui/divider": "^0.1.3",
20
+ "@startupjs-ui/icon": "^0.1.3",
21
+ "@startupjs-ui/link": "^0.1.3",
22
+ "@startupjs-ui/scroll-view": "^0.1.3",
23
+ "@startupjs-ui/span": "^0.1.3",
24
+ "@startupjs-ui/table": "^0.1.3",
25
+ "refractor": "^3.0.0"
26
+ },
27
+ "peerDependencies": {
28
+ "@react-native-clipboard/clipboard": "*",
29
+ "react": "*",
30
+ "react-native": "*",
31
+ "startupjs": "*"
32
+ },
33
+ "gitHead": "fd964ebc3892d3dd0a6c85438c0af619cc50c3f0"
34
+ }