Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
dist
node_modules
playwright-report
test-results
test-results
.esbuild-serve
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ recommend that a file or class name and description of purpose be included on
the same “printed page” as the copyright notice for easier identification within
third-party archives.

Copyright [yyyy] [name of copyright owner]
Copyright 2026, Regular Layout Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ Add the `<regular-layout>` custom element to your HTML:

```html
<regular-layout>
<div slot="main">Main content</div>
<div slot="sidebar">Sidebar content</div>
<div name="main">Main content</div>
<div name="sidebar">Sidebar content</div>
</regular-layout>
```

Expand Down Expand Up @@ -67,7 +67,7 @@ Create repositionable panels using `<regular-layout-frame>`:

```html
<regular-layout>
<regular-layout-frame slot="main">
<regular-layout-frame name="main">
Main content
</regular-layout-frame>
</regular-layout>
Expand Down
8 changes: 4 additions & 4 deletions build.mjs → build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { execSync } from "node:child_process";

const watch = process.argv.includes("--watch");

function generateDeclarations() {
function generateDeclarations(): void {
console.log("Generating TypeScript declaration files...");
execSync(
"pnpm tsc --project tsconfig.json",
Expand All @@ -24,7 +24,7 @@ function generateDeclarations() {
console.log("Declaration files generated!");
}

const browserConfig = {
const browserConfig: esbuild.BuildOptions = {
entryPoints: ["src/index.ts"],
bundle: true,
minify: true,
Expand All @@ -37,13 +37,13 @@ const browserConfig = {
metafile: true,
};

function formatBytes(bytes) {
function formatBytes(bytes: number): string {
if (bytes < 1024) return `${bytes} B`;
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
}

async function build() {
async function build(): Promise<void> {
if (watch) {
const browserContext = await esbuild.context(browserConfig);
await browserContext.watch();
Expand Down
77 changes: 0 additions & 77 deletions deploy.mjs

This file was deleted.

94 changes: 94 additions & 0 deletions deploy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
// ░░░░░░░░▄▀░█▀▄░█▀▀░█▀▀░█░█░█░░░█▀█░█▀▄░░░░░█░░░█▀█░█░█░█▀█░█░█░▀█▀░▀▄░░░░░░░░
// ░░░░░░░▀▄░░█▀▄░█▀▀░█░█░█░█░█░░░█▀█░█▀▄░▀▀▀░█░░░█▀█░░█░░█░█░█░█░░█░░░▄▀░░░░░░░
// ░░░░░░░░░▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░▀▀▀░▀░▀░▀░▀░░░░░▀▀▀░▀░▀░░▀░░▀▀▀░▀▀▀░░▀░░▀░░░░░░░░░
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ * Copyright (c) 2026, the Regular Layout Authors. This file is part * ┃
// ┃ * of the Regular Layout library, distributed under the terms of the * ┃
// ┃ * [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). * ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

import * as esbuild from "esbuild";
import {
copyFileSync,
readdirSync,
readFileSync,
writeFileSync,
} from "node:fs";
import { join } from "node:path";

const ROOT_DIR = process.cwd();
const EXAMPLES_DIR = join(ROOT_DIR, "examples");

async function deploy(): Promise<void> {
console.log("Building examples for deployment...");

// Build the examples bundle
const result = await esbuild.build({
entryPoints: [join(EXAMPLES_DIR, "index.ts")],
bundle: true,
minify: true,
minifyWhitespace: true,
minifyIdentifiers: true,
outfile: join(ROOT_DIR, "index.js"),
platform: "browser",
format: "esm",
sourcemap: true,
metafile: true,
});

if (result.metafile) {
console.log("\nBundle Size:");
for (const [file, info] of Object.entries(result.metafile.outputs)) {
const bytes = info.bytes;
const size =
bytes < 1024
? `${bytes} B`
: bytes < 1024 * 1024
? `${(bytes / 1024).toFixed(2)} KB`
: `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
console.log(` ${file}: ${size}`);
}
}

// Copy HTML file and update paths
console.log("\nCopying HTML file...");
const htmlContent = readFileSync(join(EXAMPLES_DIR, "index.html"), "utf-8");
const updatedHtml = htmlContent
.replace(
'<script type="module" src="/.esbuild-serve/index.js"></script>',
'<script type="module" src="./index.js"></script>',
)
.replace(/href="\.\.\/themes\//g, 'href="./');

writeFileSync(join(ROOT_DIR, "index.html"), updatedHtml);

// Copy CSS file
console.log("\nCopying CSS file...");
copyFileSync(join(EXAMPLES_DIR, "index.css"), join(ROOT_DIR, "index.css"));

// Copy layout.json
console.log("\nCopying layout configuration...");
copyFileSync(
join(EXAMPLES_DIR, "layout.json"),
join(ROOT_DIR, "layout.json"),
);

// Copy theme files
console.log("\nCopying theme files...");
const themesDir = join(ROOT_DIR, "themes");
const themeFiles = readdirSync(themesDir);

for (const file of themeFiles) {
if (file.endsWith(".css")) {
copyFileSync(join(themesDir, file), join(ROOT_DIR, file));
console.log(` Copied ${file}`);
}
}
}

