@startupjs-ui/docs 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.
Files changed (51) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +99 -0
  3. package/client/app/Layout/Sidebar/Content/Docs/index.js +118 -0
  4. package/client/app/Layout/Sidebar/Content/Docs/index.styl +12 -0
  5. package/client/app/Layout/Sidebar/Content/Options/index.js +52 -0
  6. package/client/app/Layout/Sidebar/Content/Options/index.styl +11 -0
  7. package/client/app/Layout/Sidebar/Content/index.js +38 -0
  8. package/client/app/Layout/Sidebar/Content/index.styl +35 -0
  9. package/client/app/Layout/Sidebar/index.js +24 -0
  10. package/client/app/Layout/index.js +97 -0
  11. package/client/app/Layout/index.styl +31 -0
  12. package/client/app/constants.styl +1 -0
  13. package/client/app/index.js +5 -0
  14. package/client/app/pages/PDoc/index.js +46 -0
  15. package/client/app/pages/PDoc/index.styl +21 -0
  16. package/client/app/pages/PHome/index.js +33 -0
  17. package/client/app/pages/index.js +2 -0
  18. package/client/app/routes.js +15 -0
  19. package/client/clientHelpers/getTitle.js +11 -0
  20. package/client/clientHelpers/hooks/index.js +6 -0
  21. package/client/clientHelpers/hooks/useLang.js +12 -0
  22. package/client/clientHelpers/hooks/useLocalStorage.js +37 -0
  23. package/client/clientHelpers/hooks/useLocalWithDefault.js +18 -0
  24. package/client/clientHelpers/hooks/useShowGrid.js +6 -0
  25. package/client/clientHelpers/hooks/useShowSizes.js +6 -0
  26. package/client/clientHelpers/hooks/useValidateWidth.js +6 -0
  27. package/client/clientHelpers/index.js +2 -0
  28. package/client/components/Props/Constructor/Table/index.js +10 -0
  29. package/client/components/Props/Constructor/Table/index.styl +2 -0
  30. package/client/components/Props/Constructor/Tbody/index.js +9 -0
  31. package/client/components/Props/Constructor/Td/index.js +10 -0
  32. package/client/components/Props/Constructor/Td/index.styl +4 -0
  33. package/client/components/Props/Constructor/Thead/index.js +9 -0
  34. package/client/components/Props/Constructor/Tr/index.js +11 -0
  35. package/client/components/Props/Constructor/Tr/index.styl +6 -0
  36. package/client/components/Props/Constructor/TypeCell/index.js +55 -0
  37. package/client/components/Props/Constructor/ValueCell/index.js +246 -0
  38. package/client/components/Props/Constructor/index.js +84 -0
  39. package/client/components/Props/Constructor/index.styl +55 -0
  40. package/client/components/Props/Renderer/GridVisualizer/index.js +88 -0
  41. package/client/components/Props/Renderer/GridVisualizer/index.styl +108 -0
  42. package/client/components/Props/Renderer/index.js +44 -0
  43. package/client/components/Props/index.js +160 -0
  44. package/client/components/Props/index.styl +25 -0
  45. package/client/components/Sandbox/index.js +64 -0
  46. package/client/components/Sandbox/index.styl +2 -0
  47. package/client/components/index.js +2 -0
  48. package/client/const/index.js +2 -0
  49. package/docsContext.js +17 -0
  50. package/index.js +13 -0
  51. package/package.json +29 -0
