@startupjs/docs 0.60.0-canary.7 → 0.60.0-canary.9

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.
@@ -1,8 +1,7 @@
1
1
  import React, { useState } from 'react'
2
- import { pug, emit, observer, useModel, $ } from 'startupjs'
2
+ import { pug, emit, observer, useModel } from 'startupjs'
3
3
  import { pathFor, useLocation } from 'startupjs/app'
4
4
  import { AutoSuggest, Button, Div, Layout, Menu, Span } from '@startupjs/ui'
5
- import { MDXProvider } from '@startupjs/mdx'
6
5
  import { ScrollableProvider } from '@startupjs/scrollable-anchors'
7
6
  import { faBars } from '@fortawesome/free-solid-svg-icons/faBars'
8
7
  import { faSearch } from '@fortawesome/free-solid-svg-icons/faSearch'
@@ -89,11 +88,10 @@ export default observer(function StyleguideLayout ({ children }) {
89
88
  // Note: Topbar height is compensated in PDoc
90
89
  // to achieve a semi-transparent effect
91
90
  return pug`
92
- MDXProvider(key=$.session.theme.get())
93
- Layout.layout(testID="Layout")
94
- Sidebar
95
- Topbar
96
- ScrollableProvider
97
- = children
91
+ Layout.layout(testID="Layout")
92
+ Sidebar
93
+ Topbar
94
+ ScrollableProvider
95
+ = children
98
96
  `
99
97
  })
@@ -1,18 +1,18 @@
1
- import { useLocal, useSyncEffect, useComponentId } from 'startupjs'
1
+ import { $, useSyncEffect, useId } from 'startupjs'
2
2
 
3
3
  export default function useLocalWithDefault (path, defaultValue) {
4
4
  if (defaultValue == null) {
5
5
  throw new Error('useLocalWithDefault: default value is required')
6
6
  }
7
7
 
8
- const componentId = useComponentId()
8
+ const componentId = useId()
9
9
  if (!path) path = `_session.${componentId}`
10
- const [value, $value] = useLocal(path)
10
+ const $value = path.split('.').reduce((acc, part) => acc[part], $)
11
11
 
12
12
  useSyncEffect(() => {
13
- if (!(value == null)) return
14
- throw $value.set('', defaultValue)
13
+ if (!($value.get() == null)) return
14
+ throw $value.set(defaultValue)
15
15
  }, [])
16
16
 
17
- return [value, $value]
17
+ return [$value.get(), $value]
18
18
  }
@@ -1,21 +1,21 @@
1
1
  import React, { useCallback, useMemo } from 'react'
2
- import { pug, observer, useValue } from 'startupjs'
2
+ import { pug, observer, $ } from 'startupjs'
3
3
  import { Button, Span, themed } from '@startupjs/ui'
4
4
  import '../index.styl'
5
5
 
6
6
  const MAX_ITEMS = 10
7
7
 
8
8
  export default observer(themed(function TypeCell ({ possibleValues, theme, type }) {
9
- const [collapsed, $collapsed] = useValue(true)
9
+ const $collapsed = $(true)
10
10
 
11
11
  const values = useMemo(() => {
12
12
  if (!Array.isArray(possibleValues)) return []
13
- return collapsed ? possibleValues.slice(0, MAX_ITEMS) : possibleValues
14
- }, [collapsed, possibleValues])
13
+ return $collapsed.get() ? possibleValues.slice(0, MAX_ITEMS) : possibleValues
14
+ }, [$collapsed, possibleValues])
15
15
 
16
16
  const toggleList = useCallback(() => {
17
- $collapsed.setDiff(!collapsed)
18
- }, [collapsed])
17
+ $collapsed.set(!$collapsed.get())
18
+ }, [$collapsed])
19
19
 
