MDL-87909 core: Include @moodlehq/design-system js
This commit also includes the @types/react, and teaches typescript how to consume the design system definition files.
This commit is contained in:
committed by
Adrian Greeve
parent
b46a8f8c3e
commit
780f9fff56
@@ -167,8 +167,12 @@ export function generateAliases() {
|
||||
|
||||
// Build TS paths for tsconfig.aliases.json
|
||||
/** @type {Record<string, string[]>} */
|
||||
const tsPaths = {};
|
||||
tsPaths["@moodle/lms/core/*"] = ["./public/lib/js/esm/src/*"]; // Always include core alias.
|
||||
const tsPaths = {
|
||||
// Always include core alias.
|
||||
"@moodle/lms/core/*": ["./public/lib/js/esm/src/*"],
|
||||
// Add the design system alias for TypeScript.
|
||||
"@moodlehq/design-system": ["./lib/js/bundles/design-system/index.d.ts"]
|
||||
};
|
||||
|
||||
for (const [componentPath, componentName] of Object.entries(componentPathMap)) {
|
||||
const reactSrcDir = path.join(rootDir, componentPath, "js", "esm", "src");
|
||||
|
||||
Vendored
+5
@@ -60,6 +60,11 @@ module.exports = grunt => {
|
||||
(async() => {
|
||||
try {
|
||||
const {watchComponents} = await import('../../.esbuild/plugin/plugincomponents.mjs');
|
||||
const { generateAliases } = await import('../../.esbuild/generate-aliases.mjs');
|
||||
const { buildPluginComponents } = await import('../../.esbuild/plugin/plugincomponents.mjs');
|
||||
|
||||
generateAliases();
|
||||
await buildPluginComponents(isDev);
|
||||
|
||||
const ctx = await watchComponents(true, onRebuild);
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { ButtonHTMLAttributes } from 'react';
|
||||
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
label: string;
|
||||
variant?: string;
|
||||
size?: 'sm' | 'lg';
|
||||
}
|
||||
export declare const Button: ({ label, variant, size, className, type, ...props }: ButtonProps) => import("react/jsx-runtime").JSX.Element;
|
||||
@@ -0,0 +1 @@
|
||||
export * from './Button';
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Button } from './button';
|
||||
export type { ButtonProps } from './button';
|
||||
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
||||
export * from './components';
|
||||
@@ -0,0 +1,31 @@
|
||||
import { jsx } from "react/jsx-runtime";
|
||||
const allowedVariants = [
|
||||
"primary",
|
||||
"secondary",
|
||||
"danger",
|
||||
"outline-primary",
|
||||
"outline-secondary",
|
||||
"outline-danger"
|
||||
];
|
||||
const Button = ({
|
||||
label,
|
||||
variant,
|
||||
size,
|
||||
className,
|
||||
type = "button",
|
||||
...props
|
||||
}) => {
|
||||
const resolvedVariant = variant && allowedVariants.includes(variant) ? variant : "primary";
|
||||
const classes = ["mds-btn", "btn", `btn-${resolvedVariant}`];
|
||||
if (size) {
|
||||
classes.push(`btn-${size}`);
|
||||
}
|
||||
if (className) {
|
||||
classes.push(className);
|
||||
}
|
||||
return /* @__PURE__ */ jsx("button", { className: classes.join(" "), type, ...props, children: label });
|
||||
};
|
||||
export {
|
||||
Button
|
||||
};
|
||||
//# sourceMappingURL=index.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sources":["../components/button/Button.tsx"],"sourcesContent":["import type { ButtonHTMLAttributes } from 'react';\n\ntype ButtonVariant =\n | 'primary'\n | 'secondary'\n | 'danger'\n | 'outline-primary'\n | 'outline-secondary'\n | 'outline-danger';\n\nexport interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n label: string;\n variant?: string;\n size?: 'sm' | 'lg';\n}\n\nconst allowedVariants: ButtonVariant[] = [\n 'primary',\n 'secondary',\n 'danger',\n 'outline-primary',\n 'outline-secondary',\n 'outline-danger',\n];\n\nexport const Button = ({\n label,\n variant,\n size,\n className,\n type = 'button',\n ...props\n}: ButtonProps) => {\n const resolvedVariant =\n variant && allowedVariants.includes(variant as ButtonVariant)\n ? variant\n : 'primary';\n\n const classes = ['mds-btn', 'btn', `btn-${resolvedVariant}`];\n if (size) {\n classes.push(`btn-${size}`);\n }\n if (className) {\n classes.push(className);\n }\n\n return (\n <button className={classes.join(' ')} type={type} {...props}>\n {label}\n </button>\n );\n};\n"],"names":[],"mappings":";AAgBA,MAAM,kBAAmC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,MAAM,SAAS,CAAC;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,GAAG;AACL,MAAmB;AACjB,QAAM,kBACJ,WAAW,gBAAgB,SAAS,OAAwB,IACxD,UACA;AAEN,QAAM,UAAU,CAAC,WAAW,OAAO,OAAO,eAAe,EAAE;AAC3D,MAAI,MAAM;AACR,YAAQ,KAAK,OAAO,IAAI,EAAE;AAAA,EAC5B;AACA,MAAI,WAAW;AACb,YAAQ,KAAK,SAAS;AAAA,EACxB;AAEA,SACE,oBAAC,UAAA,EAAO,WAAW,QAAQ,KAAK,GAAG,GAAG,MAAa,GAAG,OACnD,UAAA,MAAA,CACH;AAEJ;"}
|
||||
@@ -0,0 +1 @@
|
||||
The content of this directory is automatically managed by the `npm install` and `npm update` commands.
|
||||
@@ -18,4 +18,15 @@
|
||||
<licenseversion/>
|
||||
<repository>https://github.com/facebook/react</repository>
|
||||
</library>
|
||||
<library>
|
||||
<location>js/bundles/design-system</location>
|
||||
<name>@moodlehq/design-system</name>
|
||||
<description>The Moodle HQ design system based on React</description>
|
||||
<version>2.1.1</version>
|
||||
<license>GNU</license>
|
||||
<repository>https://github.com/moodlehq/design-system</repository>
|
||||
<copyrights>
|
||||
<copyright>Moodle HQ</copyright>
|
||||
</copyrights>
|
||||
</library>
|
||||
</libraries>
|
||||
|
||||
Generated
+2
-3
@@ -16,6 +16,7 @@
|
||||
"@babel/eslint-parser": "^7.21.3",
|
||||
"@babel/eslint-plugin": "7.19.1",
|
||||
"@babel/preset-env": "7.16.11",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@typescript-eslint/parser": "^8.53.1",
|
||||
"@xmldom/xmldom": "^0.8.7",
|
||||
@@ -2227,7 +2228,6 @@
|
||||
"integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"csstype": "^3.2.2"
|
||||
}
|
||||
@@ -4058,8 +4058,7 @@
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
||||
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ctype": {
|
||||
"version": "0.5.3",
|
||||
|
||||
+3
-2
@@ -10,15 +10,16 @@
|
||||
"upgradenote": "node .grunt/upgradenotes.mjs create"
|
||||
},
|
||||
"dependencies": {
|
||||
"@moodlehq/design-system": "^2.1",
|
||||
"react": "^19.1",
|
||||
"react-dom": "^19.1",
|
||||
"@moodlehq/design-system": "^2.1"
|
||||
"react-dom": "^19.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.17.5",
|
||||
"@babel/eslint-parser": "^7.21.3",
|
||||
"@babel/eslint-plugin": "7.19.1",
|
||||
"@babel/preset-env": "7.16.11",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@typescript-eslint/parser": "^8.53.1",
|
||||
"@xmldom/xmldom": "^0.8.7",
|
||||
|
||||
@@ -98,7 +98,7 @@ class import_map implements \JsonSerializable {
|
||||
*/
|
||||
protected function add_standard_imports(): void {
|
||||
$this->add_import('@moodle/lms/', path: 'js/esm/build', loadfromcomponent: true);
|
||||
$this->add_import('@moodlehq/design-system', path: 'lib/js/bundles/design-system');
|
||||
$this->add_import('@moodlehq/design-system', path: 'lib/js/bundles/design-system/index');
|
||||
$this->add_import('react', path: 'lib/js/bundles/react/react');
|
||||
$this->add_import('react/', path: 'lib/js/bundles/react');
|
||||
$this->add_import('react-dom', path: 'lib/js/bundles/react-dom/react-dom');
|
||||
@@ -122,11 +122,13 @@ class import_map implements \JsonSerializable {
|
||||
?\core\url $loader = null,
|
||||
?string $path = null,
|
||||
bool $loadfromcomponent = false,
|
||||
string $suffix = '.js',
|
||||
): void {
|
||||
$this->imports[$specifier] = (object) [
|
||||
'loader' => $loader,
|
||||
'path' => $path,
|
||||
'loadfromcomponent' => $loadfromcomponent,
|
||||
'suffix' => $suffix,
|
||||
];
|
||||
$this->importssorted = false;
|
||||
}
|
||||
@@ -171,7 +173,7 @@ class import_map implements \JsonSerializable {
|
||||
if (in_array('..', explode('/', $pathremainder), true)) {
|
||||
return null;
|
||||
}
|
||||
return implode(DIRECTORY_SEPARATOR, array_filter([$CFG->root, $importdata->path, $pathremainder])) . '.js';
|
||||
return implode(DIRECTORY_SEPARATOR, array_filter([$CFG->root, $importdata->path, $pathremainder])) . $importdata->suffix;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -204,7 +206,7 @@ class import_map implements \JsonSerializable {
|
||||
|
||||
// Resolve the component directory; an unknown component name returns null.
|
||||
$dir = \core\component::get_component_directory($component);
|
||||
$file = "{$dir}/{$importdata->path}/{$modulerest}.js";
|
||||
$file = "{$dir}/{$importdata->path}/{$modulerest}{$importdata->suffix}";
|
||||
if (!file_exists($file)) {
|
||||
throw new \core\exception\not_found_exception('script', $subpath);
|
||||
}
|
||||
|
||||
@@ -350,7 +350,7 @@ enum param: string {
|
||||
* Accepts lowercase letters, numbers, hyphens, underscores, dots, forward slashes, and a leading @.
|
||||
* The path must start with a letter or @. Directory traversal via '..' is rejected by the ESM controller.
|
||||
*/
|
||||
#[param_clientside_regex('^[@a-z][a-z0-9_.-]*(/[a-z0-9_./-]+)?$')]
|
||||
#[param_clientside_regex('^[@a-zA-Z][a-zA-Z0-9_.-]*(/[a-zA-Z0-9_./-]+)?$')]
|
||||
case ESM_PATH = 'esm_path';
|
||||
|
||||
/**
|
||||
|
||||
@@ -164,6 +164,7 @@ final class param_test extends \advanced_testcase {
|
||||
['react/jsx-runtime', param::ESM_PATH],
|
||||
['button.small', param::ESM_PATH],
|
||||
['@moodlehq/design-system/button.small', param::ESM_PATH],
|
||||
['@moodlehq/design-system/Button', param::ESM_PATH],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -18,14 +18,23 @@ async function init() {
|
||||
|
||||
const DS_VERSION = getPackageVersion('@moodlehq/design-system');
|
||||
const nodeModuleRoot = path.join(rootDir, 'node_modules', '@moodlehq', 'design-system');
|
||||
const bundleRoot = path.join(rootDir, 'lib', 'js', 'bundles', 'design-system');
|
||||
const themeRoot = path.join(rootDir, 'public', 'theme', 'boost');
|
||||
const themeDesignSystemRoot = path.join(themeRoot, 'scss', 'design-system');
|
||||
|
||||
console.log(chalk.blue.bold.underline('Updating @moodlehq/design-system bundle to version %s from Node Modules'), DS_VERSION);
|
||||
console.log(chalk.blue('Removing old bundles...'));
|
||||
fs.removeSync(bundleRoot, { recursive: true, force: true });
|
||||
fs.removeSync(themeDesignSystemRoot, { recursive: true, force: true });
|
||||
console.log(chalk.green('Old bundles removed ✓'));
|
||||
|
||||
// Copy the JS bundles to the lib folder.
|
||||
fs.copySync(
|
||||
path.join(nodeModuleRoot, 'dist'),
|
||||
path.join(bundleRoot),
|
||||
);
|
||||
console.log(chalk.green(`→ @moodlehq/design-system:${DS_VERSION} JS bundles ✓`));
|
||||
|
||||
// Copy tokens into the themes.
|
||||
fs.copySync(
|
||||
path.join(nodeModuleRoot, 'tokens', 'scss'),
|
||||
@@ -35,10 +44,12 @@ async function init() {
|
||||
|
||||
// Create readme files in the package folders.
|
||||
console.log(chalk.green(`→ Creating readme_moodle.txt files ✓`));
|
||||
createPackageReadme(bundleRoot, '@moodlehq/design-system');
|
||||
createPackageReadme(themeDesignSystemRoot, '@moodlehq/design-system');
|
||||
|
||||
// And update the version in thirdpartylibs.xml.
|
||||
console.log(chalk.green(`→ Updating thirdpartylibs.xml files ✓`));
|
||||
updateThirdPartyLibsXml(path.join(rootDir, 'lib'), 'js/bundles/design-system', '@moodlehq/design-system', DS_VERSION);
|
||||
updateThirdPartyLibsXml(themeRoot, 'scss/design-system', '@moodlehq/design-system', DS_VERSION);
|
||||
|
||||
console.log("\nAll bundles saved" + chalk.green(" ✓"));
|
||||
|
||||
+2
-1
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"extends": "./tsconfig.aliases.json", // Added to extend the generated aliases.
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"target": "ES2020",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"moduleResolution": "node",
|
||||
"jsx": "react-jsx",
|
||||
"strict": true,
|
||||
"skipLibCheck": true
|
||||
|
||||
Reference in New Issue
Block a user