elbe-ui 0.2.5 → 0.2.14
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/dist/index.js +17 -2
- package/dist/ui/color_theme.d.ts +5 -0
- package/dist/ui/components/badge.d.ts +25 -0
- package/dist/ui/components/box.d.ts +1027 -0
- package/dist/ui/components/button.d.ts +23 -0
- package/dist/ui/components/card.d.ts +14 -0
- package/dist/ui/components/dialog.d.ts +8 -0
- package/dist/ui/components/flex.d.ts +11 -0
- package/dist/ui/components/icon_button.d.ts +19 -0
- package/dist/ui/components/input/checkbox.d.ts +6 -0
- package/dist/ui/components/input/input_field.d.ts +22 -0
- package/dist/ui/components/input/range.d.ts +8 -0
- package/dist/ui/components/input/select.d.ts +10 -0
- package/dist/ui/components/input/text_area.d.ts +10 -0
- package/dist/ui/components/padded.d.ts +25 -0
- package/dist/ui/components/text.d.ts +33 -0
- package/dist/ui/components/toggle_button.d.ts +12 -0
- package/dist/ui/components/util.d.ts +3 -0
- package/dist/ui/util/confirm_dialog.d.ts +10 -0
- package/dist/ui/util/error_view.d.ts +1 -0
- package/dist/ui/util/toast.d.ts +5 -0
- package/dist/ui/util/util.d.ts +19 -0
- package/elbe.scss +2 -2
- package/package.json +5 -2
- package/src/index.tsx +24 -0
- package/src/ui/color_theme.ts +24 -0
- package/src/ui/components/badge.tsx +78 -0
- package/src/ui/components/box.tsx +49 -0
- package/src/ui/components/button.tsx +61 -0
- package/src/ui/components/card.tsx +45 -0
- package/src/ui/components/dialog.tsx +51 -0
- package/src/ui/components/flex.tsx +64 -0
- package/src/ui/components/icon_button.tsx +56 -0
- package/src/ui/components/input/checkbox.tsx +32 -0
- package/src/ui/components/input/input_field.tsx +57 -0
- package/src/ui/components/input/range.tsx +37 -0
- package/src/ui/components/input/select.tsx +29 -0
- package/src/ui/components/input/text_area.tsx +45 -0
- package/src/ui/components/padded.tsx +62 -0
- package/src/ui/components/text.tsx +78 -0
- package/src/ui/components/toggle_button.tsx +52 -0
- package/src/ui/components/util.tsx +3 -0
- package/src/ui/util/confirm_dialog.ts +53 -0
- package/src/ui/util/error_view.tsx +16 -0
- package/src/ui/util/toast.ts +14 -0
- package/src/ui/util/util.ts +36 -0
- package/style/color_style.scss +148 -0
- package/style/components.scss +450 -0
- package/style/root.scss +50 -0
- package/style/type_style.scss +22 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from "preact/compat";
|
|
2
|
+
import type { ElbeColorManners, ElbeColorStyles } from "../color_theme";
|
|
3
|
+
import { type ElbeProps } from "./box";
|
|
4
|
+
import type { IconChild } from "./icon_button";
|
|
5
|
+
export type ButtonProps = ElbeProps & {
|
|
6
|
+
colorStyle?: ElbeColorStyles;
|
|
7
|
+
onTap?: () => void;
|
|
8
|
+
} & ({
|
|
9
|
+
icon?: IconChild;
|
|
10
|
+
message: string;
|
|
11
|
+
} | {
|
|
12
|
+
icon: IconChild;
|
|
13
|
+
message?: string;
|
|
14
|
+
});
|
|
15
|
+
export declare class Button extends React.Component<ButtonProps & {
|
|
16
|
+
colorManner: ElbeColorManners;
|
|
17
|
+
}> {
|
|
18
|
+
static major: (p: ButtonProps) => React.JSX.Element;
|
|
19
|
+
static minor: (p: ButtonProps) => React.JSX.Element;
|
|
20
|
+
static action: (p: ButtonProps) => React.JSX.Element;
|
|
21
|
+
static integrated: (p: ButtonProps) => React.JSX.Element;
|
|
22
|
+
render(): React.JSX.Element;
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ElbeColorManners, ElbeColorModes, ElbeColorStyles, ElbeColorThemes } from "../color_theme";
|
|
2
|
+
import type { ElbeChildren } from "../util/util";
|
|
3
|
+
import { type ElbeProps } from "./box";
|
|
4
|
+
export declare function Card({ mode, colorScheme, colorStyle, colorManner, padding, margin, onTap, onLongTap, children, ...elbe }: {
|
|
5
|
+
mode?: ElbeColorModes;
|
|
6
|
+
colorScheme?: ElbeColorThemes;
|
|
7
|
+
colorStyle?: ElbeColorStyles;
|
|
8
|
+
colorManner?: ElbeColorManners;
|
|
9
|
+
padding?: number;
|
|
10
|
+
margin?: number;
|
|
11
|
+
onTap?: () => void;
|
|
12
|
+
onLongTap?: () => void;
|
|
13
|
+
children: ElbeChildren;
|
|
14
|
+
} & ElbeProps): import("preact").JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ElbeChildren } from "../util/util";
|
|
2
|
+
export declare function ElbeDialog({ title, open, onClose, children, _style, }: {
|
|
3
|
+
_style?: string;
|
|
4
|
+
title: string;
|
|
5
|
+
open: boolean;
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
children: ElbeChildren;
|
|
8
|
+
}): import("preact").JSX.Element;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ElbeProps } from "./box";
|
|
2
|
+
export type FlexProps = {
|
|
3
|
+
children: any;
|
|
4
|
+
gap?: number;
|
|
5
|
+
stretch?: boolean;
|
|
6
|
+
main?: "start" | "center" | "end" | "stretch" | "space-between" | "space-around" | "space-evenly";
|
|
7
|
+
cross?: "start" | "center" | "end" | "stretch" | "space-between" | "space-around" | "space-evenly";
|
|
8
|
+
} & ElbeProps;
|
|
9
|
+
export declare function FlexSpace({}: {}): import("preact").JSX.Element;
|
|
10
|
+
export declare function Column({ gap, main, cross, stretch, children, ...p }: FlexProps): import("preact").JSX.Element;
|
|
11
|
+
export declare function Row({ gap, main, cross, stretch, children, ...p }: FlexProps): import("preact").JSX.Element;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from "preact/compat";
|
|
2
|
+
import type { ElbeColorManners, ElbeColorStyles } from "../color_theme";
|
|
3
|
+
import type { ElbeChild } from "../util/util";
|
|
4
|
+
import { type ElbeProps } from "./box";
|
|
5
|
+
export type IconChild = ElbeChild | ((_: any) => ElbeChild);
|
|
6
|
+
export type IconButtonProps = {
|
|
7
|
+
icon?: IconChild;
|
|
8
|
+
colorStyle?: ElbeColorStyles;
|
|
9
|
+
onTap?: () => void;
|
|
10
|
+
} & ElbeProps;
|
|
11
|
+
export declare class IconButton extends React.Component<IconButtonProps & {
|
|
12
|
+
colorManner?: ElbeColorManners;
|
|
13
|
+
}> {
|
|
14
|
+
static major: (p: IconButtonProps) => React.JSX.Element;
|
|
15
|
+
static minor: (p: IconButtonProps) => React.JSX.Element;
|
|
16
|
+
static action: (p: IconButtonProps) => React.JSX.Element;
|
|
17
|
+
static integrated: (p: IconButtonProps) => React.JSX.Element;
|
|
18
|
+
render(): React.JSX.Element;
|
|
19
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "preact/compat";
|
|
2
|
+
import { type ElbeProps } from "../box";
|
|
3
|
+
import { _TextArea } from "./text_area";
|
|
4
|
+
export type InputFieldProps = {
|
|
5
|
+
label?: string;
|
|
6
|
+
hint: string;
|
|
7
|
+
readonly?: boolean;
|
|
8
|
+
value: string | number;
|
|
9
|
+
onInput?: (value: string) => void;
|
|
10
|
+
} & ElbeProps;
|
|
11
|
+
export declare class Field extends React.Component<InputFieldProps & {
|
|
12
|
+
type?: "text" | "number" | "password" | "date" | "time" | "email";
|
|
13
|
+
}> {
|
|
14
|
+
static text: (p: InputFieldProps) => React.JSX.Element;
|
|
15
|
+
static number: (p: InputFieldProps) => React.JSX.Element;
|
|
16
|
+
static password: (p: InputFieldProps) => React.JSX.Element;
|
|
17
|
+
static date: (p: InputFieldProps) => React.JSX.Element;
|
|
18
|
+
static time: (p: InputFieldProps) => React.JSX.Element;
|
|
19
|
+
static email: (p: InputFieldProps) => React.JSX.Element;
|
|
20
|
+
static multiLine: typeof _TextArea;
|
|
21
|
+
render(): React.JSX.Element;
|
|
22
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ElbeProps } from "../box";
|
|
2
|
+
export declare function Range({ value, onChange, min, max, step, ...elbe }: {
|
|
3
|
+
value: number;
|
|
4
|
+
min?: number;
|
|
5
|
+
step?: number;
|
|
6
|
+
max?: number;
|
|
7
|
+
onChange?: ((value: number) => void) | null;
|
|
8
|
+
} & ElbeProps): import("preact").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ElbeProps } from "../box";
|
|
2
|
+
export declare function Select({ options, value, label, onChange, ...elbe }: {
|
|
3
|
+
options: {
|
|
4
|
+
key: string;
|
|
5
|
+
label: string;
|
|
6
|
+
}[];
|
|
7
|
+
value?: string;
|
|
8
|
+
label?: string;
|
|
9
|
+
onChange: (value: string) => any;
|
|
10
|
+
} & ElbeProps): import("preact").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ElbeProps } from "../box";
|
|
2
|
+
export declare function _TextArea({ label, hint, readonly, rows, maxLength, value, onInput, ...elbe }: {
|
|
3
|
+
label?: string;
|
|
4
|
+
hint: string;
|
|
5
|
+
rows?: number;
|
|
6
|
+
maxLength?: number;
|
|
7
|
+
readonly?: boolean;
|
|
8
|
+
value: string | number;
|
|
9
|
+
onInput?: (value: string) => void;
|
|
10
|
+
} & ElbeProps): import("preact").JSX.Element;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from "preact/compat";
|
|
2
|
+
export type PaddedProps = {
|
|
3
|
+
children: any;
|
|
4
|
+
};
|
|
5
|
+
export declare class Padded extends React.Component<PaddedProps & {
|
|
6
|
+
top: number;
|
|
7
|
+
right: number;
|
|
8
|
+
bottom: number;
|
|
9
|
+
left: number;
|
|
10
|
+
}> {
|
|
11
|
+
constructor(props: PaddedProps & {
|
|
12
|
+
top: number;
|
|
13
|
+
right: number;
|
|
14
|
+
bottom: number;
|
|
15
|
+
left: number;
|
|
16
|
+
});
|
|
17
|
+
static all: ({ amount, ...p }: PaddedProps & {
|
|
18
|
+
amount: number;
|
|
19
|
+
}) => React.JSX.Element;
|
|
20
|
+
static symmetric: ({ vertical, horizontal, ...p }: PaddedProps & {
|
|
21
|
+
vertical: number;
|
|
22
|
+
horizontal: number;
|
|
23
|
+
}) => React.JSX.Element;
|
|
24
|
+
render(): React.JSX.Element;
|
|
25
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from "preact/compat";
|
|
2
|
+
import type { ElbeTypeStyles } from "../color_theme";
|
|
3
|
+
import type { ElbeChildren } from "../util/util";
|
|
4
|
+
import { type ElbeProps } from "./box";
|
|
5
|
+
export type TextProps = {
|
|
6
|
+
align?: "start" | "center" | "end";
|
|
7
|
+
bold?: boolean;
|
|
8
|
+
italic?: boolean;
|
|
9
|
+
underline?: boolean;
|
|
10
|
+
striked?: boolean;
|
|
11
|
+
color?: string;
|
|
12
|
+
size?: number;
|
|
13
|
+
children?: ElbeChildren;
|
|
14
|
+
v?: string;
|
|
15
|
+
} & ElbeProps;
|
|
16
|
+
export declare class Text extends React.Component<TextProps & {
|
|
17
|
+
typeStyle?: ElbeTypeStyles;
|
|
18
|
+
}> {
|
|
19
|
+
static h1: (p: TextProps) => React.JSX.Element;
|
|
20
|
+
static h2: (p: TextProps) => React.JSX.Element;
|
|
21
|
+
static h3: (p: TextProps) => React.JSX.Element;
|
|
22
|
+
static h4: (p: TextProps) => React.JSX.Element;
|
|
23
|
+
static h5: (p: TextProps) => React.JSX.Element;
|
|
24
|
+
static h6: (p: TextProps) => React.JSX.Element;
|
|
25
|
+
static s: (p: TextProps) => React.JSX.Element;
|
|
26
|
+
static m: (p: TextProps) => React.JSX.Element;
|
|
27
|
+
static l: (p: TextProps) => React.JSX.Element;
|
|
28
|
+
static code: (p: TextProps) => React.JSX.Element;
|
|
29
|
+
constructor({ typeStyle, ...props }: TextProps & {
|
|
30
|
+
typeStyle?: ElbeTypeStyles;
|
|
31
|
+
});
|
|
32
|
+
render(): React.JSX.Element;
|
|
33
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ElbeChild } from "../util/util";
|
|
2
|
+
import type { ElbeProps } from "./box";
|
|
3
|
+
export type ToggleButtonItem<T> = {
|
|
4
|
+
icon?: (_: any) => ElbeChild;
|
|
5
|
+
label: string;
|
|
6
|
+
key: T;
|
|
7
|
+
};
|
|
8
|
+
export declare function ToggleButton<T>({ items, onSelect, value, ...elbe }: {
|
|
9
|
+
items: ToggleButtonItem<T>[];
|
|
10
|
+
onSelect: ((value: T) => void) | null;
|
|
11
|
+
value: T;
|
|
12
|
+
} & ElbeProps): import("preact").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* show a simple confirm dialog
|
|
3
|
+
* @param param0 the title and message of the dialog
|
|
4
|
+
* @returns a promise that resolves to true if the user clicks "yes" or "okay" and false if the user clicks "no"
|
|
5
|
+
*/
|
|
6
|
+
export declare function showConfirmDialog({ title, message, okay, }: {
|
|
7
|
+
message: string;
|
|
8
|
+
title: string;
|
|
9
|
+
okay?: boolean;
|
|
10
|
+
}): Promise<boolean>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function _ElbeErr(msg: string): import("preact").JSX.Element;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type React from "preact/compat";
|
|
2
|
+
export type ElbeChild = React.ReactNode;
|
|
3
|
+
export type ElbeChildren = ElbeChild[] | ElbeChild;
|
|
4
|
+
/**
|
|
5
|
+
* use the web share api if available, otherwise copy the data to the clipboard
|
|
6
|
+
* @param data the data you want to share
|
|
7
|
+
* @param toastMsg the message to show in the toast if the share api is not available
|
|
8
|
+
*/
|
|
9
|
+
export declare function share(data: {
|
|
10
|
+
title: string;
|
|
11
|
+
text?: string;
|
|
12
|
+
url: string;
|
|
13
|
+
}, toastMsg?: string): void;
|
|
14
|
+
/**
|
|
15
|
+
* copy the text to the clipboard
|
|
16
|
+
* @param text the text to copy to the clipboard
|
|
17
|
+
* @param toastMsg the message to show in the toast
|
|
18
|
+
*/
|
|
19
|
+
export declare function copyToClipboard(text: string, toastMsg?: string): void;
|
package/elbe.scss
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
@import url("https://fonts.googleapis.com/css2?family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap");
|
|
7
|
-
@import url("https://fonts.googleapis.com/css2?family=Inter:
|
|
7
|
+
@import url("https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap");
|
|
8
8
|
@import url("https://fonts.googleapis.com/css2?family=Calistoga&display=swap");
|
|
9
9
|
@import url("https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&display=swap");
|
|
10
10
|
|
|
@@ -30,7 +30,7 @@ $c-modes: (
|
|
|
30
30
|
border: #ffffff14,
|
|
31
31
|
),
|
|
32
32
|
secondary: (
|
|
33
|
-
back: inter($c-accent, #ffffff,
|
|
33
|
+
back: inter($c-accent, #ffffff, 7%),
|
|
34
34
|
front: #222222,
|
|
35
35
|
border: #22222214,
|
|
36
36
|
),
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "elbe-ui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.14",
|
|
5
5
|
"author": "Robin Naumann",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -15,8 +15,11 @@
|
|
|
15
15
|
],
|
|
16
16
|
"files": [
|
|
17
17
|
"elbe.scss",
|
|
18
|
+
"style/*.scss",
|
|
18
19
|
"dist/*.js",
|
|
19
|
-
"
|
|
20
|
+
"src/**/*.ts",
|
|
21
|
+
"src/**/*.tsx",
|
|
22
|
+
"dist/**/*.d.ts"
|
|
20
23
|
],
|
|
21
24
|
"main": "dist/index.js",
|
|
22
25
|
"types": "dist/index.d.ts",
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as Lucide from "lucide-react";
|
|
2
|
+
|
|
3
|
+
// exports
|
|
4
|
+
export * from "./ui/color_theme";
|
|
5
|
+
export * from "./ui/components/badge";
|
|
6
|
+
export * from "./ui/components/box";
|
|
7
|
+
export * from "./ui/components/button";
|
|
8
|
+
export * from "./ui/components/card";
|
|
9
|
+
export * from "./ui/components/dialog";
|
|
10
|
+
export * from "./ui/components/flex";
|
|
11
|
+
export * from "./ui/components/icon_button";
|
|
12
|
+
export * from "./ui/components/input/checkbox";
|
|
13
|
+
export * from "./ui/components/input/input_field";
|
|
14
|
+
export * from "./ui/components/input/range";
|
|
15
|
+
export * from "./ui/components/input/select";
|
|
16
|
+
export * from "./ui/components/padded";
|
|
17
|
+
export * from "./ui/components/text";
|
|
18
|
+
export * from "./ui/components/toggle_button";
|
|
19
|
+
export * from "./ui/components/util";
|
|
20
|
+
export * from "./ui/util/confirm_dialog";
|
|
21
|
+
export * from "./ui/util/toast";
|
|
22
|
+
export * from "./ui/util/util";
|
|
23
|
+
|
|
24
|
+
export const Icons = Lucide.icons;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type ElbeColorStyles =
|
|
2
|
+
| "accent"
|
|
3
|
+
| "error"
|
|
4
|
+
| "warning"
|
|
5
|
+
| "success"
|
|
6
|
+
| "info";
|
|
7
|
+
|
|
8
|
+
export type ElbeColorManners = "major" | "minor" | "action" | "integrated";
|
|
9
|
+
|
|
10
|
+
export type ElbeColorThemes = "primary" | "secondary" | "inverse";
|
|
11
|
+
|
|
12
|
+
export type ElbeColorModes = "light" | "dark";
|
|
13
|
+
|
|
14
|
+
export type ElbeTypeStyles =
|
|
15
|
+
| "header-1"
|
|
16
|
+
| "header-2"
|
|
17
|
+
| "header-3"
|
|
18
|
+
| "header-4"
|
|
19
|
+
| "header-5"
|
|
20
|
+
| "header-6"
|
|
21
|
+
| "text-s"
|
|
22
|
+
| "text-m"
|
|
23
|
+
| "text-l"
|
|
24
|
+
| "code";
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React from "preact/compat";
|
|
2
|
+
import type { ElbeColorStyles } from "../color_theme";
|
|
3
|
+
import type { ElbeChild, ElbeChildren } from "../util/util";
|
|
4
|
+
import type { ElbeProps } from "./box";
|
|
5
|
+
|
|
6
|
+
export type BadgeProps = {
|
|
7
|
+
count?: number;
|
|
8
|
+
message?: string;
|
|
9
|
+
child?: ElbeChild;
|
|
10
|
+
hidden?: boolean;
|
|
11
|
+
children?: ElbeChildren;
|
|
12
|
+
} & ElbeProps;
|
|
13
|
+
|
|
14
|
+
export function TestBadge(p: BadgeProps) {
|
|
15
|
+
return new Badge({ ...p, colorStyle: "accent" });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class Badge extends React.Component<
|
|
19
|
+
BadgeProps & { colorStyle: ElbeColorStyles }
|
|
20
|
+
> {
|
|
21
|
+
constructor(props: BadgeProps & { colorStyle: ElbeColorStyles }) {
|
|
22
|
+
super(props);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static accent(p: BadgeProps) {
|
|
26
|
+
return <Badge {...p} colorStyle="accent" />;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static error(p: BadgeProps) {
|
|
30
|
+
return <Badge {...p} colorStyle="error" />;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static warning(p: BadgeProps) {
|
|
34
|
+
return <Badge {...p} colorStyle="warning" />;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static success(p: BadgeProps) {
|
|
38
|
+
return <Badge {...p} colorStyle="success" />;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static info(p: BadgeProps) {
|
|
42
|
+
return <Badge {...p} colorStyle="info" />;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
render() {
|
|
46
|
+
return (
|
|
47
|
+
<div
|
|
48
|
+
style={{
|
|
49
|
+
position: "relative",
|
|
50
|
+
display: "inline-block",
|
|
51
|
+
}}
|
|
52
|
+
>
|
|
53
|
+
{this.props.child}
|
|
54
|
+
{this.props.children}
|
|
55
|
+
<div
|
|
56
|
+
class={`b ${this.props.colorStyle} ${this.props.class ?? ""}`}
|
|
57
|
+
style={{
|
|
58
|
+
position: "absolute",
|
|
59
|
+
top: "-0.25rem",
|
|
60
|
+
right: "-0.25rem",
|
|
61
|
+
minWidth: "1.5rem",
|
|
62
|
+
minHeight: "1.5rem",
|
|
63
|
+
padding: "0rem .4rem",
|
|
64
|
+
borderRadius: "3rem",
|
|
65
|
+
fontWeight: "bold",
|
|
66
|
+
display: "flex",
|
|
67
|
+
justifyContent: "center",
|
|
68
|
+
alignItems: "center",
|
|
69
|
+
visibility: this.props.hidden ? "hidden" : "visible",
|
|
70
|
+
...this.props.style,
|
|
71
|
+
}}
|
|
72
|
+
>
|
|
73
|
+
{this.props.message ?? this.props.count}
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { h } from "preact";
|
|
2
|
+
import type { ElbeColorModes, ElbeColorThemes } from "../color_theme";
|
|
3
|
+
import type { ElbeChildren } from "../util/util";
|
|
4
|
+
|
|
5
|
+
export type ElbeProps = {
|
|
6
|
+
class?: string;
|
|
7
|
+
style?: React.CSSProperties;
|
|
8
|
+
tooltip?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export function applyProps(
|
|
12
|
+
p: ElbeProps,
|
|
13
|
+
classes?: string | null | (string | false | null | undefined)[],
|
|
14
|
+
style?: React.CSSProperties
|
|
15
|
+
) {
|
|
16
|
+
if (Array.isArray(classes)) {
|
|
17
|
+
classes = classes.filter((c) => c).join(" ");
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
class: `${classes || ""} ${p.class || ""}`,
|
|
21
|
+
style: { ...(style ?? {}), ...(p.style ?? {}) },
|
|
22
|
+
...(p.tooltip ? { ["data-tooltip"]: p.tooltip } : {}),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function Box({
|
|
27
|
+
mode,
|
|
28
|
+
scheme = "primary",
|
|
29
|
+
padding = 0,
|
|
30
|
+
margin = 0,
|
|
31
|
+
children,
|
|
32
|
+
...elbe
|
|
33
|
+
}: {
|
|
34
|
+
mode?: ElbeColorModes;
|
|
35
|
+
scheme?: ElbeColorThemes;
|
|
36
|
+
padding?: number;
|
|
37
|
+
margin?: number;
|
|
38
|
+
children: ElbeChildren;
|
|
39
|
+
} & ElbeProps) {
|
|
40
|
+
return h(
|
|
41
|
+
"div",
|
|
42
|
+
applyProps(elbe, [scheme, mode], {
|
|
43
|
+
padding: `${padding}rem`,
|
|
44
|
+
margin: `${margin}rem`,
|
|
45
|
+
...elbe.style,
|
|
46
|
+
}),
|
|
47
|
+
children
|
|
48
|
+
);
|
|
49
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React from "preact/compat";
|
|
2
|
+
import type { ElbeColorManners, ElbeColorStyles } from "../color_theme";
|
|
3
|
+
import { _ElbeErr } from "../util/error_view";
|
|
4
|
+
import { applyProps, type ElbeProps } from "./box";
|
|
5
|
+
import type { IconChild } from "./icon_button";
|
|
6
|
+
|
|
7
|
+
export type ButtonProps = ElbeProps & {
|
|
8
|
+
colorStyle?: ElbeColorStyles;
|
|
9
|
+
onTap?: () => void;
|
|
10
|
+
} & (
|
|
11
|
+
| { icon?: IconChild; message: string }
|
|
12
|
+
| {
|
|
13
|
+
icon: IconChild;
|
|
14
|
+
message?: string;
|
|
15
|
+
}
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
export class Button extends React.Component<
|
|
19
|
+
ButtonProps & {
|
|
20
|
+
colorManner: ElbeColorManners;
|
|
21
|
+
}
|
|
22
|
+
> {
|
|
23
|
+
static major = (p: ButtonProps) => _btn(p, "major");
|
|
24
|
+
static minor = (p: ButtonProps) => _btn(p, "minor");
|
|
25
|
+
static action = (p: ButtonProps) => _btn(p, "action");
|
|
26
|
+
static integrated = (p: ButtonProps) => _btn(p, "integrated");
|
|
27
|
+
|
|
28
|
+
render() {
|
|
29
|
+
return _btn(this.props, this.props.colorManner);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function _btn(
|
|
34
|
+
{ colorStyle, onTap, icon, message, ...elbe }: ButtonProps,
|
|
35
|
+
colorManner: ElbeColorManners
|
|
36
|
+
) {
|
|
37
|
+
return message || icon ? (
|
|
38
|
+
<button
|
|
39
|
+
{...applyProps(
|
|
40
|
+
elbe,
|
|
41
|
+
[
|
|
42
|
+
"row",
|
|
43
|
+
"main-center",
|
|
44
|
+
"gap-half",
|
|
45
|
+
colorStyle ?? "accent",
|
|
46
|
+
colorManner,
|
|
47
|
+
!onTap && "disabled",
|
|
48
|
+
],
|
|
49
|
+
{
|
|
50
|
+
border: "none",
|
|
51
|
+
}
|
|
52
|
+
)}
|
|
53
|
+
onClick={() => onTap && onTap()}
|
|
54
|
+
>
|
|
55
|
+
{typeof icon === "function" ? icon({}) : icon}
|
|
56
|
+
{message && <span>{message}</span>}
|
|
57
|
+
</button>
|
|
58
|
+
) : (
|
|
59
|
+
_ElbeErr("Button requires either an icon or a message")
|
|
60
|
+
);
|
|
61
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ElbeColorManners,
|
|
3
|
+
ElbeColorModes,
|
|
4
|
+
ElbeColorStyles,
|
|
5
|
+
ElbeColorThemes,
|
|
6
|
+
} from "../color_theme";
|
|
7
|
+
import type { ElbeChildren } from "../util/util";
|
|
8
|
+
import { applyProps, type ElbeProps } from "./box";
|
|
9
|
+
|
|
10
|
+
export function Card({
|
|
11
|
+
mode,
|
|
12
|
+
colorScheme = "primary",
|
|
13
|
+
colorStyle,
|
|
14
|
+
colorManner,
|
|
15
|
+
padding = 1,
|
|
16
|
+
margin = 0,
|
|
17
|
+
onTap,
|
|
18
|
+
onLongTap,
|
|
19
|
+
children,
|
|
20
|
+
...elbe
|
|
21
|
+
}: {
|
|
22
|
+
mode?: ElbeColorModes;
|
|
23
|
+
colorScheme?: ElbeColorThemes;
|
|
24
|
+
colorStyle?: ElbeColorStyles;
|
|
25
|
+
colorManner?: ElbeColorManners;
|
|
26
|
+
padding?: number;
|
|
27
|
+
margin?: number;
|
|
28
|
+
onTap?: () => void;
|
|
29
|
+
onLongTap?: () => void;
|
|
30
|
+
children: ElbeChildren;
|
|
31
|
+
} & ElbeProps) {
|
|
32
|
+
return (
|
|
33
|
+
<div
|
|
34
|
+
{...applyProps(
|
|
35
|
+
elbe,
|
|
36
|
+
["card", colorScheme, colorStyle, colorManner, mode],
|
|
37
|
+
{ padding: `${padding}rem`, margin: `${margin}rem` }
|
|
38
|
+
)}
|
|
39
|
+
onClick={onTap}
|
|
40
|
+
onContextMenu={onLongTap}
|
|
41
|
+
>
|
|
42
|
+
{children}
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { X } from "lucide-react";
|
|
2
|
+
import type { ElbeChildren } from "../util/util";
|
|
3
|
+
import { Spaced } from "./util";
|
|
4
|
+
|
|
5
|
+
export function ElbeDialog({
|
|
6
|
+
title,
|
|
7
|
+
open,
|
|
8
|
+
onClose,
|
|
9
|
+
children,
|
|
10
|
+
_style,
|
|
11
|
+
}: {
|
|
12
|
+
_style?: string;
|
|
13
|
+
title: string;
|
|
14
|
+
open: boolean;
|
|
15
|
+
onClose: () => void;
|
|
16
|
+
children: ElbeChildren;
|
|
17
|
+
}) {
|
|
18
|
+
return (
|
|
19
|
+
<dialog
|
|
20
|
+
onClick={(e) => e.stopPropagation()}
|
|
21
|
+
open={open}
|
|
22
|
+
style={"text-align: start" + (_style ?? "")}
|
|
23
|
+
>
|
|
24
|
+
<div
|
|
25
|
+
class=" card plain-opaque padding-none"
|
|
26
|
+
style="max-width: 40rem; min-width: 10rem"
|
|
27
|
+
>
|
|
28
|
+
<div class="row cross-start padded">
|
|
29
|
+
<div class="flex-1 b" style="margin-top: 0.6rem; font-size: 1.2rem">
|
|
30
|
+
{title}
|
|
31
|
+
</div>
|
|
32
|
+
<button
|
|
33
|
+
class="integrated"
|
|
34
|
+
style="width: 3rem"
|
|
35
|
+
onClick={(e) => {
|
|
36
|
+
e.stopPropagation();
|
|
37
|
+
e.preventDefault();
|
|
38
|
+
onClose();
|
|
39
|
+
}}
|
|
40
|
+
>
|
|
41
|
+
<X />
|
|
42
|
+
</button>
|
|
43
|
+
</div>
|
|
44
|
+
<Spaced amount={0.5} />
|
|
45
|
+
<div class="padded" style="max-height: 80vh; overflow: auto">
|
|
46
|
+
{children}
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
</dialog>
|
|
50
|
+
);
|
|
51
|
+
}
|