diff --git a/tools/cli/commands.js b/tools/cli/commands.js index c97d007c84..8c6c31104d 100644 --- a/tools/cli/commands.js +++ b/tools/cli/commands.js @@ -514,7 +514,8 @@ export const AVAILABLE_SKELETONS = [ DEFAULT_SKELETON, "typescript", "vue", - "svelte" + "svelte", + "tailwind", ]; main.registerCommand({ @@ -533,6 +534,7 @@ main.registerCommand({ typescript: { type: Boolean }, apollo: { type: Boolean }, svelte: { type: Boolean }, + tailwind: { type: Boolean }, }, catalogRefresh: new catalog.Refresh.Never() }, function (options) { @@ -904,6 +906,7 @@ main.registerCommand({ cmd("meteor create --svelte # to create a basic Svelte app"); cmd("meteor create --typescript # to create an app using TypeScript and React"); cmd("meteor create --blaze # to create an app using Blaze"); + cmd("meteor create --tailwind # to create an app using React and Tailwind"); } Console.info(""); diff --git a/tools/cli/help.txt b/tools/cli/help.txt index 04e636de6e..5c6129e409 100644 --- a/tools/cli/help.txt +++ b/tools/cli/help.txt @@ -150,7 +150,7 @@ Options: >>> create Create a new project. -Usage: meteor create [--release ] [--bare|--minimal|--full|--react|--vue|--apollo|--svelte|--blaze] +Usage: meteor create [--release ] [--bare|--minimal|--full|--react|--vue|--apollo|--svelte|--blaze|--tailwind] meteor create [--release ] --example [] meteor create --list meteor create --package [] @@ -188,6 +188,7 @@ Options: --svelte Create a basic svelte-based app. --typescript Create a basic Typescript React-based app. --blaze Create a basic blaze-based app. + --tailwind Create a basic react-based app, with tailwind configured. >>> update diff --git a/tools/static-assets/README.md b/tools/static-assets/README.md index 090b5250d0..b2efb024ea 100644 --- a/tools/static-assets/README.md +++ b/tools/static-assets/README.md @@ -28,6 +28,10 @@ Similar to `skel`, `skel-pack` is copied on `meteor create --package` command. Similar to `skel`, `skel-react` is copied on `meteor create --react` command. +## skel-tailwind - Package Skeleton + +Similar to `skel`, `skel-tailwind` is copied on `meteor create --tailwind` command. + ## server - Bundled App's Bootstrap The `server` folder is copied by Isobuild when the app is bundled (on diff --git a/tools/static-assets/skel-tailwind/.gitignore b/tools/static-assets/skel-tailwind/.gitignore new file mode 100644 index 0000000000..c2658d7d1b --- /dev/null +++ b/tools/static-assets/skel-tailwind/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/tools/static-assets/skel-tailwind/.meteor/.gitignore b/tools/static-assets/skel-tailwind/.meteor/.gitignore new file mode 100644 index 0000000000..4083037423 --- /dev/null +++ b/tools/static-assets/skel-tailwind/.meteor/.gitignore @@ -0,0 +1 @@ +local diff --git a/tools/static-assets/skel-tailwind/.meteor/packages b/tools/static-assets/skel-tailwind/.meteor/packages new file mode 100644 index 0000000000..72de92e77b --- /dev/null +++ b/tools/static-assets/skel-tailwind/.meteor/packages @@ -0,0 +1,23 @@ +# Meteor packages used by this project, one per line. +# Check this file (and the other files in this directory) into your repository. +# +# 'meteor add' and 'meteor remove' will edit this file for you, +# but you can also edit it by hand. + +meteor-base # Packages every Meteor app needs to have +mobile-experience # Packages for a great mobile UX +mongo # The database Meteor supports right now +reactive-var # Reactive variable for tracker + +standard-minifier-css # CSS minifier run for production mode +standard-minifier-js # JS minifier run for production mode +es5-shim # ECMAScript 5 compatibility for older browsers +ecmascript # Enable ECMAScript2015+ syntax in app code +typescript # Enable TypeScript syntax in .ts and .tsx modules +shell-server # Server-side component of the `meteor shell` command +hot-module-replacement # Update client in development without reloading the page + +autopublish # Publish all data to the clients (for prototyping) +insecure # Allow all DB writes from clients (for prototyping) +static-html # Define static page content in .html files +react-meteor-data # React higher-order component for reactively tracking Meteor data diff --git a/tools/static-assets/skel-tailwind/.meteor/platforms b/tools/static-assets/skel-tailwind/.meteor/platforms new file mode 100644 index 0000000000..efeba1b50c --- /dev/null +++ b/tools/static-assets/skel-tailwind/.meteor/platforms @@ -0,0 +1,2 @@ +server +browser diff --git a/tools/static-assets/skel-tailwind/client/main.css b/tools/static-assets/skel-tailwind/client/main.css new file mode 100644 index 0000000000..b5c61c9567 --- /dev/null +++ b/tools/static-assets/skel-tailwind/client/main.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/tools/static-assets/skel-tailwind/client/main.html b/tools/static-assets/skel-tailwind/client/main.html new file mode 100644 index 0000000000..f8fa758857 --- /dev/null +++ b/tools/static-assets/skel-tailwind/client/main.html @@ -0,0 +1,15 @@ + + ~name~ + + + + + + + + +
+ diff --git a/tools/static-assets/skel-tailwind/client/main.jsx b/tools/static-assets/skel-tailwind/client/main.jsx new file mode 100644 index 0000000000..a42cee8ff3 --- /dev/null +++ b/tools/static-assets/skel-tailwind/client/main.jsx @@ -0,0 +1,8 @@ +import React from 'react'; +import { Meteor } from 'meteor/meteor'; +import { render } from 'react-dom'; +import { App } from '/imports/ui/App'; + +Meteor.startup(() => { + render(, document.getElementById('react-target')); +}); diff --git a/tools/static-assets/skel-tailwind/imports/api/links.js b/tools/static-assets/skel-tailwind/imports/api/links.js new file mode 100644 index 0000000000..050c508eae --- /dev/null +++ b/tools/static-assets/skel-tailwind/imports/api/links.js @@ -0,0 +1,3 @@ +import { Mongo } from 'meteor/mongo'; + +export const LinksCollection = new Mongo.Collection('links'); diff --git a/tools/static-assets/skel-tailwind/imports/ui/App.jsx b/tools/static-assets/skel-tailwind/imports/ui/App.jsx new file mode 100644 index 0000000000..6cc8298b0e --- /dev/null +++ b/tools/static-assets/skel-tailwind/imports/ui/App.jsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { Hello } from './Hello.jsx'; +import { Info } from './Info.jsx'; + +export const App = () => ( +
+ + +
+); diff --git a/tools/static-assets/skel-tailwind/imports/ui/Hello.jsx b/tools/static-assets/skel-tailwind/imports/ui/Hello.jsx new file mode 100644 index 0000000000..ca51ed5233 --- /dev/null +++ b/tools/static-assets/skel-tailwind/imports/ui/Hello.jsx @@ -0,0 +1,42 @@ +import React, { useState } from 'react'; + +export const Hello = () => { + const [counter, setCounter] = useState(0); + + const increment = () => { + setCounter(counter + 1); + }; + + return ( +
+
+
+
+
+

+ Welcome to Meteor! +

+
+ +
+
+
+

+ You've pressed the button {counter} times. +

+
+
+
+ +
+
+
+
+ ) +}; diff --git a/tools/static-assets/skel-tailwind/imports/ui/Info.jsx b/tools/static-assets/skel-tailwind/imports/ui/Info.jsx new file mode 100644 index 0000000000..8272c26f94 --- /dev/null +++ b/tools/static-assets/skel-tailwind/imports/ui/Info.jsx @@ -0,0 +1,77 @@ +import React from 'react'; +import { useTracker } from 'meteor/react-meteor-data'; +import { LinksCollection } from '../api/links'; + +function classNames(...classes) { + return classes.filter(Boolean).join(' '); +} + +export const Info = () => { + const links = useTracker(() => { + const data = LinksCollection.find().fetch(); + + const foreGroundColors = ['text-red-700', 'text-orange-700', 'text-rose-700', 'text-yellow-700']; + const backgroundColors = ['bg-red-50', 'bg-orange-50', 'bg-rose-50', 'bg-yellow-50']; + + return data.map((d, index) => ({ + ...d, + iconForeground: foreGroundColors[index], + iconBackground: backgroundColors[index], + })) + }); + + const actions = links.map(link => ({ + id: link._id, + title: link.title, + href: link.url, + icon: + + , + ...link, + })); + + + + return ( +
+ {actions.map((action, actionIdx) => ( + + ))} +
+ ); +}; diff --git a/tools/static-assets/skel-tailwind/package.json b/tools/static-assets/skel-tailwind/package.json new file mode 100644 index 0000000000..122c7e4cf8 --- /dev/null +++ b/tools/static-assets/skel-tailwind/package.json @@ -0,0 +1,27 @@ +{ + "name": "~name~", + "private": true, + "scripts": { + "start": "meteor run", + "test": "meteor test --once --driver-package meteortesting:mocha", + "test-app": "TEST_WATCH=1 meteor test --full-app --driver-package meteortesting:mocha", + "visualize": "meteor --production --extra-packages bundle-visualizer" + }, + "dependencies": { + "@babel/runtime": "^7.15.4", + "autoprefixer": "^10.4.4", + "meteor-node-stubs": "^1.2.1", + "postcss": "^8.4.12", + "postcss-load-config": "^3.1.4", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "tailwindcss": "^3.0.23" + }, + "meteor": { + "mainModule": { + "client": "client/main.jsx", + "server": "server/main.js" + }, + "testModule": "tests/main.js" + } +} diff --git a/tools/static-assets/skel-tailwind/postcss.config.js b/tools/static-assets/skel-tailwind/postcss.config.js new file mode 100644 index 0000000000..33ad091d26 --- /dev/null +++ b/tools/static-assets/skel-tailwind/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/tools/static-assets/skel-tailwind/server/main.js b/tools/static-assets/skel-tailwind/server/main.js new file mode 100644 index 0000000000..13e6a4f815 --- /dev/null +++ b/tools/static-assets/skel-tailwind/server/main.js @@ -0,0 +1,31 @@ +import { Meteor } from 'meteor/meteor'; +import { LinksCollection } from '/imports/api/links'; + +function insertLink({ title, url }) { + LinksCollection.insert({title, url, createdAt: new Date()}); +} + +Meteor.startup(() => { + // If the Links collection is empty, add some data. + if (LinksCollection.find().count() === 0) { + insertLink({ + title: 'Do the Tutorial', + url: 'https://www.meteor.com/tutorials/react/creating-an-app' + }); + + insertLink({ + title: 'Follow the Guide', + url: 'http://guide.meteor.com' + }); + + insertLink({ + title: 'Read the Docs', + url: 'https://docs.meteor.com' + }); + + insertLink({ + title: 'Discussions', + url: 'https://forums.meteor.com' + }); + } +}); diff --git a/tools/static-assets/skel-tailwind/tailwind.config.js b/tools/static-assets/skel-tailwind/tailwind.config.js new file mode 100644 index 0000000000..b8bf0cafc2 --- /dev/null +++ b/tools/static-assets/skel-tailwind/tailwind.config.js @@ -0,0 +1,7 @@ +module.exports = { + content: ["./imports/ui/**/*.{js,jsx,ts,tsx}", './client/*.html'], + theme: { + extend: {}, + }, + plugins: [], +} diff --git a/tools/static-assets/skel-tailwind/tests/main.js b/tools/static-assets/skel-tailwind/tests/main.js new file mode 100644 index 0000000000..ea7a8da1e1 --- /dev/null +++ b/tools/static-assets/skel-tailwind/tests/main.js @@ -0,0 +1,20 @@ +import assert from "assert"; + +describe("~name~", function () { + it("package.json has correct name", async function () { + const { name } = await import("../package.json"); + assert.strictEqual(name, "~name~"); + }); + + if (Meteor.isClient) { + it("client is not server", function () { + assert.strictEqual(Meteor.isServer, false); + }); + } + + if (Meteor.isServer) { + it("server is not client", function () { + assert.strictEqual(Meteor.isClient, false); + }); + } +});