@forge/cli

12.23.0-next.7-experimental-44b7a1213.0.0-next.11
out/command-line/view/module-view.js
~out/command-line/view/module-view.jsModified
+113
Index: package/out/command-line/view/module-view.js
===================================================================
--- package/out/command-line/view/module-view.js
+++ package/out/command-line/view/module-view.js
@@ -7,8 +7,9 @@
 const path_1 = tslib_1.__importDefault(require("path"));
 const semver_1 = tslib_1.__importDefault(require("semver"));
 class ModuleView {
     ui;
+    static MODULE_DETAILS_WIDTH = 100;
     constructor(ui) {
         this.ui = ui;
     }
     async promptForList(message, choices) {
@@ -159,7 +160,119 @@
             }
         }
         this.emptyLine();
     }
+    async promptForModuleSelection(message, templates) {
+        const templatesByKey = new Map(templates.map((template) => [template.moduleKey, template]));
+        const selectedKey = await this.ui.promptForList(message, templates.map((template) => template.moduleKey), { format: (moduleKey) => this.formatModuleChoice(moduleKey, templatesByKey, templates) }, 10);
+        const selectedTemplate = templatesByKey.get(selectedKey);
+        if (!selectedTemplate) {
+            throw new Error(cli_shared_1.Text.module.list.errorFailedToResolveModule(selectedKey));
+        }
+        return selectedTemplate;
+    }
+    renderModuleList(templates) {
+        const templatesByProduct = new Map();
+        for (const template of templates) {
+            const group = templatesByProduct.get(template.product) ?? [];
+            group.push(template);
+            templatesByProduct.set(template.product, group);
+        }
+        const groups = Array.from(templatesByProduct.entries());
+        groups.forEach(([product, group], groupIndex) => {
+            this.info(`[${this.formatProductName(product)}]`);
+            const rows = group.map((template) => ({
+                key: template.moduleKey,
+                ui: this.formatUiFramework(template),
+                description: template.description
+            }));
+            const keyWidth = Math.max(...rows.map((row) => row.key.length));
+            const uiWidth = Math.max(...rows.map((row) => row.ui.length));
+            for (const row of rows) {
+                const dots = '.'.repeat(Math.max(3, keyWidth - row.key.length + 3));
+                const ui = row.ui.padEnd(uiWidth);
+                this.info(`  ${row.key} ${dots} ${ui}  ${row.description}`);
+            }
+            if (groupIndex < groups.length - 1) {
+                this.emptyLine();
+            }
+        });
+    }
+    renderModuleDetails(template) {
+        const divider = '═'.repeat(ModuleView.MODULE_DETAILS_WIDTH);
+        this.emptyLine();
+        this.info(template.moduleKey);
+        this.info(chalk_1.default.dim(divider));
+        this.emptyLine();
+        if (template.longDescription) {
+            this.info(cli_shared_1.Text.module.show.descriptionHeader);
+            this.renderWrappedText(template.longDescription, 1);
+            this.emptyLine();
+        }
+        if (template.documentationUrl) {
+            this.info(cli_shared_1.Text.module.show.documentationHeading);
+            this.info(`  ${template.documentationUrl}`);
+            this.emptyLine();
+        }
+        this.info(chalk_1.default.dim(divider));
+        this.info(cli_shared_1.Text.module.show.browseModulesHint);
+        this.emptyLine();
+    }
+    formatModuleChoice(moduleKey, templatesByKey, templates) {
+        const template = templatesByKey.get(moduleKey);
+        if (!template) {
+            return moduleKey;
+        }
+        const keyWidth = Math.max(...templates.map((item) => item.moduleKey.length));
+        const uiWidth = Math.max(...templates.map((item) => this.formatUiFramework(item).length));
+        const key = template.moduleKey.padEnd(keyWidth);
+        const ui = this.formatUiFramework(template).padEnd(uiWidth);
+        const description = template.description || '';
+        return `${key}  ${ui}  ${description}`;
+    }
+    formatUiFramework(template) {
+        const frameworkOrder = ['ui-kit', 'custom-ui'];
+        const frameworks = new Set();
+        if (template.uiFramework) {
+            frameworks.add(template.uiFramework);
+        }
+        for (const variant of Object.keys(template.variants ?? {})) {
+            frameworks.add(variant);
+        }
+        const values = Array.from(frameworks).sort((a, b) => frameworkOrder.indexOf(a) - frameworkOrder.indexOf(b));
+        return `[${values.length > 0 ? values.join(', ') : cli_shared_1.Text.module.list.noneUi}]`;
+    }
+    formatProductName(product) {
+        return product
+            .split('-')
+            .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
+            .join(' ');
+    }
+    renderWrappedText(text, indentSize) {
+        const indent = ' '.repeat(indentSize);
+        const width = ModuleView.MODULE_DETAILS_WIDTH - indentSize;
+        for (const line of this.wrapText(text, width)) {
+            this.info(`${indent}${line}`);
+        }
+    }
+    wrapText(text, width) {
+        const words = text.trim().split(/\s+/).filter(Boolean);
+        if (words.length === 0) {
+            return [''];
+        }
+        const lines = [];
+        let currentLine = words[0];
+        for (const word of words.slice(1)) {
+            if (`${currentLine} ${word}`.length > width) {
+                lines.push(currentLine);
+                currentLine = word;
+            }
+            else {
+                currentLine = `${currentLine} ${word}`;
+            }
+        }
+        lines.push(currentLine);
+        return lines;
+    }
 }
 exports.ModuleView = ModuleView;
 //# sourceMappingURL=module-view.js.map
\ No newline at end of file