From a57393b1d9edd38973192f6415d7a4a539b18758 Mon Sep 17 00:00:00 2001 From: Kenji Shiroma Date: Mon, 23 Oct 2023 13:30:30 +1000 Subject: [PATCH] feat(#80): component table --- .../design-system/components/alert/code.mdoc | 12 +-- .../code-content/code-content.component.tsx | 22 ++++- .../navigation/navigation.component.tsx | 5 +- .../src/components/code/code.component.tsx | 2 + .../component-props-table.component.tsx | 99 ++++++++++--------- packages/ui/generate-component-types.cjs | 66 +++++++------ .../list-box-option.component.tsx | 3 + .../list-box-section.component.tsx | 3 + .../list-box/list-box.component.tsx | 3 + .../components/popover/popover.component.tsx | 4 +- .../components/popover/popover.types.ts | 1 + .../components/add-ons/add-ons.component.tsx | 3 + .../default-add-on.component.tsx | 3 + .../icon-add-on/icon-add-on.component.tsx | 3 + .../text-add-on/text-add-on.component.tsx | 3 + .../supporting-text.component.tsx | 3 + 16 files changed, 144 insertions(+), 91 deletions(-) diff --git a/apps/site/content/design-system/components/alert/code.mdoc b/apps/site/content/design-system/components/alert/code.mdoc index f290eb330..13e762906 100644 --- a/apps/site/content/design-system/components/alert/code.mdoc +++ b/apps/site/content/design-system/components/alert/code.mdoc @@ -1,4 +1,4 @@ -## Looks +### Looks ```jsx
@@ -23,7 +23,7 @@ --- -## Text +### Text ```jsx
@@ -48,7 +48,7 @@ --- -## Heading +### Heading ```jsx @@ -61,7 +61,7 @@ --- -## Custom +### Custom ```jsx @@ -71,7 +71,7 @@ --- -## Dismissible +### Dismissible ```jsx @@ -81,7 +81,7 @@ --- -## Controlled +### Controlled ```jsx () => { diff --git a/apps/site/src/app/design-system/[...component]/components/content-tabs/components/code-content/code-content.component.tsx b/apps/site/src/app/design-system/[...component]/components/content-tabs/components/code-content/code-content.component.tsx index c1d4fbb59..840205cac 100644 --- a/apps/site/src/app/design-system/[...component]/components/content-tabs/components/code-content/code-content.component.tsx +++ b/apps/site/src/app/design-system/[...component]/components/content-tabs/components/code-content/code-content.component.tsx @@ -1,8 +1,10 @@ 'use client'; +import { DocumentElement } from '@keystatic/core'; import { DocumentRenderer } from '@keystatic/core/renderer'; import { Button, Container, Grid, Item } from '@westpac/ui'; import { NewWindowIcon } from '@westpac/ui/icon'; +import { useMemo } from 'react'; import { ComponentPropsTable } from '@/components/component-props-table'; import { Code } from '@/components/content-blocks/typography'; @@ -14,6 +16,15 @@ import { TableOfContents } from '../intro/components'; import { type CodeContentProps } from '.'; export function CodeContent({ content, westpacUIInfo, componentProps, subComponentProps }: CodeContentProps) { + const tableOfContents = useMemo(() => { + return content.reduce((acc, item: DocumentElement & { level?: number }) => { + if (item.type === 'heading' && item?.level && item.level <= 3) { + return [...acc, { title: item.children[0].text as string }]; + } + return acc; + }, [] as { title: string }[]); + }, [content]); + return ( <>
@@ -58,14 +69,17 @@ export function CodeContent({ content, westpacUIInfo, componentProps, subCompone - +
- - - +
+ +

Development examples

+ +
+
Props diff --git a/apps/site/src/app/design-system/components/sidebar/components/navigation/navigation.component.tsx b/apps/site/src/app/design-system/components/sidebar/components/navigation/navigation.component.tsx index a70bdd8e5..179dde3be 100644 --- a/apps/site/src/app/design-system/components/sidebar/components/navigation/navigation.component.tsx +++ b/apps/site/src/app/design-system/components/sidebar/components/navigation/navigation.component.tsx @@ -53,9 +53,10 @@ function Group({ label, level, crumbs, children, ...props }: GroupProps) { {open && ( diff --git a/apps/site/src/components/code/code.component.tsx b/apps/site/src/components/code/code.component.tsx index 7e877d6b4..5db8dc811 100644 --- a/apps/site/src/components/code/code.component.tsx +++ b/apps/site/src/components/code/code.component.tsx @@ -1,6 +1,7 @@ 'use client'; import React, { Fragment, useCallback, useMemo, useState } from 'react'; import { LiveProvider } from 'react-live'; +import { useOverlayTriggerState } from 'react-stately'; import { StaticCode } from '../static-code'; @@ -13,6 +14,7 @@ const LIVE_SCOPE = { useState, useCallback, useMemo, + useOverlayTriggerState, Fragment, React, }; diff --git a/apps/site/src/components/component-props-table/component-props-table.component.tsx b/apps/site/src/components/component-props-table/component-props-table.component.tsx index 6b0af829d..0bc67f5fe 100644 --- a/apps/site/src/components/component-props-table/component-props-table.component.tsx +++ b/apps/site/src/components/component-props-table/component-props-table.component.tsx @@ -1,4 +1,5 @@ import { Badge, Table } from '@westpac/ui'; +import { clsx } from 'clsx'; import React from 'react'; import { type ComponentPropsTableProps } from './component-props-table.types'; @@ -6,56 +7,58 @@ import { type ComponentPropsTableProps } from './component-props-table.types'; export function ComponentPropsTable({ className, componentProps, ...props }: ComponentPropsTableProps) { console.dir(componentProps, { depth: null }); return ( - - {componentProps.displayName} props - - - {[ - { label: 'Property', className: 'w-1/12' }, - { label: 'Type', className: 'w-1/12' }, - { label: 'Default', className: 'w-1/12' }, - { label: 'Required', className: 'w-1/12' }, - { label: 'Description', className: 'w-3/12' }, - ].map(({ label, className }) => ( - - {label} - - ))} - - - - {Object.entries(componentProps.props || {}).map(([key, value]) => { - const type = value.type.name; - const defaultValue = value.defaultValue?.value; - const required = value.required ? 'true' : 'false'; +
+
+ {componentProps.displayName} props + + + {[ + { label: 'Property', className: 'w-1/12' }, + { label: 'Type', className: 'w-1/12' }, + { label: 'Default', className: 'w-1/12' }, + { label: 'Required', className: 'w-1/12' }, + { label: 'Description', className: 'w-3/12' }, + ].map(({ label, className }) => ( + + {label} + + ))} + + + + {Object.entries(componentProps.props || {}).map(([key, value]) => { + const type = value.type.name; + const defaultValue = value.defaultValue?.value; + const required = value.required ? 'true' : 'false'; - return ( - - {key} - - {type && ( - - {type} - - )} - - - {defaultValue && ( + return ( + + {key} + + {type && ( + + {type} + + )} + + + {defaultValue && ( + + {defaultValue} + + )} + + - {defaultValue} + {required} - )} - - - - {required} - - - {value.description} - - ); - })} - -
+ + {value.description} + + ); + })} + + +
); } diff --git a/packages/ui/generate-component-types.cjs b/packages/ui/generate-component-types.cjs index 706b1869f..5163c0f4e 100644 --- a/packages/ui/generate-component-types.cjs +++ b/packages/ui/generate-component-types.cjs @@ -29,38 +29,44 @@ const TYPES_TO_BE_IGNORED = [ const results = await glob(components); const data = Object.fromEntries( - tsConfigParser.parse(results).map(({ displayName, description, props, filePath, ...rest }) => { + tsConfigParser.parse(results).reduce((acc, { displayName, description, props, filePath, tags }) => { + if (tags.private !== undefined) { + return acc; + } return [ - filePath.replace(process.cwd(), '').replace('/src/components/', '').replace('src/components/', ''), - { - displayName, - description, - // Sort the required props before the non-required props, then sort alphabetically - props: Object.fromEntries( - Object.values(props) - .sort((a, b) => { - if (a.required !== b.required) { - if (a.required) return -1; - return 1; - } - return a.name.localeCompare(b.name); - }) - .filter(a => { - if (TYPES_TO_BE_IGNORED.includes(a.parent ? a.parent.name : '')) { - return false; - } - return true; - }) - .map(a => { - if (a.name === 'tag' && a.type.name.indexOf('more ...') !== -1) { - return [a.name, { ...a, type: { ...a.type, name: 'keyof IntrinsicElements' } }]; - } - return [a.name, a]; - }), - ), - }, + ...acc, + [ + filePath.replace(process.cwd(), '').replace('/src/components/', '').replace('src/components/', ''), + { + displayName, + description, + // Sort the required props before the non-required props, then sort alphabetically + props: Object.fromEntries( + Object.values(props) + .sort((a, b) => { + if (a.required !== b.required) { + if (a.required) return -1; + return 1; + } + return a.name.localeCompare(b.name); + }) + .filter(a => { + if (TYPES_TO_BE_IGNORED.includes(a.parent ? a.parent.name : '')) { + return false; + } + return true; + }) + .map(a => { + if (a.name === 'tag' && a.type.name.indexOf('more ...') !== -1) { + return [a.name, { ...a, type: { ...a.type, name: 'keyof IntrinsicElements' } }]; + } + return [a.name, a]; + }), + ), + }, + ], ]; - }), + }, []), ); // Create the output folder if it doesn't exist diff --git a/packages/ui/src/components/autocomplete/components/list-box/components/list-box-option/list-box-option.component.tsx b/packages/ui/src/components/autocomplete/components/list-box/components/list-box-option/list-box-option.component.tsx index fa1d02f80..9855cb81f 100644 --- a/packages/ui/src/components/autocomplete/components/list-box/components/list-box-option/list-box-option.component.tsx +++ b/packages/ui/src/components/autocomplete/components/list-box/components/list-box-option/list-box-option.component.tsx @@ -10,6 +10,9 @@ interface OptionProps { state: ListState; } +/** + * @private + */ export function Option({ item, state }: OptionProps) { const ref = React.useRef(null); diff --git a/packages/ui/src/components/autocomplete/components/list-box/components/list-box-section/list-box-section.component.tsx b/packages/ui/src/components/autocomplete/components/list-box/components/list-box-section/list-box-section.component.tsx index f71e63558..3f7c1e7b3 100644 --- a/packages/ui/src/components/autocomplete/components/list-box/components/list-box-section/list-box-section.component.tsx +++ b/packages/ui/src/components/autocomplete/components/list-box/components/list-box-section/list-box-section.component.tsx @@ -5,6 +5,9 @@ import { Option } from '../list-box-option/index.js'; import { type ListBoxSectionProps } from './list-box-section.types.js'; +/** + * @private + */ export function ListBoxSection({ section, state }: ListBoxSectionProps) { const { itemProps, headingProps, groupProps } = useListBoxSection({ heading: section.rendered, diff --git a/packages/ui/src/components/autocomplete/components/list-box/list-box.component.tsx b/packages/ui/src/components/autocomplete/components/list-box/list-box.component.tsx index a554dc60a..c5f1dfab5 100644 --- a/packages/ui/src/components/autocomplete/components/list-box/list-box.component.tsx +++ b/packages/ui/src/components/autocomplete/components/list-box/list-box.component.tsx @@ -4,6 +4,9 @@ import { useListBox } from 'react-aria'; import { ListBoxSection, Option } from './components/index.js'; import { ListBoxProps } from './list-box.types.js'; +/** + * @private + */ export function ListBox(props: ListBoxProps) { const ref = React.useRef(null); diff --git a/packages/ui/src/components/autocomplete/components/popover/popover.component.tsx b/packages/ui/src/components/autocomplete/components/popover/popover.component.tsx index 3548f9254..410e1da56 100644 --- a/packages/ui/src/components/autocomplete/components/popover/popover.component.tsx +++ b/packages/ui/src/components/autocomplete/components/popover/popover.component.tsx @@ -3,7 +3,9 @@ import * as React from 'react'; import { DismissButton, Overlay, usePopover } from 'react-aria'; import { PopoverProps } from './popover.types.js'; - +/** + * @private + */ export function Popover(props: PopoverProps) { const ref = React.useRef(null); const { popoverRef = ref, state, children, className, isNonModal, portalContainer } = props; diff --git a/packages/ui/src/components/autocomplete/components/popover/popover.types.ts b/packages/ui/src/components/autocomplete/components/popover/popover.types.ts index 7bb3944c8..355968d1b 100644 --- a/packages/ui/src/components/autocomplete/components/popover/popover.types.ts +++ b/packages/ui/src/components/autocomplete/components/popover/popover.types.ts @@ -2,6 +2,7 @@ import { HTMLAttributes, ReactNode } from 'react'; import { type AriaPopoverProps } from 'react-aria'; import { type OverlayTriggerState } from 'react-stately'; +// @private export type PopoverProps = Omit & { /** * Popover content diff --git a/packages/ui/src/components/input-field/components/add-ons/add-ons.component.tsx b/packages/ui/src/components/input-field/components/add-ons/add-ons.component.tsx index 0b6f3689d..5b22433b1 100644 --- a/packages/ui/src/components/input-field/components/add-ons/add-ons.component.tsx +++ b/packages/ui/src/components/input-field/components/add-ons/add-ons.component.tsx @@ -4,6 +4,9 @@ import { styles } from './add-ons.styles.js'; import { InputAddOnProps } from './add-ons.types.js'; import { DefaultAddOn, IconAddOn, TextAddOn } from './components/index.js'; +/** + * @private + */ export const InputAddOn = ({ position, icon: Icon, diff --git a/packages/ui/src/components/input-field/components/add-ons/components/default-add-on/default-add-on.component.tsx b/packages/ui/src/components/input-field/components/add-ons/components/default-add-on/default-add-on.component.tsx index b9c7aac0f..70b0b0842 100644 --- a/packages/ui/src/components/input-field/components/add-ons/components/default-add-on/default-add-on.component.tsx +++ b/packages/ui/src/components/input-field/components/add-ons/components/default-add-on/default-add-on.component.tsx @@ -3,6 +3,9 @@ import React from 'react'; import { styles } from './default-add-on.styles.js'; import { type DefaultAddOnProps } from './default-add-on.types.js'; +/** + * @private + */ export const DefaultAddOn = ({ position, className, children, ...props }: DefaultAddOnProps) => { return (
diff --git a/packages/ui/src/components/input-field/components/add-ons/components/icon-add-on/icon-add-on.component.tsx b/packages/ui/src/components/input-field/components/add-ons/components/icon-add-on/icon-add-on.component.tsx index ceba44ba0..415cfd6a8 100644 --- a/packages/ui/src/components/input-field/components/add-ons/components/icon-add-on/icon-add-on.component.tsx +++ b/packages/ui/src/components/input-field/components/add-ons/components/icon-add-on/icon-add-on.component.tsx @@ -3,6 +3,9 @@ import React from 'react'; import { styles } from './icon-add-on.styles.js'; import { type IconAddOnProps } from './icon-add-on.types.js'; +/** + * @private + */ export const IconAddOn = ({ position, children, size, className, ...props }: IconAddOnProps) => { return (
diff --git a/packages/ui/src/components/input-field/components/add-ons/components/text-add-on/text-add-on.component.tsx b/packages/ui/src/components/input-field/components/add-ons/components/text-add-on/text-add-on.component.tsx index b59e2db53..192d4ed94 100644 --- a/packages/ui/src/components/input-field/components/add-ons/components/text-add-on/text-add-on.component.tsx +++ b/packages/ui/src/components/input-field/components/add-ons/components/text-add-on/text-add-on.component.tsx @@ -3,6 +3,9 @@ import React from 'react'; import { styles } from './text-add-on.styles.js'; import { type TextAddOnProps } from './text-add-on.types.js'; +/** + * @private + */ export const TextAddOn = ({ position, className, size, id, children, ...props }: TextAddOnProps) => { return (
diff --git a/packages/ui/src/components/input-field/components/supporting-text/supporting-text.component.tsx b/packages/ui/src/components/input-field/components/supporting-text/supporting-text.component.tsx index ac9883676..3f92d9aaf 100644 --- a/packages/ui/src/components/input-field/components/supporting-text/supporting-text.component.tsx +++ b/packages/ui/src/components/input-field/components/supporting-text/supporting-text.component.tsx @@ -3,6 +3,9 @@ import React from 'react'; import { styles } from './supporting-text.styles.js'; import { type SupportingTextProps } from './supporting-text.types.js'; +/** + * @private + */ export function SupportingText({ className, tag: Tag = 'p', children, ...props }: SupportingTextProps) { return (