deploy().catch((error) => {
console.error("Deploy failed:", error);
process.exit(1);
});
130 changes: 36 additions & 94 deletions examples/index.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
/* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
* ░░░░░░░░▄▀░█▀▄░█▀▀░█▀▀░█░█░█░░░█▀█░█▀▄░░░░░█░░░█▀█░█░█░█▀█░█░█░▀█▀░▀▄░░░░░░░░
* ░░░░░░░▀▄░░█▀▄░█▀▀░█░█░█░█░█░░░█▀█░█▀▄░▀▀▀░█░░░█▀█░░█░░█░█░█░█░░█░░░▄▀░░░░░░░
* ░░░░░░░░░▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░▀▀▀░▀░▀░▀░▀░░░░░▀▀▀░▀░▀░░▀░░▀▀▀░▀▀▀░░▀░░▀░░░░░░░░░
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
* ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
* ┃ * Copyright (c) 2026, the Regular Layout Authors. This file is part * ┃
* ┃ * of the Regular Layout library, distributed under the terms of the * ┃
* ┃ * [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). * ┃
* ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
*/

body {
margin: 0px;
font-family: "ui-monospace", "SFMono-Regular", "SF Mono", "Menlo", "Consolas", "Liberation Mono", monospace;
}

header {
padding: 0 12px;
gap: 12px;
display: flex;
align-items: center;
height: 36px;
}

/* Layout */
regular-layout {
overflow: hidden;
Expand All @@ -10,104 +31,25 @@ regular-layout {
left: 0;
right: 0;
bottom: 0;
padding: 3px;
/* padding: 12px; */

/*
`regular-layout` supports the CSS `gap` property, but the "absolute"
mode overlay will not respect it (because there is no `gap` positioning
for absolutely positioned elements), leading to slightly off-center
drag/drop overlays. As "absolute" mode is required for CSS transitions
to work (making the smooth animation), you will need to use `margin`
instead of `gap` if you want smooth overlay animations _and_ correctly
positioned overlays.
*/

/* margin: 3px; */
/* gap: 6px; */
}

/* Frame */
regular-layout-frame {
--titlebar-height: 24px;
position: relative;
box-sizing: border-box;
margin: 3px;
border-radius: 0 0 6px 6px;
border: 1px solid #666;
box-shadow: 0px 6px 6px -4px rgba(150, 150, 180);
}

regular-layout-frame::part(titlebar) {
display: flex;
align-items: stretch;
margin-left: -1px;
margin-right: -1px;
margin-bottom: 0px;
}

regular-layout-frame::part(tab) {
display: flex;
flex: 1 1 150px;
align-items: center;
font-size: 10px;
padding: 0 8px;
cursor: pointer;
max-width: 150px;
text-overflow: ellipsis;
border: 1px solid #666;
border-radius: 6px 6px 0 0;
opacity: 0.5;
}

regular-layout-frame::part(active-tab) {
opacity: 1;
}

/* Frame in Overlay Mode */
regular-layout-frame.overlay {
background-color: rgba(0, 0, 0, 0.2) !important;
border: 1px dashed rgb(0, 0, 0);
border-radius: 6px;
margin: 0;
box-shadow: none;
transition:
top 0.1s ease-in-out,
height 0.1s ease-in-out,
width 0.1s ease-in-out,
left 0.1s ease-in-out;
}

regular-layout-frame::part(container) {
display: none;
}

regular-layout-frame:not(.overlay)::part(container) {
display: revert;
}

/* Colors */
regular-layout :nth-child(8n+1),
regular-layout :nth-child(8n+1)::part(tab) {
background-color: #ffadadff;
}

regular-layout :nth-child(8n+2),
regular-layout :nth-child(8n+2)::part(tab) {
background-color: #ffd6a5ff;
}

regular-layout :nth-child(8n+3),
regular-layout :nth-child(8n+3)::part(tab) {
background-color: #fdffb6ff;
}

regular-layout :nth-child(8n+4),
regular-layout :nth-child(8n+4)::part(tab) {
background-color: #caffbfff;
}

regular-layout :nth-child(8n+5),
regular-layout :nth-child(8n+5)::part(tab) {
background-color: #9bf6ffff;
}

regular-layout :nth-child(8n+6),
regular-layout :nth-child(8n+6)::part(tab) {
background-color: #a0c4ffff;
}

regular-layout :nth-child(8n+7),
regular-layout :nth-child(8n+7)::part(tab) {
background-color: #bdb2ffff;
}

regular-layout :nth-child(8n+8),
regular-layout :nth-child(8n+8)::part(tab) {
background-color: #ffc6ffff;
}
Loading