20
20
  const renderButton = useCallback(() => {
21
21
  if (possibleValues?.length <= MAX_ITEMS) return null
@@ -26,9 +26,9 @@ export default observer(themed(function TypeCell ({ possibleValues, theme, type
26
26
  size='s'
27
27
  variant='text'
28
28
  onPress=toggleList
29
- )= collapsed ? 'More...' : 'Less'
29
+ )= $collapsed.get() ? 'More...' : 'Less'
30
30
  `
31
- }, [collapsed, possibleValues])
31
+ }, [$collapsed, possibleValues, toggleList]) // eslint-disable-line react-hooks/exhaustive-deps
32
32
 
33
33
  return pug`
34
34
  if type === 'oneOf'
@@ -1,5 +1,5 @@
1
1
  import React, { useCallback, useMemo } from 'react'
2
- import { pug, batch, observer, useValue } from 'startupjs'
2
+ import { pug, batch, observer, $ } from 'startupjs'
3
3
  import { Br, Input, Span } from '@startupjs/ui'
4
4
  import debounce from 'lodash/debounce'
5
5
  import isPlainObject from 'lodash/isPlainObject'
@@ -10,7 +10,7 @@ import omit from 'lodash/omit'
10
10
  import * as icons from '@fortawesome/free-solid-svg-icons'
11
11
  import '../index.styl'
12
12
 
13
- const EDITABLE_TYPES = ['string', 'number', 'bool', 'oneOf', 'array', 'object']
13
+ const EDITABLE_TYPES = ['string', 'number', 'boolean', 'oneOf', 'array', 'object']
14
14
 
15
15
  const IconSelect = observer(function ({ $value, value }) {
16
16
  const _icons = useMemo(
@@ -39,10 +39,10 @@ const JSONInput = observer(function ({ $value, type }) {
39
39
  return value ? JSON.stringify(value) : ''
40
40
  }, [$value])
41
41
 
42
- const [tempJSON, $tempJSON] = useValue(_JSONValue)
43
- const [badJSON, $badJSON] = useValue(false)
42
+ const $tempJSON = $(_JSONValue)
43
+ const $badJSON = $(false)
44
44
 
45
- const validateJson = useCallback(
45
+ const validateJson = useCallback( // eslint-disable-line react-hooks/exhaustive-deps
46
46
  debounce(text => {
47
47
  try {
48
48
  if (!text) {
@@ -52,13 +52,13 @@ const JSONInput = observer(function ({ $value, type }) {
52
52
  const isValidValue = parsedValue && validateByType(type, parsedValue)
53
53
  if (isValidValue) {
54
54
  $value.set(parsedValue)
55
- $badJSON.setDiff(false)
55
+ $badJSON.set(false)
56
56
  } else {
57
- $badJSON.setDiff(true)
57
+ $badJSON.set(true)
58
58
  }
59
59
  }
60
60
  } catch (error) {
61
- $badJSON.setDiff(true)
61
+ $badJSON.set(true)
62
62
  }
63
63
  }, 300),
64
64
  [$badJSON, $value]
@@ -71,10 +71,10 @@ const JSONInput = observer(function ({ $value, type }) {
71
71
 
72
72
  return pug`
73
73
  Input(
74
- inputStyleName={ badJSON }
74
+ inputStyleName={ badJSON: $badJSON.get() }
75
75
  size='s'
76
76
  type='text'
77
- value=tempJSON || ''
77
+ value=$tempJSON.get() || ''
78
78
  onChangeText=onChangeJSON
79
79
  )
80
80
  `
@@ -118,7 +118,7 @@ const PropInput = observer(function ({ $value, extraParams = {}, options, type,
118
118
  ...extraParams
119
119
  )
120
120
  `
121
- case 'bool':
121
+ case 'boolean':
122
122
  return pug`
123
123
  Input.checkbox(
124
124
  type='checkbox'
@@ -159,8 +159,8 @@ const TypesSelect = observer(function ({
159
159
  ),
160
160
  [possibleValues]
161
161
  )
162
- const [selectedValue, $selectedValue] = useValue(names[0])
163
- const $value = $props.at(name)
162
+ const $selectedValue = $(names[0])
163
+ const $value = $props[name]
164
164
  const value = $value.get()
165
165
 
166
166
  function onChange (value) {
@@ -181,15 +181,15 @@ const TypesSelect = observer(function ({
181
181
  showEmptyValue=false
182
182
  size='s'
183
183
  type='select'
184
- value=selectedValue
184
+ value=$selectedValue.get()
185
185
  onChange=onChange
186
186
  )
187
187
  Br(half)
188
188
  PropInput(
189
189
  $value=$value
190
190
  extraParams=extraParams
191
- options=options[selectedValue]
192
- type=selectedValue
191
+ options=options[$selectedValue.get()]
192
+ type=$selectedValue.get()
193
193
  value=value
194
194
  )
195
195
  else
@@ -199,7 +199,7 @@ const TypesSelect = observer(function ({
199
199
 
200
200
  export default observer(function ValueCell ({ $props, entry }) {
201
201
  const { extraParams, name, possibleValues, type } = entry
202
- const $value = $props.at(name)
202
+ const $value = $props[name]
203
203
  const value = $value.get()
204
204
 
205
205
  if (/^\$/.test(name)) { // hide Input for model prop
@@ -230,7 +230,7 @@ function validateByType (type, value) {
230
230
  return Array.isArray(value)
231
231
  case 'object':
232
232
  return isPlainObject(value)
233
- case 'bool':
233
+ case 'boolean':
234
234
  return typeof value === 'boolean'
235
235
  case 'number':
236
236
  return typeof value === 'number'
@@ -22,8 +22,8 @@ export default observer(themed(function Constructor ({
22
22
  Thead.thead
23
23
  Tr
24
24
  Td: Span.header PROP
25
+ Td: Span.header DESCRIPTION
25
26
  Td: Span.header TYPE
26
- Td: Span.header DEFAULT
27
27
  Td: Span.header.right VALUE
28
28
  Tbody
29
29
  each entry, index in entries
@@ -42,8 +42,12 @@ export default observer(themed(function Constructor ({
42
42
  color='error'
43
43
  shape='rounded'
44
44
  ) Required
45
+ if defaultValue != null
46
+ Span.valueDefault
47
+ Span(description) =#{' '}
48
+ Span.value= JSON.stringify(defaultValue)
49
+ Td: Span(description italic)= entry.description || '-'
45
50
  Td: TypeCell(possibleValues=possibleValues type=type)
46
- Td: Span.value= JSON.stringify(defaultValue)
47
51
  Td.vCenter: ValueCell(entry=entry $props=$props)
48
52
  `
49
53
  }))
@@ -19,6 +19,9 @@ $type = var(--color-text-info)
19
19
  color $value
20
20
  font-style italic
21
21
 
22
+ .valueDefault
23
+ padding-left 4u
24
+
22
25
  .type
23
26
  color $type
24
27
  font-style italic
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import { pug, observer, useModel, useLocal } from 'startupjs'
2
+ import { pug, observer, $ } from 'startupjs'
3
3
  import { themed, Div, Span } from '@startupjs/ui'
4
4
  import './index.styl'
5
5
 
@@ -17,11 +17,11 @@ export default observer(function GridVisualizer ({
17
17
  style,
18
18
  children
19
19
  }) {
20
- const $componentSize = useModel('_session.Renderer.componentSize')
20
+ const $componentSize = $.session.Renderer.componentSize
21
21
 
22
22
  function onLayout (e) {
23
23
  const { width, height } = e.nativeEvent.layout
24
- $componentSize.setDiffDeep({ width, height })
24
+ $componentSize.set({ width, height })
25
25
  }
26
26
 
27
27
  // TODO: Bring back width check as an option. For now it's commented out.
@@ -45,7 +45,8 @@ export default observer(function GridVisualizer ({
45
45
  })
46
46
 
47
47
  const LeftBar = observer(themed(({ allowHalfUnit, validate, theme }) => {
48
- const [height = 0] = useLocal('_session.Renderer.componentSize.height')
48
+ const $height = $.session.Renderer.componentSize.height
49
+ const height = $height.get() || 0
49
50
  const units = toUnits(height)
50
51
  const valid = validate ? validateGrid(height, allowHalfUnit) : true
51
52
 
@@ -1,18 +1,14 @@
1
1
  import React, { useMemo, useState } from 'react'
2
- import { pug, observer, $root, useComponentId } from 'startupjs'
2
+ import { pug, observer, $, useId } from 'startupjs'
3
3
  import { themed, Button, Div, ScrollView } from '@startupjs/ui'
4
- import parsePropTypesModule from 'parse-prop-types'
5
4
  import Constructor from './Constructor'
6
5
  import Renderer from './Renderer'
7
6
  import './index.styl'
8
7
 
9
- const parsePropTypes = parsePropTypesModule.default || parsePropTypesModule
10
- if (!parsePropTypes) throw Error('> Can\'t load parse-prop-types module. Issues with bundling')
11
-
12
- function useEntries ({ Component, props, extraParams }) {
8
+ function useEntries ({ Component, props, extraParams, propsJsonSchema }) {
13
9
  return useMemo(() => {
14
- const propTypes = parsePropTypes(Component)
15
- const entries = Object.entries(propTypes)
10
+ if (!propsJsonSchema?.properties) return []
11
+ const entries = Object.entries(propsJsonSchema.properties)
16
12
 
17
13
  const res = parseEntries(entries)
18
14
  .filter(entry => entry.name[0] !== '_') // skip private properties
@@ -36,33 +32,38 @@ function useEntries ({ Component, props, extraParams }) {
36
32
  }
37
33
 
38
34
  return res
39
- }, [])
35
+ }, [extraParams, props, propsJsonSchema])
40
36
  }
41
37
 
42
38
  function parseEntries (entries) {
43
39
  return entries.map(entry => {
44
40
  const meta = entry[1]
41
+ let type = meta.type
42
+ if (meta.enum) type = 'oneOf'
43
+ if (meta.$comment && meta.$comment.startsWith('(')) type = 'function'
44
+ if (!type) type = 'any'
45
45
  return {
46
46
  name: entry[0],
47
- type: meta.type.name,
48
- defaultValue: meta.defaultValue && meta.defaultValue.value,
49
- possibleValues: meta.type.value,
50
- isRequired: meta.required
47
+ type,
48
+ defaultValue: meta.default,
49
+ possibleValues: meta.enum,
50
+ isRequired: meta.required,
51
+ description: meta.description
51
52
  }
52
53
  })
53
54
  }
54
55
 
55
56
  async function useInitDefaultProps ({ entries, $theProps }) {
56
57
  if ($theProps.get()) return
57
- $theProps.setDiff({})
58
+ $theProps.set({})
58
59
 
59
60
  const promises = []
60
61
 
61
62
  for (const { name, value, defaultValue } of entries) {
62
63
  if (value !== undefined) {
63
- promises.push($theProps.set(name, value, null))
64
+ promises.push($theProps[name].set(value))
64
65
  } else if (defaultValue !== undefined) {
65
- promises.push($theProps.set(name, defaultValue, null))
66
+ promises.push($theProps[name].set(defaultValue))
66
67
  }
67
68
  }
68
69
  if (promises.length) throw await Promise.all(promises)
@@ -74,6 +75,7 @@ export default observer(themed(function PComponent ({
74
75
  Component,
75
76
  $props,
76
77
  props,
78
+ propsJsonSchema,
77
79
  extraParams,
78
80
  componentName,
79
81
  showGrid,
@@ -83,17 +85,17 @@ export default observer(themed(function PComponent ({
83
85
  block: defaultBlock
84
86
  }) {
85
87
  const [block, setBlock] = useState(!!defaultBlock)
86
- const componentId = useComponentId()
88
+ const componentId = useId()
87
89
 
88
90
  const $theProps = useMemo(() => {
89
91
  if (!$props) {
90
- return $root.scope(`_session.Props.${componentId}`)
92
+ return $.session.Props[componentId]
91
93
  } else {
92
94
  return $props
93
95
  }
94
- }, [$props])
96
+ }, [$props, componentId])
95
97
 
96
- const entries = useEntries({ Component, props, extraParams })
98
+ const entries = useEntries({ Component, props, extraParams, propsJsonSchema })
97
99
  useInitDefaultProps({ entries, $theProps })
98
100
 
99
101
  function Wrapper ({ children }) {
@@ -1,6 +1,6 @@
1
1
  import React from 'react'
2
- import { pug, observer, $root } from 'startupjs'
3
- import { H4 } from '@startupjs/ui'
2
+ import { pug, observer, $, useId } from 'startupjs'
3
+ import { H4, Alert } from '@startupjs/ui'
4
4
  import Props from '../Props'
5
5
  import {
6
6
  useShowGrid,
@@ -13,12 +13,14 @@ const MODELS = new WeakMap()
13
13
 
14
14
  export default observer(function Sandbox ({
15
15
  Component,
16
+ propsJsonSchema,
16
17
  $props,
17
18
  ...otherProps
18
19
  }) {
19
20
  const [showGrid] = useShowGrid()
20
21
  const [showSizes] = useShowSizes()
21
22
  const [validateWidth] = useValidateWidth()
23
+ const uniqId = useId()
22
24
 
23
25
  if (!Component) {
24
26
  return pug`
@@ -26,10 +28,25 @@ export default observer(function Sandbox ({
26
28
  `
27
29
  }
28
30
 
31
+ if (typeof propsJsonSchema !== 'object' || Object.keys(propsJsonSchema).length === 0) {
32
+ return pug`
33
+ Alert(variant='error')
34
+ | No propsJsonSchema provided for the Sandbox component (or it's an empty object).
35
+ | Make sure that:
36
+ | 1. your component file has the magic 'const export _PropsJsonSchema = ' declaration;
37
+ | 2. your component file has 'export interface' with props interface declared;
38
+ | 3. you import the '_PropsJsonSchema' from the component file
39
+ | and pass it to the Sandbox as 'propsJsonSchema' prop;
40
+ | 4. 'babel-preset-startupjs' must have an option 'docgen: true' enabled
41
+ | to transform the TS interface to JSON schema at build time.
42
+ `
43
+ }
44
+
29
45
  return pug`
30
46
  Props.root(
31
47
  Component=Component
32
- $props=$props || getUniqModel(Component)
48
+ propsJsonSchema=propsJsonSchema
49
+ $props=$props || getUniqModel(Component, uniqId)
33
50
  showSizes=showSizes
34
51
  showGrid=showGrid
35
52
  validateWidth=validateWidth
@@ -38,10 +55,9 @@ export default observer(function Sandbox ({
38
55
  `
39
56
  })
40
57
 
41
- function getUniqModel (Component) {
58
+ function getUniqModel (Component, uniqId) {
42
59
  if (MODELS.has(Component)) return MODELS.get(Component)
43
- const uniqId = $root.id()
44
- const $uniqModel = $root.scope('_session.Props.' + uniqId)
60
+ const $uniqModel = $.session.Props[uniqId]
45
61
  MODELS.set(Component, $uniqModel)
46
62
  return $uniqModel
47
63
  }
package/index.js CHANGED
@@ -1,12 +1,13 @@
1
- import { routes, Layout } from './client/app'
2
- import { wrapDocsContext } from './docsContext'
1
+ // TODO: refactor docs app to work with the new expo app structure
2
+ // import { routes, Layout } from './client/app'
3
+ // import { wrapDocsContext } from './docsContext'
3
4
 
4
- // Wrap Layout into context
5
- export default function (docs) {
6
- return {
7
- routes,
8
- Layout: wrapDocsContext(Layout, docs)
9
- }
10
- }
5
+ // // Wrap Layout into context
6
+ // export default function (docs) {
7
+ // return {
8
+ // routes,
9
+ // Layout: wrapDocsContext(Layout, docs)
10
+ // }
11
+ // }
11
12
 
12
13
  export * from './client/components'
package/package.json CHANGED
@@ -4,14 +4,13 @@
4
4
  "access": "public"
5
5
  },
6
6
  "description": "MDX documentation generator",
7
- "version": "0.60.0-canary.7",
7
+ "version": "0.60.0-canary.9",
8
8
  "type": "module",
9
9
  "main": "index.js",
10
10
  "dependencies": {
11
11
  "@fortawesome/free-solid-svg-icons": "^5.12.0",
12
- "@startupjs/mdx": "^0.60.0-canary.7",
13
- "@startupjs/scrollable-anchors": "^0.60.0-canary.7",
14
- "parse-prop-types": "^0.3.0"
12
+ "@startupjs/mdx": "^0.60.0-canary.9",
13
+ "@startupjs/scrollable-anchors": "^0.60.0-canary.7"
15
14
  },
16
15
  "peerDependencies": {
17
16
  "@startupjs/ui": "*",
@@ -19,5 +18,5 @@
19
18
  "react-native": "*",
20
19
  "startupjs": "*"
21
20
  },
22
- "gitHead": "68c5c8e9757e263133c36a24f46ba35efc9b87b8"
21
+ "gitHead": "d314ca5e6c7b96f6692fb0eb31990eebab31566f"
23
22
  }