├── .build.mjs
├── .eslintrc.cjs
├── .gitignore
├── .npmignore
├── .vscode
└── extensions.json
├── LICENSE
├── README.md
├── package.json
├── packages
└── vue-playground
│ ├── .gitignore
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── public
│ └── vite.svg
│ ├── src
│ ├── App.vue
│ ├── main.ts
│ ├── style.css
│ └── vite-env.d.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── playground
├── .eslintrc.cjs
├── .gitignore
├── README.md
├── index.html
├── package.json
├── public
│ ├── catsjuice.jpg
│ └── imgs
│ │ ├── thumb.1.jpg
│ │ ├── thumb.10.jpg
│ │ ├── thumb.2.jpg
│ │ ├── thumb.3.jpg
│ │ ├── thumb.4.jpg
│ │ ├── thumb.5.jpg
│ │ ├── thumb.6.jpg
│ │ ├── thumb.7.jpg
│ │ ├── thumb.8.jpg
│ │ └── thumb.9.jpg
├── src
│ ├── App.tsx
│ ├── assets
│ │ └── react.svg
│ ├── components
│ │ ├── app-header
│ │ │ ├── index.tsx
│ │ │ └── theme-toggle
│ │ │ │ └── theme-toggle.tsx
│ │ ├── card
│ │ │ ├── card.css
│ │ │ └── index.tsx
│ │ └── resize-frame
│ │ │ ├── index.tsx
│ │ │ ├── resize.css
│ │ │ └── ruler.tsx
│ ├── hooks
│ │ └── use-theme.ts
│ ├── index.css
│ ├── main.tsx
│ ├── utils
│ │ └── item.ts
│ └── vite-env.d.ts
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.node.json
├── uno.config.ts
└── vite.config.ts
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── rollup.config.js
├── src
├── core
│ ├── calculator.ts
│ ├── index.ts
│ └── types.ts
├── react
│ ├── context.ts
│ ├── footer.tsx
│ ├── index.ts
│ ├── item.tsx
│ ├── root.tsx
│ └── type.ts
└── vue
│ ├── index.ts
│ ├── item.ts
│ ├── root.ts
│ └── type.ts
└── tsconfig.json
/.build.mjs:
--------------------------------------------------------------------------------
1 | import { dirname, resolve } from "path";
2 | import { fileURLToPath } from "url";
3 | import chalk from "chalk";
4 | import fs from "fs";
5 | import { readFile, writeFile } from "fs/promises";
6 | import { execa } from "execa";
7 | import { execSync } from "child_process";
8 | import prompts from "prompts";
9 | import brotliSize from "brotli-size";
10 | import prettyBytes from "pretty-bytes";
11 |
12 | const info = (m) => console.log("► " + chalk.blue(m));
13 | const error = (m) => console.log("⚠️ " + chalk.red(m));
14 | const success = (m) => console.log("✅ " + chalk.green(m));
15 | const details = (m) => console.log(chalk.pink(m));
16 |
17 | const __filename = fileURLToPath(import.meta.url);
18 | const __dirname = dirname(__filename);
19 | const rootDir = resolve(__dirname);
20 | const isPublishing = process.argv[2] === "--publish";
21 |
22 | async function clean() {
23 | if (!fs.existsSync(`${rootDir}/dist`)) return;
24 | await execa("shx", ["rm", "-rf", `${rootDir}/dist`]);
25 | }
26 |
27 | async function baseBuild() {
28 | info("Building primary package");
29 | await execa("npx", ["rollup", "-c", "rollup.config.js"]);
30 | }
31 |
32 | async function vueBuild() {
33 | info("Building Vue package");
34 | await execa("npx", [
35 | "rollup",
36 | "-c",
37 | "rollup.config.js",
38 | "--environment",
39 | "FRAMEWORK:vue",
40 | ]);
41 |
42 | let raw = await readFile(resolve(rootDir, "dist/vue/index.mjs"), "utf8");
43 | raw = raw.replace("from '../index'", "from '../index.mjs'");
44 | await writeFile(resolve(rootDir, "dist/vue/index.mjs"), raw);
45 | }
46 |
47 | async function reactBuild() {
48 | info("Building React package");
49 | await execa("npx", [
50 | "rollup",
51 | "-c",
52 | "rollup.config.js",
53 | "--environment",
54 | "FRAMEWORK:react",
55 | ]);
56 | let raw = await readFile(resolve(rootDir, "dist/react/index.mjs"), "utf8");
57 | raw = raw.replace("from '../index'", "from '../index.mjs'");
58 | await writeFile(resolve(rootDir, "dist/react/index.mjs"), raw);
59 | }
60 |
61 | async function declarationsBuild() {
62 | info("Building declarations");
63 | await execa("npx", [
64 | "rollup",
65 | "-c",
66 | "rollup.config.js",
67 | "--environment",
68 | "DECLARATIONS:true",
69 | ]);
70 | }
71 |
72 | async function bundleDeclarations() {
73 | info("Organizing declarations");
74 | await execa("shx", [
75 | "mv",
76 | `${rootDir}/dist/src/core/*`,
77 | `${rootDir}/dist/core/`,
78 | ]);
79 | await execa("shx", [
80 | "mv",
81 | `${rootDir}/dist/src/react/*`,
82 | `${rootDir}/dist/react/`,
83 | ]);
84 | await execa("shx", [
85 | "mv",
86 | `${rootDir}/dist/src/vue/*`,
87 | `${rootDir}/dist/vue/`,
88 | ]);
89 | await execa("shx", ["rm", "-rf", `${rootDir}/dist/src`]);
90 | await execa("shx", ["rm", `${rootDir}/dist/index.js`]);
91 | }
92 |
93 | async function addPackageJSON() {
94 | info("Generating package.json");
95 | const raw = await readFile(resolve(rootDir, "package.json"), "utf8");
96 | const packageJSON = JSON.parse(raw);
97 | delete packageJSON.private;
98 | delete packageJSON.devDependencies;
99 | delete packageJSON.scripts;
100 | await writeFile(
101 | resolve(rootDir, "dist/package.json"),
102 | JSON.stringify(packageJSON, null, 2)
103 | );
104 | }
105 |
106 | async function addAssets() {
107 | info("Writing readme and license.");
108 | await execa("shx", [
109 | "cp",
110 | `${rootDir}/README.md`,
111 | `${rootDir}/dist/README.md`,
112 | ]);
113 | await execa("shx", ["cp", `${rootDir}/LICENSE`, `${rootDir}/dist/LICENSE`]);
114 | }
115 |
116 | async function bumpVersion() {
117 | info("Bumping version");
118 | const raw = await readFile(resolve(rootDir, "package.json"), "utf8");
119 | const packageJSON = JSON.parse(raw);
120 |
121 | const version = packageJSON.version;
122 | const [major, minor, patch] = version.split(".");
123 | const versionRes = await prompts([
124 | {
125 | type: "select",
126 | name: "value",
127 | message: `Select version bump type`,
128 | choices: [
129 | { title: "Patch", value: "patch" },
130 | { title: "Minor", value: "minor" },
131 | { title: "Major", value: "major" },
132 | ],
133 | initial: 0,
134 | },
135 | ]);
136 | const newVersion = [major, minor, patch];
137 | const index = ["major", "minor", "patch"].indexOf(versionRes.value);
138 | newVersion[index] = parseInt(newVersion[index]) + 1;
139 | for (let i = index + 1; i < newVersion.length; i++) {
140 | newVersion[i] = 0;
141 | }
142 | packageJSON.version = newVersion.join(".");
143 |
144 | const confirmRes = await prompts([
145 | {
146 | type: "confirm",
147 | name: "value",
148 | message: `Bump version to ${packageJSON.version}?`,
149 | initial: true,
150 | },
151 | ]);
152 | if (!confirmRes.value) {
153 | process.exit();
154 | }
155 | await writeFile(
156 | resolve(rootDir, "package.json"),
157 | JSON.stringify(packageJSON, null, 2)
158 | );
159 |
160 | execSync(`git add package.json`);
161 | execSync(`git commit -m "Bump version to ${packageJSON.version}"`);
162 | execSync(`git tag ${packageJSON.version}`);
163 | execSync(`git push origin --tags`);
164 | }
165 |
166 | async function prepareForPublishing() {
167 | info("Preparing for publication");
168 | const isClean = !execSync(`git status --untracked-files=no --porcelain`, {
169 | encoding: "utf-8",
170 | });
171 | if (!isClean) {
172 | error("Commit your changes before publishing.");
173 | process.exit();
174 | }
175 |
176 | // bump version
177 | await bumpVersion();
178 |
179 | const raw = await readFile(resolve(rootDir, "package.json"), "utf8");
180 | const packageJSON = JSON.parse(raw);
181 |
182 | const response = await prompts([
183 | {
184 | type: "confirm",
185 | name: "value",
186 | message: `Confirm you want to publish version ${chalk.red(
187 | packageJSON.version
188 | )}?`,
189 | initial: true,
190 | },
191 | ]);
192 | if (!response.value) {
193 | error("Please adjust the version and try again");
194 | process.exit();
195 | }
196 | }
197 |
198 | async function publish() {
199 | const response = await prompts([
200 | {
201 | type: "confirm",
202 | name: "value",
203 | message: `Project is build. Ready to publish?`,
204 | initial: false,
205 | },
206 | ]);
207 | if (response.value) {
208 | execSync("npm publish ./dist --registry https://registry.npmjs.org");
209 | }
210 | }
211 |
212 | async function outputSize(pkg) {
213 | const raw = await readFile(resolve(rootDir, `dist/${pkg}/index.mjs`), "utf8");
214 | info(`Brotli size - ${pkg}: ` + prettyBytes(brotliSize.sync(raw)));
215 | }
216 |
217 | await clean();
218 | await baseBuild();
219 | await vueBuild();
220 | await reactBuild();
221 | await declarationsBuild();
222 | await bundleDeclarations();
223 | if (!isPublishing) await addPackageJSON();
224 | await addAssets();
225 | await outputSize("core");
226 | await outputSize("react");
227 | success("Build completed");
228 | if (isPublishing) {
229 | await prepareForPublishing();
230 | await addPackageJSON();
231 | await publish();
232 | }
233 |
--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: { browser: true, es2020: true, node: true },
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:@typescript-eslint/recommended',
7 | 'plugin:react-hooks/recommended',
8 | ],
9 | ignorePatterns: ['dist', '.eslintrc.cjs'],
10 | parser: '@typescript-eslint/parser',
11 | plugins: ['react-refresh'],
12 | rules: {
13 | 'react-refresh/only-export-components': [
14 | 'warn',
15 | { allowConstantExport: true },
16 | ],
17 | },
18 | }
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist-playground
12 | dist
13 | dist-ssr
14 | *.local
15 |
16 | # Editor directories and files
17 | .vscode/*
18 | !.vscode/extensions.json
19 | .idea
20 | .DS_Store
21 | *.suo
22 | *.ntvs*
23 | *.njsproj
24 | *.sln
25 | *.sw?
26 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .eslintrc.cjs
2 | .gitignore
3 | index.html
4 | pnpm-lock.yaml
5 | public
6 | src
7 | tsconfig.json
8 | tsconfig.node.json
9 | uno.config.ts
10 | vite.config.playground.ts
11 | vite.config.ts
12 | dist-playground
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["Vue.volar"]
3 | }
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Cats Juice
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Playground
2 |
3 | [masonry.oooo.so](https://masonry.oooo.so)
4 |
5 | # Install
6 |
7 | ```
8 | npm install masonry-flow
9 | ```
10 |
11 | # Usage
12 |
13 | ## React
14 |
15 | ```tsx
16 | import MasonryFlow from "masonry-flow/react";
17 |
18 |
19 |
20 | 1
21 |
22 |
23 | 2
24 |
25 |
26 | 3
27 |
28 | ;
29 | ```
30 |
31 | ## Vue
32 |
33 | ```vue
34 |
37 |
38 |
39 |
40 |
41 | 1
42 |
43 |
44 | 2
45 |
46 |
47 | 3
48 |
49 |
50 |
51 | ```
52 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "masonry-flow",
3 | "version": "0.2.2",
4 | "type": "module",
5 | "scripts": {
6 | "dev": "pnpm --filter playground dev",
7 | "dev:react": "pnpm --filter playground dev",
8 | "dev:vue": "pnpm --filter vue-playground dev",
9 | "build": "node ./.build.mjs",
10 | "build:playground": "cd ./playground && tsc && vite build",
11 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
12 | "preview": "vite preview",
13 | "pub": "npm run build && npm publish"
14 | },
15 | "author": "CatsJuice",
16 | "license": "MIT",
17 | "repository": {
18 | "url": "https://github.com/CatsJuice/masonry-flow"
19 | },
20 | "homepage": "https://masonry.oooo.so",
21 | "dependencies": {},
22 | "types": "dist/index.d.ts",
23 | "exports": {
24 | "./core": {
25 | "import": "./core/index.mjs",
26 | "types": "./core/index.d.ts",
27 | "default": "./core/index.mjs"
28 | },
29 | "./react": {
30 | "import": "./react/index.mjs",
31 | "types": "./react/index.d.ts",
32 | "default": "./react/index.mjs"
33 | },
34 | "./vue": {
35 | "import": "./vue/index.mjs",
36 | "types": "./vue/index.d.ts",
37 | "default": "./vue/index.mjs"
38 | }
39 | },
40 | "keywords": [
41 | "masonry",
42 | "absolute grid",
43 | "masonry layout"
44 | ],
45 | "devDependencies": {
46 | "react": "^18.2.0",
47 | "react-dom": "^18.2.0",
48 | "@rollup/plugin-terser": "^0.4.4",
49 | "@rollup/plugin-typescript": "^11.1.6",
50 | "@tweakpane/core": "^2.0.4",
51 | "@types/node": "^20.12.4",
52 | "@types/react": "^18.2.66",
53 | "@types/react-dom": "^18.2.22",
54 | "@typescript-eslint/eslint-plugin": "^7.2.0",
55 | "@typescript-eslint/parser": "^7.2.0",
56 | "@vitejs/plugin-react": "^4.2.1",
57 | "brotli-size": "^4.0.0",
58 | "chalk": "^5.3.0",
59 | "eslint": "^8.57.0",
60 | "eslint-plugin-react-hooks": "^4.6.0",
61 | "eslint-plugin-react-refresh": "^0.4.6",
62 | "execa": "^9.3.0",
63 | "pretty-bytes": "^6.1.1",
64 | "prompts": "^2.4.2",
65 | "shx": "^0.3.4",
66 | "tslib": "^2.6.3",
67 | "tweakpane": "^4.0.4",
68 | "typescript": "^5.2.2",
69 | "vite": "^5.2.0",
70 | "vite-plugin-dts": "4.0.0-beta.1",
71 | "vue": "^3.4.31"
72 | }
73 | }
--------------------------------------------------------------------------------
/packages/vue-playground/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/packages/vue-playground/README.md:
--------------------------------------------------------------------------------
1 | # Vue 3 + TypeScript + Vite
2 |
3 | This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `
12 |