@@ -0,0 +1,6 @@
1
+ export { default as useLocalWithDefault } from './useLocalWithDefault'
2
+ export { default as useShowGrid } from './useShowGrid'
3
+ export { default as useShowSizes } from './useShowSizes'
4
+ export { default as useValidateWidth } from './useValidateWidth'
5
+ export { default as useLocalStorage } from './useLocalStorage'
6
+ export { default as useLang } from './useLang'
@@ -0,0 +1,12 @@
1
+ import { useSession } from 'startupjs'
2
+ import useLocalStorage from './useLocalStorage'
3
+ import { DEFAULT_LANGUAGE } from './../../const'
4
+
5
+ export default function useLang () {
6
+ const [lang, setLang] = useLocalStorage('lang', DEFAULT_LANGUAGE)
7
+ const [sessionLang, $sessionLang] = useSession('lang')
8
+ return [sessionLang || lang, newValue => {
9
+ setLang(newValue)
10
+ $sessionLang.setDiff(newValue)
11
+ }]
12
+ }
@@ -0,0 +1,37 @@
1
+ // ref: https://usehooks.com/useLocalStorage/
2
+ import { useState } from 'react'
3
+
4
+ // Hook
5
+ export default function useLocalStorage (key, initialValue) {
6
+ // State to store our value
7
+ // Pass initial state function to useState so logic is only executed once
8
+ const [storedValue, setStoredValue] = useState(() => {
9
+ try {
10
+ // Get from local storage by key
11
+ const item = window.localStorage.getItem(key)
12
+ // Parse stored json or if none return initialValue
13
+ return item ? JSON.parse(item) : initialValue
14
+ } catch (error) {
15
+ // If error also return initialValue
16
+ return initialValue
17
+ }
18
+ })
19
+
20
+ // Return a wrapped version of useState's setter function that ...
21
+ // ... persists the new value to localStorage.
22
+ const setValue = value => {
23
+ try {
24
+ // Allow value to be a function so we have same API as useState
25
+ const valueToStore =
26
+ value instanceof Function ? value(storedValue) : value
27
+ // Save state
28
+ setStoredValue(valueToStore)
29
+ // Save to local storage
30
+ window.localStorage.setItem(key, JSON.stringify(valueToStore))
31
+ } catch (error) {
32
+ // A more advanced implementation would handle the error case
33
+ }
34
+ }
35
+
36
+ return [storedValue, setValue]
37
+ }
@@ -0,0 +1,18 @@
1
+ import { $, useSyncEffect, useId } from 'startupjs'
2
+
3
+ export default function useLocalWithDefault (path, defaultValue) {
4
+ if (defaultValue == null) {
5
+ throw new Error('useLocalWithDefault: default value is required')
6
+ }
7
+
8
+ const componentId = useId()
9
+ if (!path) path = `_session.${componentId}`
10
+ const $value = path.split('.').reduce((acc, part) => acc[part], $)
11
+
12
+ useSyncEffect(() => {
13
+ if (!($value.get() == null)) return
14
+ throw $value.set(defaultValue)
15
+ }, [])
16
+
17
+ return [$value.get(), $value]
18
+ }
@@ -0,0 +1,6 @@
1
+ import useLocalWithDefault from './useLocalWithDefault'
2
+ const PATH = '_session.Props.showGrid'
3
+
4
+ export default function useShowGrid () {
5
+ return useLocalWithDefault(PATH, false)
6
+ }
@@ -0,0 +1,6 @@
1
+ import useLocalWithDefault from './useLocalWithDefault'
2
+ const PATH = '_session.Props.showSizes'
3
+
4
+ export default function useShowSizes () {
5
+ return useLocalWithDefault(PATH, true)
6
+ }
@@ -0,0 +1,6 @@
1
+ import useLocalWithDefault from './useLocalWithDefault'
2
+ const PATH = '_session.Props.validateWidth'
3
+
4
+ export default function useValidateWidth () {
5
+ return useLocalWithDefault(PATH, false)
6
+ }
@@ -0,0 +1,2 @@
1
+ export * from './hooks'
2
+ export { default as getTitle } from './getTitle'
@@ -0,0 +1,10 @@
1
+ import React from 'react'
2
+ import { pug, observer } from 'startupjs'
3
+ import Div from '@startupjs-ui/div'
4
+ import './index.styl'
5
+
6
+ export default observer(function Table ({ children, style }) {
7
+ return pug`
8
+ Div.root(style=style)= children
9
+ `
10
+ })
@@ -0,0 +1,2 @@
1
+ .root
2
+ width 100%
@@ -0,0 +1,9 @@
1
+ import React from 'react'
2
+ import { pug, observer } from 'startupjs'
3
+ import Div from '@startupjs-ui/div'
4
+
5
+ export default observer(function Tbody ({ children, style }) {
6
+ return pug`
7
+ Div(style=style)= children
8
+ `
9
+ })
@@ -0,0 +1,10 @@
1
+ import React from 'react'
2
+ import { pug, observer } from 'startupjs'
3
+ import Div from '@startupjs-ui/div'
4
+ import './index.styl'
5
+
6
+ export default observer(function Td ({ children, style }) {
7
+ return pug`
8
+ Div.root(style=style)= children
9
+ `
10
+ })
@@ -0,0 +1,4 @@
1
+ .root
2
+ padding 1u
3
+ flex 1
4
+ justify-content center
@@ -0,0 +1,9 @@
1
+ import React from 'react'
2
+ import { pug, observer } from 'startupjs'
3
+ import Div from '@startupjs-ui/div'
4
+
5
+ export default observer(function Thead ({ children, style }) {
6
+ return pug`
7
+ Div(style=style)= children
8
+ `
9
+ })
@@ -0,0 +1,11 @@
1
+ import React from 'react'
2
+ import { pug, observer } from 'startupjs'
3
+ import { themed } from '@startupjs-ui/core'
4
+ import Div from '@startupjs-ui/div'
5
+ import './index.styl'
6
+
7
+ export default observer(themed(function Tr ({ children, style }) {
8
+ return pug`
9
+ Div.root(style=style)= children
10
+ `
11
+ }))
@@ -0,0 +1,6 @@
1
+ .root
2
+ flex-direction row
3
+ border-color var(--color-border-main)
4
+ border-bottom-width 1px
5
+ padding-left 1u
6
+ padding-right 1u
@@ -0,0 +1,55 @@
1
+ import React, { useCallback, useMemo } from 'react'
2
+ import { pug, observer, $ } from 'startupjs'
3
+ import Button from '@startupjs-ui/button'
4
+ import Span from '@startupjs-ui/span'
5
+ import { themed } from '@startupjs-ui/core'
6
+ import '../index.styl'
7
+
8
+ const MAX_ITEMS = 10
9
+
10
+ export default observer(themed(function TypeCell ({ possibleValues, theme, type }) {
11
+ const $collapsed = $(true)
12
+
13
+ const values = useMemo(() => {
14
+ if (!Array.isArray(possibleValues)) return []
15
+ return $collapsed.get() ? possibleValues.slice(0, MAX_ITEMS) : possibleValues
16
+ }, [$collapsed, possibleValues])
17
+
18
+ const toggleList = useCallback(() => {
19
+ $collapsed.set(!$collapsed.get())
20
+ }, [$collapsed])
21
+
22
+ const renderButton = useCallback(() => {
23
+ if (possibleValues?.length <= MAX_ITEMS) return null
24
+ return pug`
25
+ Span &nbsp&nbsp
26
+ Button(
27
+ color='primary'
28
+ size='s'
29
+ variant='text'
30
+ onPress=toggleList
31
+ )= $collapsed.get() ? 'More...' : 'Less'
32
+ `
33
+ }, [$collapsed, possibleValues, toggleList]) // eslint-disable-line react-hooks/exhaustive-deps
34
+
35
+ return pug`
36
+ if type === 'oneOf'
37
+ Span.possibleValue
38
+ each value, index in values
39
+ Span(key=index)
40
+ if index
41
+ Span.separator(styleName=[theme]) #{' | '}
42
+ Span.value(styleName=[theme])= JSON.stringify(value)
43
+ = renderButton()
44
+ else if type === 'oneOfType'
45
+ Span.possibleType
46
+ each value, index in values
47
+ React.Fragment(key=index)
48
+ if index
49
+ Span.separator #{' | '}
50
+ Span.type(styleName=[theme])= value && value.name
51
+ = renderButton()
52
+ else
53
+ Span.type(styleName=[theme])= type
54
+ `
55
+ }))
@@ -0,0 +1,246 @@
1
+ import React, { useCallback, useMemo } from 'react'
2
+ import { pug, batch, observer, $ } from 'startupjs'
3
+ import Br from '@startupjs-ui/br'
4
+ import Input from '@startupjs-ui/input'
5
+ import Span from '@startupjs-ui/span'
6
+ import debounce from 'lodash/debounce'
7
+ import isPlainObject from 'lodash/isPlainObject'
8
+ import keys from 'lodash/keys'
9
+ import omit from 'lodash/omit'
10
+ // TODO: IMPORTANT! Refactor this to NOT import all icons
11
+ // since it HUGELY bloats the bundle size
12
+ import * as icons from '@fortawesome/free-solid-svg-icons'
13
+ import '../index.styl'
14
+
15
+ const EDITABLE_TYPES = ['string', 'number', 'boolean', 'oneOf', 'array', 'object']
16
+
17
+ const IconSelect = observer(function ({ $value, value }) {
18
+ const _icons = useMemo(
19
+ () =>
20
+ keys(omit(icons, ['fas', 'prefix'])).map(key => ({
21
+ label: key,
22
+ value: icons[key]
23
+ })),
24
+ []
25
+ )
26
+
27
+ return pug`
28
+ Input(
29
+ options=_icons
30
+ size='s'
31
+ type='select'
32
+ value=value
33
+ onChange=value => $value.set(value)
34
+ )
35
+ `
36
+ })
37
+
38
+ const JSONInput = observer(function ({ $value, type }) {
39
+ const _JSONValue = useMemo(() => {
40
+ const value = $value.get()
41
+ return value ? JSON.stringify(value) : ''
42
+ }, [$value])
43
+
44
+ const $tempJSON = $(_JSONValue)
45
+ const $badJSON = $(false)
46
+
47
+ const validateJson = useCallback( // eslint-disable-line react-hooks/exhaustive-deps
48
+ debounce(text => {
49
+ try {
50
+ if (!text) {
51
+ $value.del() // clear value if no text
52
+ } else {
53
+ const parsedValue = JSON.parse(text)
54
+ const isValidValue = parsedValue && validateByType(type, parsedValue)
55
+ if (isValidValue) {
56
+ $value.set(parsedValue)
57
+ $badJSON.set(false)
58
+ } else {
59
+ $badJSON.set(true)
60
+ }
61
+ }
62
+ } catch (error) {
63
+ $badJSON.set(true)
64
+ }
65
+ }, 300),
66
+ [$badJSON, $value]
67
+ )
68
+
69
+ function onChangeJSON (text) {
70
+ $tempJSON.set(text)
71
+ validateJson(text)
72
+ }
73
+
74
+ return pug`
75
+ Input(
76
+ inputStyleName={ badJSON: $badJSON.get() }
77
+ size='s'
78
+ type='text'
79
+ value=$tempJSON.get() || ''
80
+ onChangeText=onChangeJSON
81
+ )
82
+ `
83
+ })
84
+
85
+ const PropInput = observer(function ({ $value, extraParams = {}, options, type, value }) {
86
+ switch (type) {
87
+ case 'array':
88
+ case 'object':
89
+ // custom Select for icon objects instead of JSONInput
90
+ // when extraParams.showIconSelect is true
91
+ if (extraParams.showIconSelect) {
92
+ return pug`
93
+ IconSelect($value=$value value=value)
94
+ `
95
+ }
96
+ return pug`
97
+ JSONInput(
98
+ type=type
99
+ value=value
100
+ $value=$value
101
+ )
102
+ `
103
+ case 'string':
104
+ return pug`
105
+ Input(
106
+ size='s'
107
+ type='text'
108
+ value=value
109
+ onChangeText=value => $value.set(value)
110
+ ...extraParams
111
+ )
112
+ `
113
+ case 'number':
114
+ return pug`
115
+ Input(
116
+ size='s'
117
+ type='number'
118
+ value=value
119
+ onChangeNumber=value => $value.set(value)
120
+ ...extraParams
121
+ )
122
+ `
123
+ case 'boolean':
124
+ return pug`
125
+ Input.checkbox(
126
+ type='checkbox'
127
+ value=!!value
128
+ onChange=value => $value.set(value)
129
+ )
130
+ `
131
+ case 'oneOf':
132
+ return pug`
133
+ Input(
134
+ options=options
135
+ size='s'
136
+ type='select'
137
+ value=value
138
+ onChange=value => $value.set(value)
139
+ ...extraParams
140
+ )
141
+ `
142
+ default:
143
+ return null
144
+ }
145
+ })
146
+
147
+ const TypesSelect = observer(function ({
148
+ $props,
149
+ entry: { name, defaultValue, possibleValues, extraParams = {} }
150
+ }) {
151
+ const { names, options } = useMemo(
152
+ () =>
153
+ possibleValues.reduce(
154
+ (acc, { name, value }) => {
155
+ if (!EDITABLE_TYPES.includes(name)) return acc
156
+ acc.names.push(name)
157
+ acc.options[name] = Array.isArray(value) ? value : []
158
+ return acc
159
+ },
160
+ { names: [], options: {} }
161
+ ),
162
+ [possibleValues]
163
+ )
164
+ const $selectedValue = $(names[0])
165
+ const $value = $props[name]
166
+ const value = $value.get()
167
+
168
+ function onChange (value) {
169
+ batch(() => {
170
+ if (defaultValue !== undefined && validateByType(value, defaultValue)) {
171
+ $value.set(defaultValue)
172
+ } else {
173
+ $value.del()
174
+ }
175
+ $selectedValue.set(value)
176
+ })
177
+ }
178
+
179
+ return pug`
180
+ if names.length
181
+ Input(
182
+ options=names
183
+ showEmptyValue=false
184
+ size='s'
185
+ type='select'
186
+ value=$selectedValue.get()
187
+ onChange=onChange
188
+ )
189
+ Br(half)
190
+ PropInput(
191
+ $value=$value
192
+ extraParams=extraParams
193
+ options=options[$selectedValue.get()]
194
+ type=$selectedValue.get()
195
+ value=value
196
+ )
197
+ else
198
+ Span.unsupported -
199
+ `
200
+ })
201
+
202
+ export default observer(function ValueCell ({ $props, entry }) {
203
+ const { extraParams, name, possibleValues, type } = entry
204
+ const $value = $props[name]
205
+ const value = $value.get()
206
+
207
+ if (/^\$/.test(name)) { // hide Input for model prop
208
+ return pug`
209
+ Span.unsupported -
210
+ `
211
+ }
212
+
213
+ return pug`
214
+ if EDITABLE_TYPES.includes(type)
215
+ PropInput(
216
+ $value=$value
217
+ extraParams=extraParams
218
+ options=possibleValues
219
+ type=type
220
+ value=value
221
+ )
222
+ else if type === 'oneOfType'
223
+ TypesSelect($props=$props entry=entry)
224
+ else
225
+ Span.unsupported -
226
+ `
227
+ })
228
+
229
+ function validateByType (type, value) {
230
+ switch (type) {
231
+ case 'array':
232
+ return Array.isArray(value)
233
+ case 'object':
234
+ return isPlainObject(value)
235
+ case 'boolean':
236
+ return typeof value === 'boolean'
237
+ case 'number':
238
+ return typeof value === 'number'
239
+ case 'string':
240
+ return typeof value === 'string'
241
+ case 'oneOf':
242
+ return true
243
+ default:
244
+ return false
245
+ }
246
+ }
@@ -0,0 +1,84 @@
1
+ import React from 'react'
2
+ import { Platform } from 'react-native'
3
+ import { pug, observer, $ } from 'startupjs'
4
+ import Span from '@startupjs-ui/span'
5
+ import Tag from '@startupjs-ui/tag'
6
+ import { themed } from '@startupjs-ui/core'
7
+ import Div from '@startupjs-ui/div'
8
+ import Table from './Table'
9
+ import Tbody from './Tbody'
10
+ import Thead from './Thead'
11
+ import Tr from './Tr'
12
+ import Td from './Td'
13
+ import TypeCell from './TypeCell'
14
+ import ValueCell from './ValueCell'
15
+ import './index.styl'
16
+
17
+ export default observer(themed(function Constructor ({
18
+ Component,
19
+ extendedFrom,
20
+ entries,
21
+ $props,
22
+ style
23
+ }) {
24
+ const $showExtends = $()
25
+ function renderEntry (entry) {
26
+ const { name, type, defaultValue, possibleValues, isRequired } = entry
27
+ return pug`
28
+ Tr(key=name)
29
+ Td
30
+ Span.name(
31
+ style={
32
+ fontFamily: Platform.OS === 'ios' ? 'Menlo-Regular' : 'monospace'
33
+ }
34
+ )= name
35
+ if isRequired
36
+ Tag.required(
37
+ variant='outlined'
38
+ size='s'
39
+ color='error'
40
+ shape='rounded'
41
+ ) Required
42
+ if defaultValue != null
43
+ Span.valueDefault
44
+ Span(description) =#{' '}
45
+ Span.value= JSON.stringify(defaultValue)
46
+ Td: Span(description italic)= entry.description || '-'
47
+ Td: TypeCell(possibleValues=possibleValues type=type)
48
+ Td.vCenter: ValueCell(entry=entry $props=$props)
49
+ `
50
+ }
51
+ return pug`
52
+ Table.table(style=style)
53
+ Thead.thead
54
+ Tr
55
+ Td: Span.header PROP
56
+ Td: Span.header DESCRIPTION
57
+ Td: Span.header TYPE
58
+ Td: Span.header.right VALUE
59
+ Tbody
60
+ if extendedFrom
61
+ Div.extends
62
+ Div.collapsibleHeader(onPress=() => $showExtends.set(!$showExtends.get()))
63
+ Span(italic style={
64
+ fontFamily: Platform.OS === 'ios' ? 'Menlo-Regular' : 'monospace'
65
+ })
66
+ if $showExtends.get()
67
+ | -#{' '}
68
+ else
69
+ | +#{' '}
70
+ | Extends component props from#{' '}
71
+ Span(bold)= extendedFrom + ' '
72
+ if $showExtends.get()
73
+ | (tap to collapse)
74
+ else
75
+ | (tap to expand)
76
+ if $showExtends.get()
77
+ each entry, index in entries
78
+ if entry.extendedFrom === extendedFrom
79
+ = renderEntry(entry)
80
+ each entry, index in entries
81
+ if !entry.extendedFrom
82
+ = renderEntry(entry)
83
+ `
84
+ }))
@@ -0,0 +1,55 @@
1
+ $input = var(--color-border-main)
2
+ $header = var(--color-text-description)
3
+ $value = var(--color-text-success)
4
+ $type = var(--color-text-info)
5
+
6
+ .header
7
+ font-size 12px
8
+ letter-spacing 1px
9
+ fontFamily('normal', 600)
10
+ color $header
11
+
12
+ &.right
13
+ text-align right
14
+
15
+ .extends
16
+ border-bottom-width 2px
17
+ border-bottom-color var(--color-border-main)
18
+ background-color rgba(black, 0.03)
19
+
20
+ .collapsibleHeader
21
+ padding 1u 1u 1u 2u
22
+
23
+ .possibleValue
24
+ flex-direction row
25
+
26
+ .value
27
+ color $value
28
+ font-style italic
29
+
30
+ .valueDefault
31
+ padding-left 4u
32
+
33
+ .type
34
+ color $type
35
+ font-style italic
36
+
37
+ .checkbox
38
+ align-self flex-end
39
+
40
+ .unsupported
41
+ color var(--color-text-description)
42
+ text-align right
43
+
44
+ .separator
45
+ color var(--color-text-placeholder)
46
+
47
+ .vCenter
48
+ justify-content center
49
+
50
+ .required
51
+ margin-top 0.5u
52
+ align-self flex-start
53
+
54
+ .badJSON
55
+ color var(--color-text-error)