mevebu 1.7.1 → 1.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -20
- package/mevebu/app/mevebu.js +129 -1
- package/mevebu/app/tailwind.css +29 -12
- package/mevebu/libs/js/core.js +3 -3
- package/mevebu/libs/js/icons.js +6 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,25 +1,34 @@
|
|
|
1
1
|
# mevebu
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**186 small tools, each on its own page, all running in your browser.**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
A box of browser tools for the jobs that do not deserve an app: convert a value,
|
|
6
|
+
hash a text, sign a token, format JSON, pick a color, run a timer, count words,
|
|
7
|
+
build a cron line, check a JWT, read a QR. Every tool opens on its own page and
|
|
8
|
+
most of them update as you type, so there is no submit button and no waiting.
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
Nothing leaves your tab. There is no account to make, nothing to upload, and
|
|
11
|
+
nothing saved to a server.
|
|
9
12
|
|
|
10
|
-
```
|
|
11
|
-
|
|
13
|
+
```
|
|
14
|
+
tools 186
|
|
15
|
+
categories 20
|
|
16
|
+
followers 1 (one tab, no account)
|
|
17
|
+
uploads 0
|
|
12
18
|
```
|
|
13
19
|
|
|
14
|
-
##
|
|
20
|
+
## Install and run
|
|
15
21
|
|
|
16
22
|
```sh
|
|
23
|
+
npm install -g mevebu
|
|
17
24
|
mevebu
|
|
18
25
|
```
|
|
19
26
|
|
|
20
|
-
|
|
27
|
+
`mevebu` starts a local server (it tries port 5555, then 5678, then 5432, then
|
|
28
|
+
any free port), opens your browser to the home page, and serves the static
|
|
29
|
+
folder bundled with the package. Press `Ctrl+C` in the terminal to stop it.
|
|
21
30
|
|
|
22
|
-
###
|
|
31
|
+
### CLI
|
|
23
32
|
|
|
24
33
|
```
|
|
25
34
|
-p, --port <number> Try this port first (5555, 5678, 5432 otherwise).
|
|
@@ -29,15 +38,16 @@ The tools open in your default browser. Press `Ctrl+C` in the terminal to stop.
|
|
|
29
38
|
-h, --help Print this help and exit.
|
|
30
39
|
```
|
|
31
40
|
|
|
32
|
-
The
|
|
33
|
-
|
|
41
|
+
The first three ports are stable across restarts, so the bookmark to your tools
|
|
42
|
+
page keeps working.
|
|
34
43
|
|
|
35
|
-
##
|
|
44
|
+
## What's inside
|
|
36
45
|
|
|
37
|
-
|
|
46
|
+
A tool is a small page that does one job. The registry lists them all; here is
|
|
47
|
+
the shape of it.
|
|
38
48
|
|
|
39
|
-
| Category |
|
|
40
|
-
| :--- |
|
|
49
|
+
| Category | Count |
|
|
50
|
+
| :--- | ---: |
|
|
41
51
|
| Random | 3 |
|
|
42
52
|
| Passwords and keys | 10 |
|
|
43
53
|
| Developer | 21 |
|
|
@@ -58,16 +68,108 @@ and falls back to any free port only when those are taken.
|
|
|
58
68
|
| GitHub | 8 |
|
|
59
69
|
| Units | 8 |
|
|
60
70
|
| QR codes | 2 |
|
|
61
|
-
|
|
62
|
-
|
|
71
|
+
| **Total** | **186** |
|
|
72
|
+
|
|
73
|
+
The counts are kept honest by the registry, so the page and the README never
|
|
74
|
+
drift apart. Press `Ctrl+K` in the app to search the full list by name, by
|
|
75
|
+
keyword, or by what the tool does.
|
|
76
|
+
|
|
77
|
+
A short tour of the most reached-for tools, one from each side of the catalog:
|
|
78
|
+
|
|
79
|
+
- **Password generator**: make a password, copy it, and the page never talks
|
|
80
|
+
to anything but your clipboard.
|
|
81
|
+
- **JSON formatter**: paste, and the formatted version fills in as you type.
|
|
82
|
+
- **JWT generator and decoder**: sign a token with HS256, RS256 or ES256, or
|
|
83
|
+
paste a token and read its header and payload.
|
|
84
|
+
- **Color palette**: pick one color, get a matching set in analogous,
|
|
85
|
+
complementary or monochrome schemes.
|
|
86
|
+
- **Countdown timer**: a quiet, fullscreen timer that keeps running when the
|
|
87
|
+
tab is hidden.
|
|
88
|
+
- **QR code generator**: turn a URL, a Wi-Fi config or any text into a scannable
|
|
89
|
+
image right in the tab.
|
|
90
|
+
- **Slug converter**: keep a sentence readable while you turn it into a URL.
|
|
91
|
+
|
|
92
|
+
The full list is at the home page and under each category.
|
|
93
|
+
|
|
94
|
+
## How it stays private
|
|
95
|
+
|
|
96
|
+
Every tool is a static HTML file, a tiny JavaScript module, and a Lucide icon.
|
|
97
|
+
The HTML and the JavaScript are served from your machine when you run `mevebu`,
|
|
98
|
+
or from the file you host when you copy the `mevebu/` folder somewhere. There is
|
|
99
|
+
no server-side code, no analytics, and no API key.
|
|
100
|
+
|
|
101
|
+
When you paste a password, a token, or a CSV into a tool:
|
|
102
|
+
|
|
103
|
+
- the text is processed in the browser tab, by the file that the page loaded
|
|
104
|
+
from, using the standard Web Crypto API or the standard browser APIs the
|
|
105
|
+
tool needs
|
|
106
|
+
- nothing is sent to a remote server, because there is no remote server in
|
|
107
|
+
the loop
|
|
108
|
+
- nothing is saved to disk by the tool, because the tool does not have a way
|
|
109
|
+
to write to your file system
|
|
110
|
+
- the only network request the page makes is to load itself, and to read the
|
|
111
|
+
GitHub star count for the footer chip (and that request fails silently when
|
|
112
|
+
you are offline)
|
|
113
|
+
|
|
114
|
+
You can verify this by opening the network tab in your browser's dev tools and
|
|
115
|
+
watching a tool do its work. There is no upload. The same tool, loaded the same
|
|
116
|
+
way, behaves the same in a hotel Wi-Fi as it does on a server room.
|
|
117
|
+
|
|
118
|
+
## Hosting the static folder
|
|
119
|
+
|
|
120
|
+
If you would rather not run the CLI, the whole app is a plain static site. Copy
|
|
121
|
+
the `mevebu/` folder from this repo, or from the npm package, to any host that
|
|
122
|
+
serves files: a static site host, a CDN, an object store, a USB drive. Routes
|
|
123
|
+
are hash routes (`#/security/password-generator`), so no server rewrites are
|
|
124
|
+
needed.
|
|
125
|
+
|
|
126
|
+
The shipped folder is plain files, the CSS is one committed stylesheet that
|
|
127
|
+
Tailwind built from one source file, and there is no separate build step. The
|
|
128
|
+
hosting layer never runs code on your behalf.
|
|
63
129
|
|
|
64
130
|
## Development
|
|
65
131
|
|
|
66
132
|
```sh
|
|
67
|
-
|
|
68
|
-
|
|
133
|
+
git clone https://github.com/mevebu/mevebu
|
|
134
|
+
cd mevebu
|
|
135
|
+
npm install
|
|
136
|
+
npm run css # build the stylesheet from tailwind.src.css
|
|
137
|
+
npm run icons # regenerate the vendored Lucide icon set
|
|
138
|
+
npm start # serve the static folder on http://localhost:5555
|
|
69
139
|
```
|
|
70
140
|
|
|
141
|
+
The app is a few hundred lines of vanilla JavaScript (ESM) in
|
|
142
|
+
`mevebu/app/mevebu.js` and a small shared vocabulary in `mevebu/libs/js/core.js`.
|
|
143
|
+
Every tool is a single file in `mevebu/libs/js/tools/`, exports a `mount(slot)`
|
|
144
|
+
function and (optionally) an `unmount()` to stop timers, cameras and observers.
|
|
145
|
+
The registry in `mevebu/libs/js/registry.js` is the single source of truth: add
|
|
146
|
+
an entry to `TOOLS` and a file, and the catalog, search, breadcrumb, and
|
|
147
|
+
category page pick it up.
|
|
148
|
+
|
|
149
|
+
The CSS is Tailwind v4, built from one source file, with the stylesheet output
|
|
150
|
+
committed so the shipped folder is still plain static files. There is no
|
|
151
|
+
component layer and no `mvb-` class: every utility is written at the call
|
|
152
|
+
site, and the design tokens live in `mevebu/app/tailwind.src.css`.
|
|
153
|
+
|
|
154
|
+
Layout and color decisions, the type scale, the orbit lines, the "energy 1,
|
|
155
|
+
rhythm 2, motion 1" dials, and the rest of the visual system, are recorded in
|
|
156
|
+
`AGENTS.md` and `DESIGN.md`, the two docs an agent reads first.
|
|
157
|
+
|
|
158
|
+
## Report a problem
|
|
159
|
+
|
|
160
|
+
Every tool page has a small "Report a problem" link at the bottom, alongside
|
|
161
|
+
the tool's actions. It opens a GitHub issue with the tool name, the page URL
|
|
162
|
+
and the mevebu version already filled in, so all you have to do is describe
|
|
163
|
+
what happened and what you expected.
|
|
164
|
+
|
|
71
165
|
## License
|
|
72
166
|
|
|
73
|
-
MIT
|
|
167
|
+
MIT. The whole list, the whole source, the whole thing is in the repository.
|
|
168
|
+
If a tool here saved you time, a coffee keeps the next one coming:
|
|
169
|
+
<https://buymeacoffee.com/fastro>.
|
|
170
|
+
|
|
171
|
+
## Links
|
|
172
|
+
|
|
173
|
+
- Repository: <https://github.com/mevebu/mevebu>
|
|
174
|
+
- npm: <https://www.npmjs.com/package/mevebu>
|
|
175
|
+
- Donate: <https://buymeacoffee.com/fastro>
|
package/mevebu/app/mevebu.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
$, $$, el, icon, getFavorites, isFavorite, toggleFavorite, setTheme,
|
|
8
8
|
modal, modalHead, button, copyButton, openPalette, shuffle, toolcard, blank,
|
|
9
9
|
VERSION, PACKAGE_NAME, checkForUpdate, updateCommand, compareVersions, releaseUrl,
|
|
10
|
+
textInput, textArea, panel,
|
|
10
11
|
} from "../libs/js/core.js";
|
|
11
12
|
|
|
12
13
|
const DONATE_URL = "https://buymeacoffee.com/fastro";
|
|
@@ -128,7 +129,7 @@ function masthead() {
|
|
|
128
129
|
|
|
129
130
|
return el(
|
|
130
131
|
"header",
|
|
131
|
-
{
|
|
132
|
+
{ id: "masthead", class: "z-30 border-b border-orbit bg-deck data-[pin]:sticky data-[pin]:top-0 data-[pin]:transition-shadow" },
|
|
132
133
|
el(
|
|
133
134
|
"div",
|
|
134
135
|
{ class: "mx-[var(--margin)] flex h-[var(--bar)] items-center gap-[clamp(14px,3vw,32px)]" },
|
|
@@ -754,6 +755,117 @@ function moreFromMev(tool) {
|
|
|
754
755
|
);
|
|
755
756
|
}
|
|
756
757
|
|
|
758
|
+
// What the browser tells us about itself, without asking the user to retype it.
|
|
759
|
+
// Every field can come back empty (a hardened browser, a private mode), so the
|
|
760
|
+
// form still works when it does.
|
|
761
|
+
function browserFacts() {
|
|
762
|
+
const ua = navigator.userAgent;
|
|
763
|
+
const browser = /Edg\//.test(ua) ? "Edge"
|
|
764
|
+
: /OPR\//.test(ua) ? "Opera"
|
|
765
|
+
: /Firefox\//.test(ua) ? "Firefox"
|
|
766
|
+
: /Chrome\//.test(ua) ? "Chrome"
|
|
767
|
+
: /Safari\//.test(ua) ? "Safari"
|
|
768
|
+
: "Unknown";
|
|
769
|
+
const version = (ua.match(new RegExp(browser + "\\/([\\d.]+)")) ?? [])[1] ?? "";
|
|
770
|
+
const platform = navigator.userAgentData?.platform
|
|
771
|
+
?? (/Windows/.test(ua) ? "Windows" : /Mac OS X/.test(ua) ? "macOS"
|
|
772
|
+
: /Android/.test(ua) ? "Android" : /iPhone|iPad/.test(ua) ? "iOS"
|
|
773
|
+
: /Linux/.test(ua) ? "Linux" : "");
|
|
774
|
+
const screen = `${window.screen.width}x${window.screen.height} @${window.devicePixelRatio}x`;
|
|
775
|
+
return { browser: `${browser} ${version}`.trim(), platform, screen };
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
function openReport(tool) {
|
|
779
|
+
const facts = browserFacts();
|
|
780
|
+
const doing = textArea({ rows: 3, placeholder: "I was building a daily expression for a backup job." });
|
|
781
|
+
const happened = textArea({ rows: 3, placeholder: "The preview stayed empty when I typed 0 3." });
|
|
782
|
+
const expected = textArea({ rows: 3, placeholder: "I expected it to read \"03:00 every day\"." });
|
|
783
|
+
const browserField = textInput({ value: facts.browser });
|
|
784
|
+
const platformField = textInput({ value: [facts.platform, facts.screen].filter(Boolean).join(" · ") });
|
|
785
|
+
let opened = false;
|
|
786
|
+
|
|
787
|
+
const submit = button("Open GitHub issue", { icon: "external-link", kind: "fill" });
|
|
788
|
+
// The actions row renders outside the form, so the button names it explicitly.
|
|
789
|
+
submit.type = "submit";
|
|
790
|
+
submit.setAttribute("form", "report-form");
|
|
791
|
+
submit.disabled = true;
|
|
792
|
+
submit.setAttribute("aria-disabled", "true");
|
|
793
|
+
const validate = () => {
|
|
794
|
+
const ready = happened.value.trim().length > 0 && doing.value.trim().length > 0;
|
|
795
|
+
submit.disabled = !ready;
|
|
796
|
+
if (ready) submit.removeAttribute("aria-disabled");
|
|
797
|
+
else submit.setAttribute("aria-disabled", "true");
|
|
798
|
+
};
|
|
799
|
+
for (const area of [doing, happened]) area.addEventListener("input", validate);
|
|
800
|
+
|
|
801
|
+
const form = el(
|
|
802
|
+
"form",
|
|
803
|
+
{
|
|
804
|
+
id: "report-form",
|
|
805
|
+
class: "grid gap-3.5",
|
|
806
|
+
onsubmit: (event) => {
|
|
807
|
+
event.preventDefault();
|
|
808
|
+
if (opened || submit.disabled) return;
|
|
809
|
+
opened = true;
|
|
810
|
+
const body = [
|
|
811
|
+
"### What I was doing",
|
|
812
|
+
doing.value.trim() || "_not given_",
|
|
813
|
+
"",
|
|
814
|
+
"### What happened",
|
|
815
|
+
happened.value.trim() || "_not given_",
|
|
816
|
+
"",
|
|
817
|
+
"### What I expected",
|
|
818
|
+
expected.value.trim() || "_not given_",
|
|
819
|
+
"",
|
|
820
|
+
"### Where",
|
|
821
|
+
`- Tool: ${tool.name} (\`${tool.id}\`)`,
|
|
822
|
+
`- Page: #/${tool.category}/${tool.id}`,
|
|
823
|
+
`- mevebu: ${VERSION}`,
|
|
824
|
+
"",
|
|
825
|
+
"### Browser",
|
|
826
|
+
`- ${browserField.value || "unknown"}`,
|
|
827
|
+
`- ${platformField.value || "unknown"}`,
|
|
828
|
+
].join("\n");
|
|
829
|
+
const title = `Bug in ${tool.name}`;
|
|
830
|
+
const href = `https://github.com/mevebu/mevebu/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`;
|
|
831
|
+
window.open(href, "_blank", "noopener");
|
|
832
|
+
},
|
|
833
|
+
},
|
|
834
|
+
panel("What were you doing?", doing),
|
|
835
|
+
panel("What happened?", happened),
|
|
836
|
+
panel("What did you expect?", expected, "Optional"),
|
|
837
|
+
el(
|
|
838
|
+
"div",
|
|
839
|
+
{ class: "grid gap-3 rounded-r2 border border-orbit bg-deck-2 p-3.5" },
|
|
840
|
+
el("p", { class: "m-0 text-2xs text-ink-3" },
|
|
841
|
+
"Already filled in from this tab. Edit it if something is off."),
|
|
842
|
+
panel("Browser", browserField),
|
|
843
|
+
panel("Screen", platformField),
|
|
844
|
+
),
|
|
845
|
+
submit
|
|
846
|
+
);
|
|
847
|
+
|
|
848
|
+
modal({
|
|
849
|
+
label: `Report a problem with ${tool.name}`,
|
|
850
|
+
panelClass: "m-auto w-[min(560px,100%)] p-[clamp(22px,3vw,28px)] max-h-[calc(100dvh-40px)] overflow-y-auto",
|
|
851
|
+
body: [
|
|
852
|
+
modalHead("flag", `Report a problem with ${tool.name}`),
|
|
853
|
+
el("p", { class: "m-0 text-sm text-ink-2" },
|
|
854
|
+
"Tell us what went wrong and the issue opens on GitHub with this page and browser already filled in."),
|
|
855
|
+
form,
|
|
856
|
+
],
|
|
857
|
+
actions: [submit],
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
function reportButton(tool) {
|
|
862
|
+
return button("Report a problem", {
|
|
863
|
+
icon: "flag",
|
|
864
|
+
class: "mt-4",
|
|
865
|
+
onclick: () => openReport(tool),
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
|
|
757
869
|
async function toolPage(tool, category) {
|
|
758
870
|
const token = ++navToken;
|
|
759
871
|
const slot = el("div", {});
|
|
@@ -764,6 +876,7 @@ async function toolPage(tool, category) {
|
|
|
764
876
|
{ class: PAGE_NARROW },
|
|
765
877
|
benchHead(tool, category),
|
|
766
878
|
slot,
|
|
879
|
+
el("div", { class: "flex flex-col items-start" }, reportButton(tool)),
|
|
767
880
|
more
|
|
768
881
|
);
|
|
769
882
|
|
|
@@ -900,6 +1013,20 @@ const scrollMemory = new Map();
|
|
|
900
1013
|
let activePath = null;
|
|
901
1014
|
let historyMove = false;
|
|
902
1015
|
|
|
1016
|
+
|
|
1017
|
+
// Sticky everywhere except the tools index and a single tool page, where
|
|
1018
|
+
// the page owns the whole frame and the navbar would steal vertical space.
|
|
1019
|
+
function pinMasthead(path) {
|
|
1020
|
+
const head = document.getElementById("masthead");
|
|
1021
|
+
if (!head) return;
|
|
1022
|
+
const pinned = !(
|
|
1023
|
+
path === "/tools" ||
|
|
1024
|
+
/^\/[^/]+\/[^/]+$/.test(path)
|
|
1025
|
+
);
|
|
1026
|
+
if (pinned) head.dataset.pin = "";
|
|
1027
|
+
else delete head.dataset.pin;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
903
1030
|
async function render(path) {
|
|
904
1031
|
const restoring = historyMove;
|
|
905
1032
|
historyMove = false;
|
|
@@ -909,6 +1036,7 @@ async function render(path) {
|
|
|
909
1036
|
if (!node) return;
|
|
910
1037
|
$("#view").replaceChildren(node);
|
|
911
1038
|
markActiveNav(["/", "/tools", "/categories", "/about"].includes(path) ? path : "");
|
|
1039
|
+
pinMasthead(path);
|
|
912
1040
|
activePath = path;
|
|
913
1041
|
window.scrollTo({ top: restoring ? scrollMemory.get(path) ?? 0 : 0 });
|
|
914
1042
|
if (!history.state?.mevebu) history.replaceState({ mevebu: true }, "", location.href);
|
package/mevebu/app/tailwind.css
CHANGED
|
@@ -208,18 +208,12 @@
|
|
|
208
208
|
.static {
|
|
209
209
|
position: static;
|
|
210
210
|
}
|
|
211
|
-
.sticky {
|
|
212
|
-
position: sticky;
|
|
213
|
-
}
|
|
214
211
|
.inset-0 {
|
|
215
212
|
inset: 0px;
|
|
216
213
|
}
|
|
217
214
|
.end-3 {
|
|
218
215
|
inset-inline-end: calc(var(--spacing) * 3);
|
|
219
216
|
}
|
|
220
|
-
.top-0 {
|
|
221
|
-
top: 0px;
|
|
222
|
-
}
|
|
223
217
|
.top-0\.5 {
|
|
224
218
|
top: calc(var(--spacing) * 0.5);
|
|
225
219
|
}
|
|
@@ -265,6 +259,9 @@
|
|
|
265
259
|
.m-0 {
|
|
266
260
|
margin: 0px;
|
|
267
261
|
}
|
|
262
|
+
.m-auto {
|
|
263
|
+
margin: auto;
|
|
264
|
+
}
|
|
268
265
|
.mx-\[var\(--margin\)\] {
|
|
269
266
|
margin-inline: var(--margin);
|
|
270
267
|
}
|
|
@@ -304,6 +301,9 @@
|
|
|
304
301
|
.mt-3\.5 {
|
|
305
302
|
margin-top: calc(var(--spacing) * 3.5);
|
|
306
303
|
}
|
|
304
|
+
.mt-4 {
|
|
305
|
+
margin-top: calc(var(--spacing) * 4);
|
|
306
|
+
}
|
|
307
307
|
.mt-5 {
|
|
308
308
|
margin-top: calc(var(--spacing) * 5);
|
|
309
309
|
}
|
|
@@ -469,6 +469,9 @@
|
|
|
469
469
|
.max-h-\[380px\] {
|
|
470
470
|
max-height: 380px;
|
|
471
471
|
}
|
|
472
|
+
.max-h-\[calc\(100dvh-40px\)\] {
|
|
473
|
+
max-height: calc(100dvh - 40px);
|
|
474
|
+
}
|
|
472
475
|
.max-h-\[min\(60vh\,360px\)\] {
|
|
473
476
|
max-height: min(60vh, 360px);
|
|
474
477
|
}
|
|
@@ -523,6 +526,9 @@
|
|
|
523
526
|
.w-\[min\(480px\,100\%\)\] {
|
|
524
527
|
width: min(480px, 100%);
|
|
525
528
|
}
|
|
529
|
+
.w-\[min\(560px\,100\%\)\] {
|
|
530
|
+
width: min(560px, 100%);
|
|
531
|
+
}
|
|
526
532
|
.w-\[min\(640px\,100\%\)\] {
|
|
527
533
|
width: min(640px, 100%);
|
|
528
534
|
}
|
|
@@ -923,6 +929,9 @@
|
|
|
923
929
|
.p-2 {
|
|
924
930
|
padding: calc(var(--spacing) * 2);
|
|
925
931
|
}
|
|
932
|
+
.p-3\.5 {
|
|
933
|
+
padding: calc(var(--spacing) * 3.5);
|
|
934
|
+
}
|
|
926
935
|
.p-5 {
|
|
927
936
|
padding: calc(var(--spacing) * 5);
|
|
928
937
|
}
|
|
@@ -1016,6 +1025,9 @@
|
|
|
1016
1025
|
.py-\[13px\] {
|
|
1017
1026
|
padding-block: 13px;
|
|
1018
1027
|
}
|
|
1028
|
+
.py-\[clamp\(20px\,5vh\,40px\)\] {
|
|
1029
|
+
padding-block: clamp(20px, 5vh, 40px);
|
|
1030
|
+
}
|
|
1019
1031
|
.py-\[clamp\(28px\,6vw\,56px\)\] {
|
|
1020
1032
|
padding-block: clamp(28px, 6vw, 56px);
|
|
1021
1033
|
}
|
|
@@ -1082,9 +1094,6 @@
|
|
|
1082
1094
|
.pt-\[clamp\(32px\,5vw\,60px\)\] {
|
|
1083
1095
|
padding-top: clamp(32px, 5vw, 60px);
|
|
1084
1096
|
}
|
|
1085
|
-
.pt-\[clamp\(60px\,9vh\,110px\)\] {
|
|
1086
|
-
padding-top: clamp(60px, 9vh, 110px);
|
|
1087
|
-
}
|
|
1088
1097
|
.pb-2 {
|
|
1089
1098
|
padding-bottom: calc(var(--spacing) * 2);
|
|
1090
1099
|
}
|
|
@@ -1094,9 +1103,6 @@
|
|
|
1094
1103
|
.pb-7 {
|
|
1095
1104
|
padding-bottom: calc(var(--spacing) * 7);
|
|
1096
1105
|
}
|
|
1097
|
-
.pb-10 {
|
|
1098
|
-
padding-bottom: calc(var(--spacing) * 10);
|
|
1099
|
-
}
|
|
1100
1106
|
.pb-\[var\(--margin\)\] {
|
|
1101
1107
|
padding-bottom: var(--margin);
|
|
1102
1108
|
}
|
|
@@ -1582,6 +1588,17 @@
|
|
|
1582
1588
|
--tw-shadow: 0 0 0 1px var(--tw-shadow-color, var(--orbit));
|
|
1583
1589
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
1584
1590
|
}
|
|
1591
|
+
.data-\[pin\]\:sticky[data-pin] {
|
|
1592
|
+
position: sticky;
|
|
1593
|
+
}
|
|
1594
|
+
.data-\[pin\]\:top-0[data-pin] {
|
|
1595
|
+
top: 0px;
|
|
1596
|
+
}
|
|
1597
|
+
.data-\[pin\]\:transition-shadow[data-pin] {
|
|
1598
|
+
transition-property: box-shadow;
|
|
1599
|
+
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
|
1600
|
+
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
|
1601
|
+
}
|
|
1585
1602
|
.data-\[state\=open\]\:opacity-100[data-state="open"] {
|
|
1586
1603
|
opacity: 100%;
|
|
1587
1604
|
}
|
package/mevebu/libs/js/core.js
CHANGED
|
@@ -197,14 +197,14 @@ export function modalHead(iconName, title) {
|
|
|
197
197
|
export function modal({ label, body, actions = [], onOpen, onClose, panelClass } = {}) {
|
|
198
198
|
lastFocus = document.activeElement;
|
|
199
199
|
const veil = el("div", {
|
|
200
|
-
class: "group fixed inset-0 z-80 grid
|
|
200
|
+
class: "group fixed inset-0 z-80 grid place-items-center overflow-y-auto bg-[var(--scrim)] px-5 py-[clamp(20px,5vh,40px)] opacity-0 transition-opacity duration-200 data-[state=open]:opacity-100",
|
|
201
201
|
});
|
|
202
202
|
const panel = el(
|
|
203
203
|
"div",
|
|
204
204
|
{
|
|
205
205
|
class:
|
|
206
206
|
"relative grid gap-4 rounded-r3 border border-orbit bg-deck shadow-[var(--shadow)] transition-transform duration-200 ease-[var(--ease)] translate-y-3.5 scale-[0.97] group-data-[state=open]:translate-y-0 group-data-[state=open]:scale-100 " +
|
|
207
|
-
(panelClass ?? "w-[min(480px,100%)] p-[clamp(22px,3vw,28px)]"),
|
|
207
|
+
(panelClass ?? "m-auto w-[min(480px,100%)] p-[clamp(22px,3vw,28px)]"),
|
|
208
208
|
role: "dialog",
|
|
209
209
|
"aria-modal": "true",
|
|
210
210
|
"aria-label": label,
|
|
@@ -750,7 +750,7 @@ export function blank(iconName, text) {
|
|
|
750
750
|
// ---------- version ----------
|
|
751
751
|
|
|
752
752
|
// Kept in one place. The CLI reads the same value from package.json.
|
|
753
|
-
export const VERSION = "1.7.
|
|
753
|
+
export const VERSION = "1.7.3";
|
|
754
754
|
export const PACKAGE_NAME = "mevebu";
|
|
755
755
|
export const REPO_SLUG = "mevebu/mevebu";
|
|
756
756
|
|
package/mevebu/libs/js/icons.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// GENERATED FILE, DO NOT EDIT.
|
|
2
|
-
// Source: lucide v1.
|
|
2
|
+
// Source: lucide v1.59.0 (ISC), icons/173 names from scripts/vendor-icons.mjs
|
|
3
3
|
// Regenerate with: npm run icons
|
|
4
4
|
|
|
5
5
|
const D = {
|
|
@@ -13,9 +13,11 @@ const D = {
|
|
|
13
13
|
"coffee": [ ["path", { d: "M10 2v2" }], ["path", { d: "M14 2v2" }], [ "path", { d: "M16 8a1 1 0 0 1 1 1v8a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1h14a4 4 0 1 1 0 8h-1" } ], ["path", { d: "M6 2v2" }] ],
|
|
14
14
|
"external-link": [ ["path", { d: "M15 3h6v6" }], ["path", { d: "M10 14 21 3" }], ["path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }] ],
|
|
15
15
|
"corner-down-left": [ ["path", { d: "M20 4v7a4 4 0 0 1-4 4H4" }], ["path", { d: "m9 10-5 5 5 5" }] ],
|
|
16
|
+
"flag": [ [ "path", { d: "M4 22V4a1 1 0 0 1 .4-.8A6 6 0 0 1 8 2c3 0 5 2 7.333 2q2 0 3.067-.8A1 1 0 0 1 20 4v10a1 1 0 0 1-.4.8A6 6 0 0 1 16 16c-3 0-5-2-8-2a6 6 0 0 0-4 1.528" } ] ],
|
|
16
17
|
"info": [ ["circle", { cx: "12", cy: "12", r: "10" }], ["path", { d: "M12 16v-4" }], ["path", { d: "M12 8h.01" }] ],
|
|
17
18
|
"circle-question-mark": [ ["circle", { cx: "12", cy: "12", r: "10" }], ["path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }], ["path", { d: "M12 17h.01" }] ],
|
|
18
19
|
"circle-arrow-up": [ ["circle", { cx: "12", cy: "12", r: "10" }], ["path", { d: "m16 12-4-4-4 4" }], ["path", { d: "M12 16V8" }] ],
|
|
20
|
+
"bug": [ ["path", { d: "M12 20v-9" }], ["path", { d: "M14 7a4 4 0 0 1 4 4v3a6 6 0 0 1-12 0v-3a4 4 0 0 1 4-4z" }], ["path", { d: "M14.12 3.88 16 2" }], ["path", { d: "M21 21a4 4 0 0 0-3.81-4" }], ["path", { d: "M21 5a4 4 0 0 1-3.55 3.97" }], ["path", { d: "M22 13h-4" }], ["path", { d: "M3 21a4 4 0 0 1 3.81-4" }], ["path", { d: "M3 5a4 4 0 0 0 3.55 3.97" }], ["path", { d: "M6 13H2" }], ["path", { d: "m8 2 1.88 1.88" }], ["path", { d: "M9 7.13V6a3 3 0 1 1 6 0v1.13" }] ],
|
|
19
21
|
"shuffle": [ ["path", { d: "m18 14 4 4-4 4" }], ["path", { d: "m18 2 4 4-4 4" }], ["path", { d: "M2 18h1.973a4 4 0 0 0 3.3-1.7l5.454-8.6a4 4 0 0 1 3.3-1.7H22" }], ["path", { d: "M2 6h1.972a4 4 0 0 1 3.6 2.2" }], ["path", { d: "M22 18h-6.041a4 4 0 0 1-3.3-1.8l-.359-.45" }] ],
|
|
20
22
|
"shield-check": [ [ "path", { d: "M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" } ], ["path", { d: "m9 12 2 2 4-4" }] ],
|
|
21
23
|
"terminal": [ ["path", { d: "M12 19h8" }], ["path", { d: "m4 17 6-6-6-6" }] ],
|
|
@@ -57,6 +59,9 @@ const D = {
|
|
|
57
59
|
"loader": [ ["path", { d: "M12 2v4" }], ["path", { d: "m16.2 7.8 2.9-2.9" }], ["path", { d: "M18 12h4" }], ["path", { d: "m16.2 16.2 2.9 2.9" }], ["path", { d: "M12 18v4" }], ["path", { d: "m4.9 19.1 2.9-2.9" }], ["path", { d: "M2 12h4" }], ["path", { d: "m4.9 4.9 2.9 2.9" }] ],
|
|
58
60
|
"play": [ [ "path", { d: "M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z" } ] ],
|
|
59
61
|
"lock": [ ["rect", { width: "18", height: "11", x: "3", y: "11", rx: "2", ry: "2" }], ["path", { d: "M7 11V7a5 5 0 0 1 10 0v4" }] ],
|
|
62
|
+
"wrench": [ [ "path", { d: "M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z" } ] ],
|
|
63
|
+
"gauge": [ ["path", { d: "m12 14 4-4" }], ["path", { d: "M3.34 19a10 10 0 1 1 17.32 0" }] ],
|
|
64
|
+
"monitor": [ ["rect", { width: "20", height: "14", x: "2", y: "3", rx: "2" }], ["line", { x1: "8", x2: "16", y1: "21", y2: "21" }], ["line", { x1: "12", x2: "12", y1: "17", y2: "21" }] ],
|
|
60
65
|
"calendar-days": [ ["path", { d: "M8 2v3" }], ["path", { d: "M16 2v3" }], ["rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }], ["path", { d: "M3 9h18" }], ["path", { d: "M8 13h.01" }], ["path", { d: "M12 13h.01" }], ["path", { d: "M16 13h.01" }], ["path", { d: "M8 17h.01" }], ["path", { d: "M12 17h.01" }], ["path", { d: "M16 17h.01" }] ],
|
|
61
66
|
"graduation-cap": [ [ "path", { d: "M21.42 10.922a1 1 0 0 0-.019-1.838L12.83 5.18a2 2 0 0 0-1.66 0L2.6 9.08a1 1 0 0 0 0 1.832l8.57 3.908a2 2 0 0 0 1.66 0z" } ], ["path", { d: "M22 10v6" }], ["path", { d: "M6 12.5V16a6 3 0 0 0 12 0v-3.5" }] ],
|
|
62
67
|
"calculator": [ ["rect", { width: "16", height: "20", x: "4", y: "2", rx: "2" }], ["line", { x1: "8", x2: "16", y1: "6", y2: "6" }], ["line", { x1: "16", x2: "16", y1: "14", y2: "18" }], ["path", { d: "M16 10h.01" }], ["path", { d: "M12 10h.01" }], ["path", { d: "M8 10h.01" }], ["path", { d: "M12 14h.01" }], ["path", { d: "M8 14h.01" }], ["path", { d: "M12 18h.01" }], ["path", { d: "M8 18h.01" }] ],
|