@memobit/libs 3.8.3 → 3.10.0
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 +96 -95
- package/dist/components/Confetti/Confetti2.js +26 -25
- package/dist/components/ErrorBoundary/ErrorBoundary2.js +9 -8
- package/dist/components/Icon/Icon2.js +34 -17
- package/dist/components/IconPicker/IconPicker2.js +43 -29
- package/dist/components/InputDate/InputDate2.js +16 -15
- package/dist/components/InputEmail/InputEmail2.js +22 -21
- package/dist/components/InputFile/InputFile2.js +9 -8
- package/dist/components/InputNumber/InputNumber2.js +7 -6
- package/dist/components/InputPassword/InputPassword2.js +6 -5
- package/dist/components/InputSearch/InputSearch2.js +18 -17
- package/dist/components/InputText/InputText2.js +6 -5
- package/dist/components/InputTextarea/InputTextarea2.js +11 -10
- package/dist/components/InputTime/InputTime2.js +35 -34
- package/dist/components/InputUrl/InputUrl2.js +20 -19
- package/dist/components/QuantitySelector/QuantitySelector2.js +19 -18
- package/dist/errors.d.ts +78 -0
- package/dist/errors.js +9 -0
- package/dist/helpers/ErrorReporting.js +179 -0
- package/dist/helpers/Logger.js +31 -0
- package/dist/helpers/VersionInfo.js +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/memobit-icons.json +1 -41
- package/dist/styles/base.scss +36 -36
- package/dist/styles/effects.scss +72 -72
- package/dist/styles/highlight.scss +6 -6
- package/dist/styles/scrollbars.scss +30 -30
- package/dist/styles/utilities.scss +238 -238
- package/dist/styles/utility-classes.scss +93 -93
- package/dist/styles/variables.scss +73 -73
- package/dist/version.js +2 -2
- package/dist/version.json +4 -4
- package/package.json +148 -142
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export declare type ErrorReportContext = Record<string, unknown>;
|
|
2
|
+
|
|
3
|
+
export declare interface ErrorReportingConfig {
|
|
4
|
+
/** The app id registered in the hub, e.g. `garage`. */
|
|
5
|
+
appId: string;
|
|
6
|
+
/** The hub ingest URL, e.g. `https://hub.memobit.ro/api/errors/ingest`. */
|
|
7
|
+
endpoint: string;
|
|
8
|
+
/** Turns reporting off for this run, e.g. `import.meta.env.PROD` to report only from production builds. Defaults to true. */
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
/** Shown in the hub next to each error. Defaults to `production`. */
|
|
11
|
+
environment?: string;
|
|
12
|
+
/** Build or commit the errors came from. */
|
|
13
|
+
release?: string;
|
|
14
|
+
/** Also report `console.error` and `console.warn` calls. Defaults to true. */
|
|
15
|
+
captureConsole?: boolean;
|
|
16
|
+
/** Messages to drop, on top of the built-in browser noise filters. */
|
|
17
|
+
ignore?: (string | RegExp)[];
|
|
18
|
+
/** Most events sent per page load or process run. Defaults to 200. */
|
|
19
|
+
maxEventsPerSession?: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Error reporting shared by every memobit app, in the browser and in Node. Errors and
|
|
24
|
+
* warnings are batched and POSTed to the hub's errors/ingest endpoint, which groups them,
|
|
25
|
+
* lists them on the hub's Errors page and emails on new errors and on spikes.
|
|
26
|
+
*
|
|
27
|
+
* React-free on purpose (it ships through the `@memobit/libs/errors` entry), so Node
|
|
28
|
+
* servers can use it too. The hub can switch reporting off — globally, per app, or
|
|
29
|
+
* automatically on a spike — and the reporter then stays quiet for as long as it is told.
|
|
30
|
+
*/
|
|
31
|
+
export declare type ErrorReportLevel = 'error' | 'warning';
|
|
32
|
+
|
|
33
|
+
/** Sends whatever is queued now instead of waiting for the next batch. */
|
|
34
|
+
export declare const flushErrorReports: () => Promise<void>;
|
|
35
|
+
|
|
36
|
+
/** Browser apps: call once, before rendering. */
|
|
37
|
+
export declare const installErrorReporting: (config: ErrorReportingConfig) => void;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Node servers: call once at startup, passing `process`. Unhandled rejections reach
|
|
41
|
+
* Node's uncaught-exception path, so both are covered. Listening there would stop the
|
|
42
|
+
* crash Node normally does, so — unless the server has its own handler — the process
|
|
43
|
+
* still exits with code 1, once the report is sent (or after 3s).
|
|
44
|
+
*/
|
|
45
|
+
export declare const installNodeErrorReporting: (nodeProcess: NodeProcessLike, config: ErrorReportingConfig) => void;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Use in place of `console.*` in app code. `debug` and `info` only write to the console;
|
|
49
|
+
* `warn` and `error` also report to the hub once error reporting is installed — and only
|
|
50
|
+
* once, even though the console capture is on.
|
|
51
|
+
*/
|
|
52
|
+
export declare const logger: {
|
|
53
|
+
debug: (message: string, context?: ErrorReportContext) => void;
|
|
54
|
+
info: (message: string, context?: ErrorReportContext) => void;
|
|
55
|
+
warn: (message: string, context?: ErrorReportContext) => void;
|
|
56
|
+
/** `error` is the caught value, if there is one; its stack is kept. */
|
|
57
|
+
error: (message: string, error?: unknown, context?: ErrorReportContext) => void;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/** The part of Node's `process` the reporter needs; pass `process` itself. */
|
|
61
|
+
export declare interface NodeProcessLike {
|
|
62
|
+
on(event: 'uncaughtException', listener: (error: Error) => void): unknown;
|
|
63
|
+
listenerCount(event: 'uncaughtException'): number;
|
|
64
|
+
exit(code?: number): void;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Reports a caught error you handled but still want to know about. */
|
|
68
|
+
declare const reportError_2: (error: unknown, context?: ErrorReportContext) => void;
|
|
69
|
+
export { reportError_2 as reportError }
|
|
70
|
+
|
|
71
|
+
export { }
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
declare global {
|
|
75
|
+
interface Window {
|
|
76
|
+
__VERSIONS__: FullVersionInfo;
|
|
77
|
+
}
|
|
78
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { flushErrorReports as o, installErrorReporting as t, installNodeErrorReporting as e, reportError as p } from "./helpers/ErrorReporting.js";
|
|
2
|
+
import { logger as l } from "./helpers/Logger.js";
|
|
3
|
+
export {
|
|
4
|
+
o as flushErrorReports,
|
|
5
|
+
t as installErrorReporting,
|
|
6
|
+
e as installNodeErrorReporting,
|
|
7
|
+
l as logger,
|
|
8
|
+
p as reportError
|
|
9
|
+
};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
var b = 5e3, A = 10, U = 25, _ = 1e3, f = 4e3, m = 60, R = 3e3, T = [/ResizeObserver loop/, /^Script error\.?$/], l = null, u = !1, E = /* @__PURE__ */ new WeakSet(), d = {}, p = (e, r) => e.length > r ? `${e.slice(0, r)}…` : e, v = (e) => typeof e == "object" && e !== null && !Array.isArray(e), $ = (e) => v(e) && (e.enabled === void 0 || typeof e.enabled == "boolean"), s = (e) => {
|
|
2
|
+
if (e instanceof Error) return e.message ? `${e.name}: ${e.message}` : e.name;
|
|
3
|
+
if (typeof e == "string") return e;
|
|
4
|
+
try {
|
|
5
|
+
return p(JSON.stringify(e) ?? String(e), 500);
|
|
6
|
+
} catch {
|
|
7
|
+
return String(e);
|
|
8
|
+
}
|
|
9
|
+
}, C = (e) => {
|
|
10
|
+
const [r, ...n] = e;
|
|
11
|
+
return typeof r != "string" || !/%[sdifoOc]/.test(r) ? e.map(s).join(" ") : [r.replace(/%([sdifoOc%])/g, (t, o) => {
|
|
12
|
+
if (o === "%") return "%";
|
|
13
|
+
if (n.length === 0) return t;
|
|
14
|
+
const a = n.shift();
|
|
15
|
+
return o === "c" ? "" : s(a);
|
|
16
|
+
}), ...n.map(s)].join(" ");
|
|
17
|
+
}, O = (e) => {
|
|
18
|
+
if (e)
|
|
19
|
+
try {
|
|
20
|
+
const r = JSON.stringify(e);
|
|
21
|
+
if (r.length > f) return { truncated: p(r, f) };
|
|
22
|
+
const n = JSON.parse(r);
|
|
23
|
+
return v(n) ? n : void 0;
|
|
24
|
+
} catch {
|
|
25
|
+
return { unserializable: s(e) };
|
|
26
|
+
}
|
|
27
|
+
}, N = () => typeof location > "u" ? void 0 : location.origin + location.pathname, q = (e, r, n) => n?.includes("-extension://") ? !0 : e.ignore.some((t) => typeof t == "string" ? r.includes(t) : t.test(r)), h = (e, r) => {
|
|
28
|
+
e.pausedUntil = Date.now() + Math.max(30, r) * 1e3, e.queue.clear();
|
|
29
|
+
}, g = (e) => {
|
|
30
|
+
e.timer === null && (e.timer = setTimeout(() => {
|
|
31
|
+
c();
|
|
32
|
+
}, b));
|
|
33
|
+
}, y = (e, r) => {
|
|
34
|
+
(d[e] ?? console[e]).apply(console, r);
|
|
35
|
+
}, i = (e) => {
|
|
36
|
+
const r = l;
|
|
37
|
+
if (!(!r || u)) {
|
|
38
|
+
if (typeof e.error == "object" && e.error !== null) {
|
|
39
|
+
if (E.has(e.error)) return;
|
|
40
|
+
E.add(e.error);
|
|
41
|
+
}
|
|
42
|
+
if (!(Date.now() < r.pausedUntil || q(r, e.message, e.stack))) {
|
|
43
|
+
u = !0;
|
|
44
|
+
try {
|
|
45
|
+
const n = p(e.message, _), t = `${e.level}|${n}|${e.stack?.split(`
|
|
46
|
+
`, 2).join("|") ?? ""}`, o = r.queue.get(t);
|
|
47
|
+
if (o) {
|
|
48
|
+
o.count += 1;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (r.sent + r.queue.size >= r.maxEvents) {
|
|
52
|
+
r.capReached || (r.capReached = !0, y("warn", [`[memobit] Error reporting stopped for this session after ${r.maxEvents} events.`]));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
r.queue.set(t, {
|
|
56
|
+
level: e.level,
|
|
57
|
+
message: n,
|
|
58
|
+
stack: e.stack,
|
|
59
|
+
url: N(),
|
|
60
|
+
context: O(e.context),
|
|
61
|
+
count: 1
|
|
62
|
+
}), r.queue.size >= A ? c() : g(r);
|
|
63
|
+
} finally {
|
|
64
|
+
u = !1;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}, x = (e, r) => {
|
|
69
|
+
i({
|
|
70
|
+
level: "error",
|
|
71
|
+
message: s(e),
|
|
72
|
+
stack: e instanceof Error ? e.stack : void 0,
|
|
73
|
+
context: r,
|
|
74
|
+
error: e
|
|
75
|
+
});
|
|
76
|
+
}, c = async () => {
|
|
77
|
+
const e = l;
|
|
78
|
+
if (!e) return;
|
|
79
|
+
e.timer !== null && (clearTimeout(e.timer), e.timer = null);
|
|
80
|
+
const r = [...e.queue.entries()].slice(0, U);
|
|
81
|
+
if (r.length === 0) return;
|
|
82
|
+
r.forEach(([t]) => e.queue.delete(t)), e.sent += r.length;
|
|
83
|
+
const n = JSON.stringify({
|
|
84
|
+
app: e.appId,
|
|
85
|
+
source: e.source,
|
|
86
|
+
environment: e.environment,
|
|
87
|
+
release: e.release,
|
|
88
|
+
events: r.map(([, t]) => t)
|
|
89
|
+
});
|
|
90
|
+
try {
|
|
91
|
+
const t = await (await fetch(e.endpoint, {
|
|
92
|
+
method: "POST",
|
|
93
|
+
headers: { "Content-Type": "text/plain;charset=UTF-8" },
|
|
94
|
+
body: n,
|
|
95
|
+
credentials: "omit",
|
|
96
|
+
keepalive: n.length < 6e4
|
|
97
|
+
})).json().catch(() => null);
|
|
98
|
+
$(t) && t.enabled === !1 && h(e, t.retryAfter ?? m);
|
|
99
|
+
} catch {
|
|
100
|
+
h(e, m);
|
|
101
|
+
}
|
|
102
|
+
e.queue.size > 0 && g(e);
|
|
103
|
+
}, w = (e, r) => l || e.enabled === !1 || !e.appId || !e.endpoint ? !1 : (l = {
|
|
104
|
+
appId: e.appId,
|
|
105
|
+
endpoint: e.endpoint,
|
|
106
|
+
source: r,
|
|
107
|
+
environment: e.environment ?? "production",
|
|
108
|
+
release: e.release,
|
|
109
|
+
ignore: [...T, ...e.ignore ?? []],
|
|
110
|
+
maxEvents: e.maxEventsPerSession ?? 200,
|
|
111
|
+
queue: /* @__PURE__ */ new Map(),
|
|
112
|
+
sent: 0,
|
|
113
|
+
pausedUntil: 0,
|
|
114
|
+
capReached: !1,
|
|
115
|
+
timer: null
|
|
116
|
+
}, !0), S = () => {
|
|
117
|
+
const e = console.error, r = console.warn;
|
|
118
|
+
d.error = e, d.warn = r;
|
|
119
|
+
const n = (t, o) => {
|
|
120
|
+
const a = o.find((k) => k instanceof Error);
|
|
121
|
+
i({
|
|
122
|
+
level: t,
|
|
123
|
+
message: C(o),
|
|
124
|
+
stack: a instanceof Error ? a.stack : void 0,
|
|
125
|
+
error: a
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
console.error = (...t) => {
|
|
129
|
+
e.apply(console, t), n("error", t);
|
|
130
|
+
}, console.warn = (...t) => {
|
|
131
|
+
r.apply(console, t), n("warning", t);
|
|
132
|
+
};
|
|
133
|
+
}, I = (e) => {
|
|
134
|
+
if (typeof window > "u" || !w(e, "client")) return;
|
|
135
|
+
window.addEventListener("error", (n) => {
|
|
136
|
+
const t = n.error;
|
|
137
|
+
i({
|
|
138
|
+
level: "error",
|
|
139
|
+
message: t instanceof Error ? s(t) : n.message || "Unknown error",
|
|
140
|
+
stack: t instanceof Error ? t.stack : `at ${n.filename}:${n.lineno}:${n.colno}`,
|
|
141
|
+
error: t
|
|
142
|
+
});
|
|
143
|
+
}), window.addEventListener("unhandledrejection", (n) => {
|
|
144
|
+
const t = n.reason;
|
|
145
|
+
i({
|
|
146
|
+
level: "error",
|
|
147
|
+
message: `Unhandled rejection: ${s(t)}`,
|
|
148
|
+
stack: t instanceof Error ? t.stack : void 0,
|
|
149
|
+
error: t
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
const r = () => {
|
|
153
|
+
c();
|
|
154
|
+
};
|
|
155
|
+
window.addEventListener("pagehide", r), document.addEventListener("visibilitychange", () => {
|
|
156
|
+
document.visibilityState === "hidden" && r();
|
|
157
|
+
}), e.captureConsole !== !1 && S();
|
|
158
|
+
}, L = (e, r) => {
|
|
159
|
+
w(r, "server") && (e.on("uncaughtException", (n) => {
|
|
160
|
+
if (i({
|
|
161
|
+
level: "error",
|
|
162
|
+
message: `Uncaught ${s(n)}`,
|
|
163
|
+
stack: n.stack,
|
|
164
|
+
error: n
|
|
165
|
+
}), e.listenerCount("uncaughtException") > 1) return;
|
|
166
|
+
y("error", [n]);
|
|
167
|
+
const t = new Promise((o) => setTimeout(o, R));
|
|
168
|
+
Promise.race([c(), t]).finally(() => e.exit(1));
|
|
169
|
+
}), r.captureConsole !== !1 && S());
|
|
170
|
+
};
|
|
171
|
+
export {
|
|
172
|
+
i as captureEvent,
|
|
173
|
+
s as describeValue,
|
|
174
|
+
c as flushErrorReports,
|
|
175
|
+
I as installErrorReporting,
|
|
176
|
+
L as installNodeErrorReporting,
|
|
177
|
+
x as reportError,
|
|
178
|
+
y as writeNativeConsole
|
|
179
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { captureEvent as e, describeValue as d, writeNativeConsole as n } from "./ErrorReporting.js";
|
|
2
|
+
var v = (o, i, r) => {
|
|
3
|
+
const a = [o];
|
|
4
|
+
return r !== void 0 && a.push(r), i !== void 0 && a.push(i), a;
|
|
5
|
+
}, t = {
|
|
6
|
+
debug: (o, i) => {
|
|
7
|
+
n("debug", v(o, i));
|
|
8
|
+
},
|
|
9
|
+
info: (o, i) => {
|
|
10
|
+
n("info", v(o, i));
|
|
11
|
+
},
|
|
12
|
+
warn: (o, i) => {
|
|
13
|
+
n("warn", v(o, i)), e({
|
|
14
|
+
level: "warning",
|
|
15
|
+
message: o,
|
|
16
|
+
context: i
|
|
17
|
+
});
|
|
18
|
+
},
|
|
19
|
+
error: (o, i, r) => {
|
|
20
|
+
n("error", v(o, r, i)), e({
|
|
21
|
+
level: "error",
|
|
22
|
+
message: i === void 0 ? o : `${o}: ${d(i)}`,
|
|
23
|
+
stack: i instanceof Error ? i.stack : void 0,
|
|
24
|
+
context: r,
|
|
25
|
+
error: i
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
export {
|
|
30
|
+
t as logger
|
|
31
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1481,8 +1481,8 @@ export declare interface ErrorBoundaryProps {
|
|
|
1481
1481
|
/** Label for the reset button. Defaults to "Try again". */
|
|
1482
1482
|
resetLabel?: string;
|
|
1483
1483
|
/**
|
|
1484
|
-
* Optional callback invoked when an error is caught.
|
|
1485
|
-
*
|
|
1484
|
+
* Optional callback invoked when an error is caught. Caught errors are already
|
|
1485
|
+
* reported to the hub once error reporting is installed, and always logged to the console.
|
|
1486
1486
|
*/
|
|
1487
1487
|
onError?: (error: Error, info: ErrorInfo) => void;
|
|
1488
1488
|
/**
|
|
@@ -3242,7 +3242,7 @@ export declare interface TimelineMarkerInfo {
|
|
|
3242
3242
|
dateLabel: string;
|
|
3243
3243
|
}
|
|
3244
3244
|
|
|
3245
|
-
export declare const TimelineMarkers: <T extends TimelineMarkersItem>({ items, renderItem, className
|
|
3245
|
+
export declare const TimelineMarkers: <T extends TimelineMarkersItem>({ items, renderItem, className }: TimelineMarkersProps<T>) => JSX.Element;
|
|
3246
3246
|
|
|
3247
3247
|
export declare interface TimelineMarkersItem {
|
|
3248
3248
|
id: string | number;
|
package/dist/memobit-icons.json
CHANGED
|
@@ -5,54 +5,14 @@
|
|
|
5
5
|
"arrow-left",
|
|
6
6
|
"arrow-right",
|
|
7
7
|
"arrow-up",
|
|
8
|
-
"bullet",
|
|
9
|
-
"burst",
|
|
10
|
-
"calendar",
|
|
11
8
|
"calendar-month",
|
|
12
9
|
"calendar-week",
|
|
13
10
|
"caret-down",
|
|
14
11
|
"caret-left",
|
|
15
12
|
"caret-right",
|
|
16
13
|
"caret-up",
|
|
17
|
-
"checkmark",
|
|
18
|
-
"clear",
|
|
19
|
-
"clipboard",
|
|
20
|
-
"comment",
|
|
21
|
-
"confetti",
|
|
22
14
|
"credit-card",
|
|
23
|
-
"empty",
|
|
24
|
-
"file",
|
|
25
|
-
"filters",
|
|
26
|
-
"fireworks",
|
|
27
|
-
"folder",
|
|
28
|
-
"food",
|
|
29
|
-
"gallery",
|
|
30
|
-
"grid",
|
|
31
|
-
"key",
|
|
32
|
-
"link",
|
|
33
|
-
"lock",
|
|
34
|
-
"logout",
|
|
35
|
-
"map",
|
|
36
15
|
"menu-hamburger",
|
|
37
|
-
"
|
|
38
|
-
"other",
|
|
39
|
-
"ownership",
|
|
40
|
-
"pin",
|
|
41
|
-
"plus",
|
|
42
|
-
"previous",
|
|
43
|
-
"radio",
|
|
44
|
-
"return",
|
|
45
|
-
"save",
|
|
46
|
-
"scss",
|
|
47
|
-
"search",
|
|
48
|
-
"sparkle",
|
|
49
|
-
"star",
|
|
50
|
-
"table",
|
|
51
|
-
"target",
|
|
52
|
-
"theme-picker",
|
|
53
|
-
"time",
|
|
54
|
-
"tree",
|
|
55
|
-
"tune",
|
|
56
|
-
"warning"
|
|
16
|
+
"theme-picker"
|
|
57
17
|
]
|
|
58
18
|
}
|
package/dist/styles/base.scss
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
// Universal body painting + sizing. Consumed via themes.scss so every memobit
|
|
2
|
-
// app picks it up automatically.
|
|
3
|
-
//
|
|
4
|
-
// Why this lives here:
|
|
5
|
-
// Theme backgrounds are gradients (multi-stop linear/radial). If the body is
|
|
6
|
-
// shorter than the viewport during initial render — empty content, loading
|
|
7
|
-
// state — the gradient gets tiled vertically by default, producing visible
|
|
8
|
-
// horizontal banding. `min-height: 100vh` ensures the body is at least as tall
|
|
9
|
-
// as the viewport so the gradient renders at full size on first paint;
|
|
10
|
-
// `background-repeat: no-repeat` is a defensive guard for edge cases (zoom,
|
|
11
|
-
// tall viewport with short content after HMR).
|
|
12
|
-
//
|
|
13
|
-
// Do NOT use the `background` shorthand in consumer App.scss — it resets
|
|
14
|
-
// `background-repeat` to its initial `repeat` value and re-introduces the
|
|
15
|
-
// banding. Set `background-image` long-hand if a per-project override is
|
|
16
|
-
// needed; otherwise omit and let this rule own it.
|
|
17
|
-
|
|
18
|
-
html,
|
|
19
|
-
body {
|
|
20
|
-
background: var(--body-background);
|
|
21
|
-
background-repeat: no-repeat;
|
|
22
|
-
margin: 0;
|
|
23
|
-
padding: 0;
|
|
24
|
-
min-height: 100vh;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Ambient glow overlay — themes opt in via `--body-background-glow`. Pinned to
|
|
28
|
-
// the viewport so it stays put on scroll; z-index: -1 keeps it behind app content.
|
|
29
|
-
body::before {
|
|
30
|
-
content: '';
|
|
31
|
-
position: fixed;
|
|
32
|
-
inset: 0;
|
|
33
|
-
z-index: -1;
|
|
34
|
-
background: var(--body-background-glow, none);
|
|
35
|
-
pointer-events: none;
|
|
36
|
-
}
|
|
1
|
+
// Universal body painting + sizing. Consumed via themes.scss so every memobit
|
|
2
|
+
// app picks it up automatically.
|
|
3
|
+
//
|
|
4
|
+
// Why this lives here:
|
|
5
|
+
// Theme backgrounds are gradients (multi-stop linear/radial). If the body is
|
|
6
|
+
// shorter than the viewport during initial render — empty content, loading
|
|
7
|
+
// state — the gradient gets tiled vertically by default, producing visible
|
|
8
|
+
// horizontal banding. `min-height: 100vh` ensures the body is at least as tall
|
|
9
|
+
// as the viewport so the gradient renders at full size on first paint;
|
|
10
|
+
// `background-repeat: no-repeat` is a defensive guard for edge cases (zoom,
|
|
11
|
+
// tall viewport with short content after HMR).
|
|
12
|
+
//
|
|
13
|
+
// Do NOT use the `background` shorthand in consumer App.scss — it resets
|
|
14
|
+
// `background-repeat` to its initial `repeat` value and re-introduces the
|
|
15
|
+
// banding. Set `background-image` long-hand if a per-project override is
|
|
16
|
+
// needed; otherwise omit and let this rule own it.
|
|
17
|
+
|
|
18
|
+
html,
|
|
19
|
+
body {
|
|
20
|
+
background: var(--body-background);
|
|
21
|
+
background-repeat: no-repeat;
|
|
22
|
+
margin: 0;
|
|
23
|
+
padding: 0;
|
|
24
|
+
min-height: 100vh;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Ambient glow overlay — themes opt in via `--body-background-glow`. Pinned to
|
|
28
|
+
// the viewport so it stays put on scroll; z-index: -1 keeps it behind app content.
|
|
29
|
+
body::before {
|
|
30
|
+
content: '';
|
|
31
|
+
position: fixed;
|
|
32
|
+
inset: 0;
|
|
33
|
+
z-index: -1;
|
|
34
|
+
background: var(--body-background-glow, none);
|
|
35
|
+
pointer-events: none;
|
|
36
|
+
}
|
package/dist/styles/effects.scss
CHANGED
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
.note-container-effect {
|
|
2
|
-
font-size: var(--font-size-md);
|
|
3
|
-
line-height: 1.6;
|
|
4
|
-
padding: var(--spacing-16);
|
|
5
|
-
border-radius: var(--spacing-12);
|
|
6
|
-
border-left: var(--spacing-2) solid var(--note-container-effect-border-left-color);
|
|
7
|
-
background-color: var(--note-container-effect-background-color);
|
|
8
|
-
color: var(--note-container-effect-color);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
.infuse-effect {
|
|
12
|
-
border-width: var(--spacing-1);
|
|
13
|
-
border-style: solid;
|
|
14
|
-
transition: all 0.3s;
|
|
15
|
-
position: relative;
|
|
16
|
-
|
|
17
|
-
&::before {
|
|
18
|
-
content: '';
|
|
19
|
-
position: absolute;
|
|
20
|
-
top: 0;
|
|
21
|
-
left: 0;
|
|
22
|
-
background: var(--infuse-effect-before-background);
|
|
23
|
-
width: var(--spacing-4);
|
|
24
|
-
height: 100%;
|
|
25
|
-
opacity: 0;
|
|
26
|
-
transition: opacity 0.3s;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
&:hover {
|
|
30
|
-
transform: translateY(-5px);
|
|
31
|
-
border-color: var(--infuse-effect-hover-border-color);
|
|
32
|
-
box-shadow: 0 var(--spacing-12) var(--spacing-24) var(--infuse-effect-hover-box-shadow-color);
|
|
33
|
-
|
|
34
|
-
&::before {
|
|
35
|
-
opacity: 1;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.up-lift-effect {
|
|
41
|
-
border-width: var(--spacing-1);
|
|
42
|
-
border-style: solid;
|
|
43
|
-
box-shadow: 0 var(--spacing-4) var(--spacing-12) var(--up-lift-effect-box-shadow-color);
|
|
44
|
-
transition: all 0.3s ease;
|
|
45
|
-
position: relative;
|
|
46
|
-
|
|
47
|
-
&::before {
|
|
48
|
-
content: '';
|
|
49
|
-
position: absolute;
|
|
50
|
-
top: 0;
|
|
51
|
-
left: 0;
|
|
52
|
-
width: 5px;
|
|
53
|
-
height: 100%;
|
|
54
|
-
background: var(--up-lift-effect-before-background);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
&:hover {
|
|
58
|
-
transform: translateY(-5px);
|
|
59
|
-
border-color: var(--up-lift-effect-hover-border-color);
|
|
60
|
-
box-shadow: 0 var(--spacing-12) var(--spacing-24) var(--up-lift-effect-hover-box-shadow-color);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
.glow-effect {
|
|
65
|
-
transition: 0.3s;
|
|
66
|
-
|
|
67
|
-
&:hover {
|
|
68
|
-
box-shadow: var(--glow-box-shadow-color);
|
|
69
|
-
transform: translateY(-2px);
|
|
70
|
-
border-color: var(--glow-hover-border-color);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
1
|
+
.note-container-effect {
|
|
2
|
+
font-size: var(--font-size-md);
|
|
3
|
+
line-height: 1.6;
|
|
4
|
+
padding: var(--spacing-16);
|
|
5
|
+
border-radius: var(--spacing-12);
|
|
6
|
+
border-left: var(--spacing-2) solid var(--note-container-effect-border-left-color);
|
|
7
|
+
background-color: var(--note-container-effect-background-color);
|
|
8
|
+
color: var(--note-container-effect-color);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.infuse-effect {
|
|
12
|
+
border-width: var(--spacing-1);
|
|
13
|
+
border-style: solid;
|
|
14
|
+
transition: all 0.3s;
|
|
15
|
+
position: relative;
|
|
16
|
+
|
|
17
|
+
&::before {
|
|
18
|
+
content: '';
|
|
19
|
+
position: absolute;
|
|
20
|
+
top: 0;
|
|
21
|
+
left: 0;
|
|
22
|
+
background: var(--infuse-effect-before-background);
|
|
23
|
+
width: var(--spacing-4);
|
|
24
|
+
height: 100%;
|
|
25
|
+
opacity: 0;
|
|
26
|
+
transition: opacity 0.3s;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&:hover {
|
|
30
|
+
transform: translateY(-5px);
|
|
31
|
+
border-color: var(--infuse-effect-hover-border-color);
|
|
32
|
+
box-shadow: 0 var(--spacing-12) var(--spacing-24) var(--infuse-effect-hover-box-shadow-color);
|
|
33
|
+
|
|
34
|
+
&::before {
|
|
35
|
+
opacity: 1;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.up-lift-effect {
|
|
41
|
+
border-width: var(--spacing-1);
|
|
42
|
+
border-style: solid;
|
|
43
|
+
box-shadow: 0 var(--spacing-4) var(--spacing-12) var(--up-lift-effect-box-shadow-color);
|
|
44
|
+
transition: all 0.3s ease;
|
|
45
|
+
position: relative;
|
|
46
|
+
|
|
47
|
+
&::before {
|
|
48
|
+
content: '';
|
|
49
|
+
position: absolute;
|
|
50
|
+
top: 0;
|
|
51
|
+
left: 0;
|
|
52
|
+
width: 5px;
|
|
53
|
+
height: 100%;
|
|
54
|
+
background: var(--up-lift-effect-before-background);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
&:hover {
|
|
58
|
+
transform: translateY(-5px);
|
|
59
|
+
border-color: var(--up-lift-effect-hover-border-color);
|
|
60
|
+
box-shadow: 0 var(--spacing-12) var(--spacing-24) var(--up-lift-effect-hover-box-shadow-color);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.glow-effect {
|
|
65
|
+
transition: 0.3s;
|
|
66
|
+
|
|
67
|
+
&:hover {
|
|
68
|
+
box-shadow: var(--glow-box-shadow-color);
|
|
69
|
+
transform: translateY(-2px);
|
|
70
|
+
border-color: var(--glow-hover-border-color);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
mark {
|
|
2
|
-
background-color: var(--button-warning-background-color);
|
|
3
|
-
color: var(--button-warning-color);
|
|
4
|
-
padding: var(--spacing-1) var(--spacing-4);
|
|
5
|
-
border-radius: var(--radius-sm);
|
|
6
|
-
}
|
|
1
|
+
mark {
|
|
2
|
+
background-color: var(--button-warning-background-color);
|
|
3
|
+
color: var(--button-warning-color);
|
|
4
|
+
padding: var(--spacing-1) var(--spacing-4);
|
|
5
|
+
border-radius: var(--radius-sm);
|
|
6
|
+
}
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
:root {
|
|
2
|
-
--scrollbar-size: 6px;
|
|
3
|
-
--scrollbar-track-color: transparent;
|
|
4
|
-
--scrollbar-thumb-color: var(--delimiter-color, rgba(128, 128, 128, 0.45));
|
|
5
|
-
--scrollbar-thumb-hover-color: var(--body-color-muted, rgba(128, 128, 128, 0.65));
|
|
6
|
-
--scrollbar-radius: var(--radius-full, 9999px);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
* {
|
|
10
|
-
scrollbar-color: var(--scrollbar-thumb-color) var(--scrollbar-track-color);
|
|
11
|
-
scrollbar-width: thin;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
*::-webkit-scrollbar {
|
|
15
|
-
width: var(--scrollbar-size);
|
|
16
|
-
height: var(--scrollbar-size);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
*::-webkit-scrollbar-track {
|
|
20
|
-
background: var(--scrollbar-track-color);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
*::-webkit-scrollbar-thumb {
|
|
24
|
-
background: var(--scrollbar-thumb-color);
|
|
25
|
-
border-radius: var(--scrollbar-radius);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
*::-webkit-scrollbar-thumb:hover {
|
|
29
|
-
background: var(--scrollbar-thumb-hover-color);
|
|
30
|
-
}
|
|
1
|
+
:root {
|
|
2
|
+
--scrollbar-size: 6px;
|
|
3
|
+
--scrollbar-track-color: transparent;
|
|
4
|
+
--scrollbar-thumb-color: var(--delimiter-color, rgba(128, 128, 128, 0.45));
|
|
5
|
+
--scrollbar-thumb-hover-color: var(--body-color-muted, rgba(128, 128, 128, 0.65));
|
|
6
|
+
--scrollbar-radius: var(--radius-full, 9999px);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
* {
|
|
10
|
+
scrollbar-color: var(--scrollbar-thumb-color) var(--scrollbar-track-color);
|
|
11
|
+
scrollbar-width: thin;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
*::-webkit-scrollbar {
|
|
15
|
+
width: var(--scrollbar-size);
|
|
16
|
+
height: var(--scrollbar-size);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
*::-webkit-scrollbar-track {
|
|
20
|
+
background: var(--scrollbar-track-color);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
*::-webkit-scrollbar-thumb {
|
|
24
|
+
background: var(--scrollbar-thumb-color);
|
|
25
|
+
border-radius: var(--scrollbar-radius);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
*::-webkit-scrollbar-thumb:hover {
|
|
29
|
+
background: var(--scrollbar-thumb-hover-color);
|
|
30
|
+
}
|