diff --git a/cspell.json b/cspell.json index 63dab56b..ba78afdf 100644 --- a/cspell.json +++ b/cspell.json @@ -15,6 +15,7 @@ ".git", "pnpm-lock.yaml", "node_modules", - "pnpm-workspace.yaml" + "pnpm-workspace.yaml", + "docs/package.json" ] -} \ No newline at end of file +} diff --git a/docs/app/client/authcode/page.tsx b/docs/app/client/authcode/page.tsx index 307f1a46..d164e7f7 100644 --- a/docs/app/client/authcode/page.tsx +++ b/docs/app/client/authcode/page.tsx @@ -1,18 +1,15 @@ import React from "react"; -import Image from "next/image"; +import dynamic from "next/dynamic"; +import { Loader } from "@heathmont/moon-base-tw"; import { getExamples } from "@/utils/getExamples"; -import { MDX } from "@/components/MDX"; import { ExampleSectionData } from "@/components/exampleSection/ExampleSection"; import { MainLayout } from "@/components/MainLayout"; +import { PageHeadComponent } from "@/components/PageHeadComponent"; +import { PropsTable } from "@/components/propsTable"; -import dynamic from "next/dynamic"; -import TitleTags from "@/components/TitleTags"; - +import props from "./props"; import image from "./authcode.webp"; -import { Loader } from "@heathmont/moon-base-tw"; -import { PageHeadComponent } from "@/components/PageHeadComponent"; -const TITLE = "AuthCode"; const ordered = [ "Default", "WithManualSubmit", @@ -57,7 +54,7 @@ export default async function AuthCodePage(request: {
- {/* TODO: Props table/s */} + + These are props specific to the{" "} + AuthCode component: +

+ } + data={props} + />
); diff --git a/docs/app/client/authcode/props.ts b/docs/app/client/authcode/props.ts new file mode 100644 index 00000000..f703b6f9 --- /dev/null +++ b/docs/app/client/authcode/props.ts @@ -0,0 +1,67 @@ +import { PropsTableProp } from "@/types"; + +const Props: PropsTableProp[] = [ + { + name: "onChange", + type: ["(value: string) => {}"], + description: "Callback function triggered upon a value change.", + required: true, + }, + { + name: "length", + type: ["number"], + description: "Number of digits for entering single values.", + defaultState: 6, + }, + { + name: "allowedCharacters", + type: ["alphanumeric", "numeric", "alpha"], + defaultState: "alphanumeric", + description: "Specifies the type of input characters allowed.", + }, + { + name: "autoFocus", + type: ["boolean"], + defaultState: "false", + description: + "When set to true, inputs automatically receive the keyboard focus.", + }, + { + name: "isPassword", + type: ["boolean"], + defaultState: "false", + description: + "When set to true, inputs will show entered values as obfuscated symbols.", + }, + { + name: "disabled", + type: ["boolean"], + defaultState: "false", + description: "When set to true, the AuthCode component is disabled.", + }, + { + name: "placeholder", + type: ["string"], + description: "Default placeholder for input elements.", + }, + { + name: "isValid", + type: ["boolean"], + defaultState: "true", + description: "When set to false, the AuthCode will show a error state.", + }, + { + name: "className", + type: ["string"], + description: + "Specifies the extra styles for the container that wraps the set of input elements.", + }, + { + name: "ariaLabel", + type: ["string"], + defaultState: '"Character `${i + 1}`"', + description: "Specifies the common of the aria phrase for input elements.", + }, +]; + +export default Props; diff --git a/docs/components/propsTable/PropsTableItem.tsx b/docs/components/propsTable/PropsTableItem.tsx index 2dd45967..619a9521 100644 --- a/docs/components/propsTable/PropsTableItem.tsx +++ b/docs/components/propsTable/PropsTableItem.tsx @@ -1,11 +1,26 @@ -import type { Data } from "./index"; +import { PropsTableProp, PropsTablePropTypes } from "@/types"; +import { Tag } from "@heathmont/moon-base-tw"; type PropsTableItemProps = { - prop: Data; + prop: PropsTableProp; }; const PropsTableItem = ({ prop }: PropsTableItemProps) => { - const { name, type, defaultState, description } = prop; + const { name, type, defaultState, required, description } = prop; + + const renderType = (item: PropsTablePropTypes) => { + // Check using Regex if the prop is a arrow function + const isArrowFunction = /\(([^)]+)\) => \w/.test(item); + + if (isArrowFunction) { + return item; + } else if (["number", "boolean", "string"].includes(item)) { + return item; + } else { + return `"${item}"`; + } + }; + return (
@@ -13,9 +28,14 @@ const PropsTableItem = ({ prop }: PropsTableItemProps) => { Prop

- + {name} - +

@@ -24,6 +44,12 @@ const PropsTableItem = ({ prop }: PropsTableItemProps) => {

{defaultState || "-"}

+
+ + Required + +

{required ? "Yes" : "No"}

+
Description @@ -31,7 +57,9 @@ const PropsTableItem = ({ prop }: PropsTableItemProps) => {

{description}

-

{type}

+

+ {type?.map(renderType).join(" | ")} +

); diff --git a/docs/components/propsTable/index.tsx b/docs/components/propsTable/index.tsx index f1e19b9e..bdb814e6 100644 --- a/docs/components/propsTable/index.tsx +++ b/docs/components/propsTable/index.tsx @@ -1,15 +1,9 @@ import PropsTableItem from "./PropsTableItem"; import HeaderSection from "../HeaderSection"; - -export type Data = { - name: string; - type: string; - defaultState: string | React.ReactNode; - description: string; -}; +import { type PropsTableProp } from "@/types"; type TableProps = { - data: Data[]; + data: PropsTableProp[]; title?: string; description?: string | JSX.Element; }; @@ -19,9 +13,11 @@ export const PropsTable = ({ data, title, description }: TableProps) => {

- {data.map((prop: Data) => ( - - ))} + {data + .sort((x: PropsTableProp) => (x.required ? -1 : 1)) + .map((prop: PropsTableProp) => ( + + ))}
); }; diff --git a/docs/package.json b/docs/package.json index 28cd811f..382f7c25 100644 --- a/docs/package.json +++ b/docs/package.json @@ -37,4 +37,4 @@ "tailwindcss": "^3.3.0", "typescript": "^5" } -} \ No newline at end of file +} diff --git a/docs/scripts/cli.mjs b/docs/scripts/cli.mjs index 322dd44f..c52ec3a4 100644 --- a/docs/scripts/cli.mjs +++ b/docs/scripts/cli.mjs @@ -1,16 +1,16 @@ -import { Command } from 'commander'; -import { promises as fs } from 'fs'; -import path from 'path'; +import { Command } from "commander"; +import { promises as fs } from "fs"; +import path from "path"; -// pnpm run doc moon-cli generate example +// pnpm run doc moon-cli generate example const program = new Command(); export function generateFilesContent(component, name, title) { - const _documentation = `--- + const _documentation = `--- title: ${title || name} --- `; - const _example = `"use client"; + const _example = `"use client"; import React from "react"; export const ${name} = () => { @@ -19,122 +19,136 @@ export const ${name} = () => { export default ${name} `; - const _e2e = `test('${name}: should render and match screenshot', async ({ page }) => { + const _e2e = `test('${name}: should render and match screenshot', async ({ page }) => { await expect(page).toHaveScreenshot(\`${component}-${name}.png\`, { maxDiffPixelRatio: MAX_DIFF_PIXEL_RATIO }) }) `; - return Object.assign({}, { - documentation: { - content: _documentation, - path: path.join(`docs/app/client/${component}/descriptions`, `${name}.md`) - }, - example: { - content: _example, - path: path.join(`docs/app/client/${component}/examples`, `${name}.tsx`) - }, - e2e: { - content: _e2e, - path: path.join(`docs/e2e/`, `${component}.spec.ts`) // CARE THIS JUST ADD THE END OF THE FILE - } - }) + return Object.assign( + {}, + { + documentation: { + content: _documentation, + path: path.join( + `docs/app/client/${component}/descriptions`, + `${name}.md`, + ), + }, + example: { + content: _example, + path: path.join(`docs/app/client/${component}/examples`, `${name}.tsx`), + }, + e2e: { + content: _e2e, + path: path.join(`docs/e2e/`, `${component}.spec.ts`), // CARE THIS JUST ADD THE END OF THE FILE + }, + }, + ); } -export async function writeToFile({ - contentToWrite, - path, -}) { - if (!contentToWrite) { - throw new Error('Content for writeToFile function must be provided.'); - } - if (!path) { - throw new Error('Path for writeToFile function must be provided.'); - } +export async function writeToFile({ contentToWrite, path }) { + if (!contentToWrite) { + throw new Error("Content for writeToFile function must be provided."); + } + if (!path) { + throw new Error("Path for writeToFile function must be provided."); + } - try { - await fs.writeFile(path, contentToWrite, 'utf8'); - console.log(`${path} file has been written successfully.`); - } catch (err) { - if (err instanceof Error) { - console.error('Error writing to file:', err.message); - throw err; - } + try { + await fs.writeFile(path, contentToWrite, "utf8"); + console.log(`${path} file has been written successfully.`); + } catch (err) { + if (err instanceof Error) { + console.error("Error writing to file:", err.message); + throw err; } + } } program - .name('moon-cli') - .description('CLI to some moon.io utils') - .version('0.0.1'); - -program.command('generate') - .description('Generate the entry in the file project') - .argument('', 'Right now this can be only \'example\'') - .option('--component ', 'The component of this example') - .option('--name ', 'The name of the example') - .option('--title ', 'The title of the example (optional)') - .action(async (arg, options) => { - console.log("Experimental Moon.io CLI"); - let valid = true; - if (!['example'].includes(arg)) { - valid = false; - console.log('You should select a valid type for the generation'); - } - if ( - !(typeof options.component === 'string') || - !(typeof options.name === 'string') - ) { - valid = false; - program.help() - console.log('[!] name and component is mandatory'); - } + .name("moon-cli") + .description("CLI to some moon.io utils") + .version("0.0.1"); - if (valid) { - try { - fs.stat(`docs/app/client/${options.component}`) - } catch (err) { - valid = false; - console.log(`[!!] Component ${options.component} not exists`) - } - } +program + .command("generate") + .description("Generate the entry in the file project") + .argument("<type>", "Right now this can be only 'example'") + .option("--component <component>", "The component of this example") + .option("--name <name>", "The name of the example") + .option("--title <title>", "The title of the example (optional)") + .action(async (arg, options) => { + console.log("Experimental Moon.io CLI"); + let valid = true; + if (!["example"].includes(arg)) { + valid = false; + console.log("You should select a valid type for the generation"); + } + if ( + !(typeof options.component === "string") || + !(typeof options.name === "string") + ) { + valid = false; + program.help(); + console.log("[!] name and component is mandatory"); + } - if (valid) { - const filesContent = generateFilesContent(options.component, options.name, options.title); - if (typeof options.title === "string" && options.title?.length > 0) { - // Documentation - try { - await fs.access(filesContent.documentation.path, fs.constants.F_OK); - console.log(`[!!] File ${filesContent.documentation.path} already exists`) - } catch (err) { - console.log(`[!] Creating ${filesContent.documentation.path}...`) - await writeToFile({ - contentToWrite: filesContent.documentation.content, - path: filesContent.documentation.path - }) - } - } - // Component - try { - await fs.access(filesContent.example.path, fs.constants.F_OK); - console.log(`[!!] File ${filesContent.example.path} already exists`) - } catch (err) { - console.log(`[!] Creating ${filesContent.example.path}...`) - await writeToFile({ - contentToWrite: filesContent.example.content, - path: filesContent.example.path - }) - } + if (valid) { + try { + fs.stat(`docs/app/client/${options.component}`); + } catch (err) { + valid = false; + console.log(`[!!] Component ${options.component} not exists`); + } + } - // e2e - try { - await fs.access(filesContent.e2e.path, fs.constants.F_OK); - console.log(`[!!] Adding to ${filesContent.e2e.path} e2e test`); - await fs.appendFile(filesContent.e2e.path, filesContent.e2e.content, "utf-8") - } catch (err) { - console.log(`[!!] Not exists e2e file ${filesContent.e2e.path}...`) - } + if (valid) { + const filesContent = generateFilesContent( + options.component, + options.name, + options.title, + ); + if (typeof options.title === "string" && options.title?.length > 0) { + // Documentation + try { + await fs.access(filesContent.documentation.path, fs.constants.F_OK); + console.log( + `[!!] File ${filesContent.documentation.path} already exists`, + ); + } catch (err) { + console.log(`[!] Creating ${filesContent.documentation.path}...`); + await writeToFile({ + contentToWrite: filesContent.documentation.content, + path: filesContent.documentation.path, + }); } - }); + } + // Component + try { + await fs.access(filesContent.example.path, fs.constants.F_OK); + console.log(`[!!] File ${filesContent.example.path} already exists`); + } catch (err) { + console.log(`[!] Creating ${filesContent.example.path}...`); + await writeToFile({ + contentToWrite: filesContent.example.content, + path: filesContent.example.path, + }); + } + + // e2e + try { + await fs.access(filesContent.e2e.path, fs.constants.F_OK); + console.log(`[!!] Adding to ${filesContent.e2e.path} e2e test`); + await fs.appendFile( + filesContent.e2e.path, + filesContent.e2e.content, + "utf-8", + ); + } catch (err) { + console.log(`[!!] Not exists e2e file ${filesContent.e2e.path}...`); + } + } + }); -program.parse(); \ No newline at end of file +program.parse(); diff --git a/docs/types/index.ts b/docs/types/index.ts new file mode 100644 index 00000000..b0b401ca --- /dev/null +++ b/docs/types/index.ts @@ -0,0 +1,2 @@ +export { type PropsTableProp, type PropsTablePropTypes } from "./propsTable"; +export { type NonEmptyArray } from "./utils"; diff --git a/docs/types/propsTable.ts b/docs/types/propsTable.ts new file mode 100644 index 00000000..03a488b1 --- /dev/null +++ b/docs/types/propsTable.ts @@ -0,0 +1,17 @@ +import { type ReactNode } from "react"; +import { type NonEmptyArray } from "./utils"; + +export type PropsTablePropTypes = "number" | "boolean" | "string" | string; + +export interface PropsTableProp { + /* This field is mandatory, name of the prop */ + name: string; + /* Type field is mandatory, array contains the types of the prop, should contains at least 1 value */ + type: NonEmptyArray<PropsTablePropTypes>; + /* Description is mandatory for every props */ + description: string; + /* Default is not mandatory */ + defaultState?: ReactNode; + /* The field required can be used only for required prop */ + required?: boolean; +} diff --git a/docs/types/utils.ts b/docs/types/utils.ts new file mode 100644 index 00000000..1f523e86 --- /dev/null +++ b/docs/types/utils.ts @@ -0,0 +1,2 @@ +// Type Non-Empty-Array +export type NonEmptyArray<T> = [T, ...T[]]; diff --git a/words.txt b/words.txt index 3b27d544..aad714fa 100644 --- a/words.txt +++ b/words.txt @@ -1,4 +1,6 @@ crey authcode webp -heathmont \ No newline at end of file +heathmont +frieza +beerus