diff --git a/packages/@react-spectrum/listbox/docs/ListBox.mdx b/packages/@react-spectrum/listbox/docs/ListBox.mdx new file mode 100644 index 00000000000..bfdb067c521 --- /dev/null +++ b/packages/@react-spectrum/listbox/docs/ListBox.mdx @@ -0,0 +1,58 @@ + + +import {Layout} from '@react-spectrum/docs'; +export default Layout; + +import docs from 'docs:@react-spectrum/listbox'; +import {HeaderInfo, PropTable} from '@react-spectrum/docs'; +import packageData from '../package.json'; + +```jsx import +import {ListBox, Section, Item} from '@react-spectrum/listbox'; +``` + +# ListBox + +

{docs.exports.ListBox.description}

+ + + +## Example + +```tsx example + +
+ Left + Middle + Right +
+
+ Top + Center + Bottom +
+
+``` + +## Content + +### Accessibility + +### Internationalization + +## Events + +## Props + + + +## Visual Options diff --git a/packages/@react-spectrum/listbox/src/ListBox.tsx b/packages/@react-spectrum/listbox/src/ListBox.tsx index a5c61df9c1a..9c5f4a9a332 100644 --- a/packages/@react-spectrum/listbox/src/ListBox.tsx +++ b/packages/@react-spectrum/listbox/src/ListBox.tsx @@ -36,5 +36,10 @@ function ListBox(props: SpectrumListBoxProps, ref: DOMRef) // forwardRef doesn't support generic parameters, so cast the result to the correct type // https://stackoverflow.com/questions/58469229/react-with-typescript-generics-while-using-react-forwardref + + +/** + * Listbox shows lists + */ const _ListBox = React.forwardRef(ListBox) as (props: SpectrumListBoxProps & {ref?: DOMRef}) => ReactElement; export {_ListBox as ListBox}; diff --git a/packages/@react-types/shared/src/collections.d.ts b/packages/@react-types/shared/src/collections.d.ts index 4156d1f4daa..a27e3e2383f 100644 --- a/packages/@react-types/shared/src/collections.d.ts +++ b/packages/@react-types/shared/src/collections.d.ts @@ -106,7 +106,7 @@ export interface KeyboardDelegate { /** Returns the key visually one page above the given one, or `null` for none. */ getKeyPageAbove?(key: Key): Key, - + /** Returns the first key, or `null` for none. */ getFirstKey?(): Key, diff --git a/packages/dev/docs/src/types.js b/packages/dev/docs/src/types.js index e23fe646f7f..886d7ebac23 100644 --- a/packages/dev/docs/src/types.js +++ b/packages/dev/docs/src/types.js @@ -85,7 +85,7 @@ export function Type({type}) { case 'alias': return ; default: - console.log('UNKNOWN TYPE', type); + console.log('no render component for TYPE', type); return null; } } @@ -124,7 +124,12 @@ function JoinList({elements, joiner}) { return elements .reduce((acc, v, i) => [ ...acc, - {joiner}, + + {joiner} + , ], []).slice(1); } diff --git a/packages/dev/parcel-packager-docs/DocsPackager.js b/packages/dev/parcel-packager-docs/DocsPackager.js index d0c4276ff82..d1eb577a080 100644 --- a/packages/dev/parcel-packager-docs/DocsPackager.js +++ b/packages/dev/parcel-packager-docs/DocsPackager.js @@ -11,6 +11,7 @@ */ const {Packager} = require('@parcel/plugin'); +const v8 = require('v8'); module.exports = new Packager({ async package({bundle, bundleGraph, options}) { @@ -171,21 +172,31 @@ module.exports = new Packager({ }); async function parse(asset) { - let code = await asset.getCode(); - return [asset.id, JSON.parse(code)]; + let buffer = await asset.getBuffer(); + return [asset.id, v8.deserialize(buffer)]; } +let cache = new Map(); +// cache things in pre-visit order so the references exist function walk(obj, fn, k = null) { let recurse = (obj) => { + if (cache.has(obj)) { + return cache.get(obj); + } if (Array.isArray(obj)) { - return obj.map((item, i) => walk(item, fn, k)); + let resultArray = []; + cache.set(obj, resultArray); + obj.forEach((item, i) => resultArray[i] = walk(item, fn, k)); + return resultArray; } else if (obj && typeof obj === 'object') { let res = {}; + cache.set(obj, res); for (let key in obj) { res[key] = walk(obj[key], fn, key); } return res; } else { + cache.set(obj, obj); return obj; } }; diff --git a/packages/dev/parcel-transformer-docs/DocsTransformer.js b/packages/dev/parcel-transformer-docs/DocsTransformer.js index 8d910bdfe83..c8726a057c2 100644 --- a/packages/dev/parcel-transformer-docs/DocsTransformer.js +++ b/packages/dev/parcel-transformer-docs/DocsTransformer.js @@ -15,9 +15,12 @@ const {parse} = require('@babel/parser'); const traverse = require('@babel/traverse').default; const t = require('@babel/types'); const doctrine = require('doctrine'); +const v8 = require('v8'); + module.exports = new Transformer({ async transform({asset, options}) { + let nodeCache = new Map(); if (asset.type === 'json') { return [asset]; } @@ -28,7 +31,7 @@ module.exports = new Transformer({ allowReturnOutsideFunction: true, strictMode: false, sourceType: 'module', - plugins: ['exportDefaultFrom', 'exportNamespaceFrom', 'dynamicImport', 'typescript', 'jsx'] + plugins: ['classProperties', 'exportDefaultFrom', 'exportNamespaceFrom', 'dynamicImport', 'typescript', 'jsx'] }); let exports = {}; @@ -83,33 +86,40 @@ module.exports = new Transformer({ } }); - function processExport(path) { + function processPath(path, node) { + if (path.isTSParenthesizedType()) { + return processExport(path.get('typeAnnotation'), node); + } + if (path.isTSAsExpression()) { + // not sure why I can't pass typeAnnotation instead + return processExport(path.get('expression'), node); + } if (path.isVariableDeclarator()) { if (!path.node.init) { return; } let docs = getJSDocs(path.parentPath); - let value = processExport(path.get('init')); - addDocs(value, docs); - return value; + processExport(path.get('init'), node); + addDocs(node, docs); + return node; } if (isReactForwardRef(path)) { - return processExport(path.get('arguments.0')); + return processExport(path.get('arguments.0'), node); } if (path.isFunction()) { if (isReactComponent(path)) { let props = path.node.params[0]; let docs = getJSDocs(path); - return { + return Object.assign(node, { type: 'component', props: props && props.typeAnnotation ? processExport(path.get('params.0.typeAnnotation.typeAnnotation')) : null, description: docs.description || null - }; + }); } else { // TODO: normal function } @@ -117,14 +127,17 @@ module.exports = new Transformer({ if (path.isTSTypeReference()) { if (path.node.typeParameters) { - return { + let base = processExport(path.get('typeName')); + let typeParameters = path.get('typeParameters.params').map(p => processExport(p)); + return Object.assign(node, { type: 'application', - base: processExport(path.get('typeName')), - typeParameters: path.get('typeParameters.params').map(p => processExport(p)) - }; + base, + typeParameters + }); } - return processExport(path.get('typeName')); + let base = processExport(path.get('typeName'), node); + return base; } if (path.isImportSpecifier()) { @@ -134,17 +147,17 @@ module.exports = new Transformer({ pipeline: 'docs-json' }); - return { + return Object.assign(node, { type: 'reference', local: path.node.local.name, imported: path.node.imported.name, specifier: path.parent.source.value - }; + }); } if (path.isTSTypeAliasDeclaration()) { let docs = getJSDocs(path); - return { + return Object.assign(node, { type: 'alias', id: `${asset.filePath}:${path.node.id.name}`, name: path.node.id.name, @@ -152,7 +165,7 @@ module.exports = new Transformer({ typeParameters: path.node.typeParameters ? path.get('typeParameters.params').map(p => processExport(p)) : [], description: docs.description || null, access: docs.access - }; + }); } if (path.isTSInterfaceDeclaration()) { @@ -162,21 +175,21 @@ module.exports = new Transformer({ if (property) { properties[property.name] = property; } else { - console.log('UNKNOWN PROPERTY', propertyPath.node); + console.log('UNKNOWN PROPERTY interface declaration', propertyPath.node); } } let exts = path.node.extends ? path.get('extends').map(e => processExport(e)) : []; let docs = getJSDocs(path); - return addDocs({ + return Object.assign(node, addDocs({ type: 'interface', id: `${asset.filePath}:${path.node.id.name}`, name: path.node.id.name, extends: exts, properties, typeParameters: path.node.typeParameters ? path.get('typeParameters.params').map(p => processExport(p)) : [] - }, docs); + }, docs)); } if (path.isTSTypeLiteral()) { @@ -186,31 +199,31 @@ module.exports = new Transformer({ if (property) { properties[property.name] = property; } else { - console.log('UNKNOWN PROPERTY', member.node); + console.log('UNKNOWN PROPERTY (type literal)', member.node); } } - return { + return Object.assign(node, { type: 'object', properties - }; + }); } if (path.isTSPropertySignature()) { let name = t.isStringLiteral(path.node.key) ? path.node.key.value : path.node.key.name; let docs = getJSDocs(path); - return addDocs({ + return Object.assign(node, addDocs({ type: 'property', name, value: processExport(path.get('typeAnnotation.typeAnnotation')), optional: path.node.optional || false - }, docs); + }, docs)); } if (path.isTSMethodSignature()) { let name = t.isStringLiteral(path.node.key) ? path.node.key.value : path.node.key.name; let docs = getJSDocs(path); - return addDocs({ + return Object.assign(node, addDocs({ type: 'property', name, value: { @@ -227,84 +240,84 @@ module.exports = new Transformer({ ? path.get('typeParameters.params').map(p => processExport(p)) : [] } - }, docs); + }, docs)); } if (path.isTSExpressionWithTypeArguments()) { if (path.node.typeParameters) { - return { + return Object.assign(node, { type: 'application', base: processExport(path.get('expression')), typeParameters: path.get('typeParameters.params').map(p => processExport(p)) - }; + }); } - return processExport(path.get('expression')); + return processExport(path.get('expression'), node); } if (path.isIdentifier()) { let binding = path.scope.getBinding(path.node.name); if (!binding) { - return { + return Object.assign(node, { type: 'identifier', name: path.node.name - }; + }); } - - return processExport(binding.path); + let bindings = processExport(binding.path, node); + return bindings; } if (path.isTSBooleanKeyword()) { - return {type: 'boolean'}; + return Object.assign(node, {type: 'boolean'}); } if (path.isTSStringKeyword()) { - return {type: 'string'}; + return Object.assign(node, {type: 'string'}); } if (path.isTSNumberKeyword()) { - return {type: 'number'}; + return Object.assign(node, {type: 'number'}); } if (path.isTSAnyKeyword()) { - return {type: 'any'}; + return Object.assign(node, {type: 'any'}); } if (path.isTSNullKeyword()) { - return {type: 'null'}; + return Object.assign(node, {type: 'null'}); } if (path.isTSVoidKeyword()) { - return {type: 'void'}; + return Object.assign(node, {type: 'void'}); } if (path.isTSObjectKeyword()) { - return {type: 'object'}; // ??? + return Object.assign(node, {type: 'object'}); // ??? } if (path.isTSArrayType()) { - return { + return Object.assign(node, { type: 'array', elementType: processExport(path.get('elementType')) - }; + }); } if (path.isTSUnionType()) { - return { + return Object.assign(node, { type: 'union', elements: path.get('types').map(t => processExport(t)) - }; + }); } if (path.isTSLiteralType()) { - return { + return Object.assign(node, { type: typeof path.node.literal.value, value: path.node.literal.value - }; + }); } if (path.isTSFunctionType() || path.isTSConstructorType()) { - return { + return Object.assign(node, { type: 'function', parameters: path.get('parameters').map(p => ({ type: 'parameter', @@ -313,27 +326,36 @@ module.exports = new Transformer({ })), return: path.node.typeAnnotation ? processExport(path.get('typeAnnotation.typeAnnotation')) : {type: 'any'}, typeParameters: path.node.typeParameters ? path.get('typeParameters.params').map(p => processExport(p)) : [] - }; + }); } if (path.isTSIntersectionType()) { - return { + return Object.assign(node, { type: 'intersection', types: path.get('types').map(p => processExport(p)) - }; + }); } if (path.isTSTypeParameter()) { - return { + return Object.assign(node, { type: 'typeParameter', name: path.node.name, default: path.node.default ? processExport(path.get('default')) : null - }; + }); } console.log('UNKNOWN TYPE', path.node.type); } + function processExport(path, node = {}) { + if (nodeCache.has(path)) { + return nodeCache.get(path); + } else { + nodeCache.set(path, node); + return processPath(path, node); + } + } + function isReactForwardRef(path) { return isReactCall(path, 'forwardRef'); } @@ -479,7 +501,8 @@ module.exports = new Transformer({ // console.log(exports) asset.type = 'json'; - asset.setCode(JSON.stringify(exports, false, 2)); + let buffer = v8.serialize(exports); + asset.setBuffer(buffer); return [asset]; } });