@adecore/ui 0.54.11 → 0.54.13
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/EmptyScene.d.ts +7 -0
- package/dist/EmptyScene.js +96 -0
- package/dist/EmptyState.d.ts +2 -1
- package/dist/EmptyState.js +55 -39
- package/dist/PanelEmpty.d.ts +3 -1
- package/dist/PanelEmpty.js +17 -11
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/menu/parts.d.ts +1 -1
- package/dist/menu/parts.js +85 -38
- package/dist/theme.css +107 -0
- package/package.json +1 -1
- package/src/EmptyScene.tsx +30 -0
- package/src/EmptyState.tsx +7 -3
- package/src/PanelEmpty.tsx +7 -2
- package/src/index.ts +1 -0
- package/src/menu/parts.tsx +38 -4
- package/src/theme.css +107 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { c as _c } from "react/compiler-runtime";
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { useId } from 'react';
|
|
4
|
+
/* The drawing an `EmptyState` shows through `scene`. It only decorates, so it stays out of the accessibility tree. */
|
|
5
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
6
|
+
export function EmptyScene(t0) {
|
|
7
|
+
const $ = _c(14);
|
|
8
|
+
const {
|
|
9
|
+
compact: t1,
|
|
10
|
+
children,
|
|
11
|
+
className
|
|
12
|
+
} = t0;
|
|
13
|
+
const compact = t1 === undefined ? false : t1;
|
|
14
|
+
const gradient = useId();
|
|
15
|
+
const t2 = `url("#${gradient}")`;
|
|
16
|
+
let t3;
|
|
17
|
+
if ($[0] !== t2) {
|
|
18
|
+
t3 = {
|
|
19
|
+
"--scene-fill": t2
|
|
20
|
+
};
|
|
21
|
+
$[0] = t2;
|
|
22
|
+
$[1] = t3;
|
|
23
|
+
} else {
|
|
24
|
+
t3 = $[1];
|
|
25
|
+
}
|
|
26
|
+
const style = t3;
|
|
27
|
+
const t4 = compact && "scene-compact";
|
|
28
|
+
let t5;
|
|
29
|
+
if ($[2] !== className || $[3] !== t4) {
|
|
30
|
+
t5 = clsx("scene", t4, className);
|
|
31
|
+
$[2] = className;
|
|
32
|
+
$[3] = t4;
|
|
33
|
+
$[4] = t5;
|
|
34
|
+
} else {
|
|
35
|
+
t5 = $[4];
|
|
36
|
+
}
|
|
37
|
+
let t6;
|
|
38
|
+
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
|
|
39
|
+
t6 = /*#__PURE__*/_jsx("stop", {
|
|
40
|
+
offset: "0",
|
|
41
|
+
style: {
|
|
42
|
+
stopColor: "var(--scene-top)"
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
$[5] = t6;
|
|
46
|
+
} else {
|
|
47
|
+
t6 = $[5];
|
|
48
|
+
}
|
|
49
|
+
let t7;
|
|
50
|
+
if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
|
|
51
|
+
t7 = /*#__PURE__*/_jsx("stop", {
|
|
52
|
+
offset: "1",
|
|
53
|
+
style: {
|
|
54
|
+
stopColor: "var(--scene-bottom)"
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
$[6] = t7;
|
|
58
|
+
} else {
|
|
59
|
+
t7 = $[6];
|
|
60
|
+
}
|
|
61
|
+
let t8;
|
|
62
|
+
if ($[7] !== gradient) {
|
|
63
|
+
t8 = /*#__PURE__*/_jsx("defs", {
|
|
64
|
+
children: /*#__PURE__*/_jsxs("linearGradient", {
|
|
65
|
+
id: gradient,
|
|
66
|
+
x1: "0",
|
|
67
|
+
y1: "0",
|
|
68
|
+
x2: "0",
|
|
69
|
+
y2: "1",
|
|
70
|
+
children: [t6, t7]
|
|
71
|
+
})
|
|
72
|
+
});
|
|
73
|
+
$[7] = gradient;
|
|
74
|
+
$[8] = t8;
|
|
75
|
+
} else {
|
|
76
|
+
t8 = $[8];
|
|
77
|
+
}
|
|
78
|
+
let t9;
|
|
79
|
+
if ($[9] !== children || $[10] !== style || $[11] !== t5 || $[12] !== t8) {
|
|
80
|
+
t9 = /*#__PURE__*/_jsxs("svg", {
|
|
81
|
+
className: t5,
|
|
82
|
+
viewBox: "0 0 160 104",
|
|
83
|
+
style: style,
|
|
84
|
+
"aria-hidden": "true",
|
|
85
|
+
children: [t8, children]
|
|
86
|
+
});
|
|
87
|
+
$[9] = children;
|
|
88
|
+
$[10] = style;
|
|
89
|
+
$[11] = t5;
|
|
90
|
+
$[12] = t8;
|
|
91
|
+
$[13] = t9;
|
|
92
|
+
} else {
|
|
93
|
+
t9 = $[13];
|
|
94
|
+
}
|
|
95
|
+
return t9;
|
|
96
|
+
}
|
package/dist/EmptyState.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export interface EmptyStateProps {
|
|
|
4
4
|
icon?: LucideIcon | ReactElement<{
|
|
5
5
|
size?: number;
|
|
6
6
|
}>;
|
|
7
|
+
scene?: ReactNode;
|
|
7
8
|
busy?: boolean;
|
|
8
9
|
title?: ReactNode;
|
|
9
10
|
children: ReactNode;
|
|
@@ -11,4 +12,4 @@ export interface EmptyStateProps {
|
|
|
11
12
|
className?: string;
|
|
12
13
|
ref?: Ref<HTMLDivElement>;
|
|
13
14
|
}
|
|
14
|
-
export declare function EmptyState({ icon, busy, title, children, action, className, ref }: EmptyStateProps): import("react").JSX.Element;
|
|
15
|
+
export declare function EmptyState({ icon, scene, busy, title, children, action, className, ref }: EmptyStateProps): import("react").JSX.Element;
|
package/dist/EmptyState.js
CHANGED
|
@@ -7,9 +7,10 @@ import { Spinner } from "./Spinner.js";
|
|
|
7
7
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
8
|
const ICON_SIZE = 20;
|
|
9
9
|
export function EmptyState(t0) {
|
|
10
|
-
const $ = _c(
|
|
10
|
+
const $ = _c(24);
|
|
11
11
|
const {
|
|
12
12
|
icon,
|
|
13
|
+
scene,
|
|
13
14
|
busy: t1,
|
|
14
15
|
title,
|
|
15
16
|
children,
|
|
@@ -27,8 +28,20 @@ export function EmptyState(t0) {
|
|
|
27
28
|
t2 = $[1];
|
|
28
29
|
}
|
|
29
30
|
let t3;
|
|
30
|
-
if ($[2] !== busy || $[3] !==
|
|
31
|
-
t3 =
|
|
31
|
+
if ($[2] !== busy || $[3] !== scene) {
|
|
32
|
+
t3 = scene && !busy && /*#__PURE__*/_jsx("div", {
|
|
33
|
+
className: "mb-2",
|
|
34
|
+
children: scene
|
|
35
|
+
});
|
|
36
|
+
$[2] = busy;
|
|
37
|
+
$[3] = scene;
|
|
38
|
+
$[4] = t3;
|
|
39
|
+
} else {
|
|
40
|
+
t3 = $[4];
|
|
41
|
+
}
|
|
42
|
+
let t4;
|
|
43
|
+
if ($[5] !== busy || $[6] !== icon || $[7] !== scene) {
|
|
44
|
+
t4 = (busy || icon && !scene) && /*#__PURE__*/_jsx("span", {
|
|
32
45
|
className: "text-text-faint",
|
|
33
46
|
children: busy ? /*#__PURE__*/_jsx(Spinner, {
|
|
34
47
|
size: ICON_SIZE
|
|
@@ -39,61 +52,64 @@ export function EmptyState(t0) {
|
|
|
39
52
|
size: ICON_SIZE
|
|
40
53
|
})
|
|
41
54
|
});
|
|
42
|
-
$[
|
|
43
|
-
$[
|
|
44
|
-
$[
|
|
55
|
+
$[5] = busy;
|
|
56
|
+
$[6] = icon;
|
|
57
|
+
$[7] = scene;
|
|
58
|
+
$[8] = t4;
|
|
45
59
|
} else {
|
|
46
|
-
|
|
60
|
+
t4 = $[8];
|
|
47
61
|
}
|
|
48
|
-
let
|
|
49
|
-
if ($[
|
|
50
|
-
|
|
51
|
-
className: "text-
|
|
62
|
+
let t5;
|
|
63
|
+
if ($[9] !== scene || $[10] !== title) {
|
|
64
|
+
t5 = title && /*#__PURE__*/_jsx("p", {
|
|
65
|
+
className: clsx("text-text", scene ? "text-base font-semibold" : "text-sm font-medium"),
|
|
52
66
|
children: title
|
|
53
67
|
});
|
|
54
|
-
$[
|
|
55
|
-
$[
|
|
68
|
+
$[9] = scene;
|
|
69
|
+
$[10] = title;
|
|
70
|
+
$[11] = t5;
|
|
56
71
|
} else {
|
|
57
|
-
|
|
72
|
+
t5 = $[11];
|
|
58
73
|
}
|
|
59
|
-
let
|
|
60
|
-
if ($[
|
|
61
|
-
|
|
74
|
+
let t6;
|
|
75
|
+
if ($[12] !== children) {
|
|
76
|
+
t6 = /*#__PURE__*/_jsx("p", {
|
|
62
77
|
className: "max-w-[280px] text-xs leading-snug text-text-muted",
|
|
63
78
|
children: children
|
|
64
79
|
});
|
|
65
|
-
$[
|
|
66
|
-
$[
|
|
80
|
+
$[12] = children;
|
|
81
|
+
$[13] = t6;
|
|
67
82
|
} else {
|
|
68
|
-
|
|
83
|
+
t6 = $[13];
|
|
69
84
|
}
|
|
70
|
-
let
|
|
71
|
-
if ($[
|
|
72
|
-
|
|
85
|
+
let t7;
|
|
86
|
+
if ($[14] !== action) {
|
|
87
|
+
t7 = action && /*#__PURE__*/_jsx("div", {
|
|
73
88
|
className: "mt-2",
|
|
74
89
|
children: action
|
|
75
90
|
});
|
|
76
|
-
$[
|
|
77
|
-
$[
|
|
91
|
+
$[14] = action;
|
|
92
|
+
$[15] = t7;
|
|
78
93
|
} else {
|
|
79
|
-
|
|
94
|
+
t7 = $[15];
|
|
80
95
|
}
|
|
81
|
-
let
|
|
82
|
-
if ($[
|
|
83
|
-
|
|
96
|
+
let t8;
|
|
97
|
+
if ($[16] !== ref || $[17] !== t2 || $[18] !== t3 || $[19] !== t4 || $[20] !== t5 || $[21] !== t6 || $[22] !== t7) {
|
|
98
|
+
t8 = /*#__PURE__*/_jsxs("div", {
|
|
84
99
|
ref: ref,
|
|
85
100
|
className: t2,
|
|
86
|
-
children: [t3, t4, t5, t6]
|
|
101
|
+
children: [t3, t4, t5, t6, t7]
|
|
87
102
|
});
|
|
88
|
-
$[
|
|
89
|
-
$[
|
|
90
|
-
$[
|
|
91
|
-
$[
|
|
92
|
-
$[
|
|
93
|
-
$[
|
|
94
|
-
$[
|
|
103
|
+
$[16] = ref;
|
|
104
|
+
$[17] = t2;
|
|
105
|
+
$[18] = t3;
|
|
106
|
+
$[19] = t4;
|
|
107
|
+
$[20] = t5;
|
|
108
|
+
$[21] = t6;
|
|
109
|
+
$[22] = t7;
|
|
110
|
+
$[23] = t8;
|
|
95
111
|
} else {
|
|
96
|
-
|
|
112
|
+
t8 = $[23];
|
|
97
113
|
}
|
|
98
|
-
return
|
|
114
|
+
return t8;
|
|
99
115
|
}
|
package/dist/PanelEmpty.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ import type { ReactNode, Ref } from 'react';
|
|
|
3
3
|
export interface PanelEmptyProps {
|
|
4
4
|
header?: ReactNode;
|
|
5
5
|
icon?: LucideIcon;
|
|
6
|
+
scene?: ReactNode;
|
|
7
|
+
title?: ReactNode;
|
|
6
8
|
busy?: boolean;
|
|
7
9
|
action?: ReactNode;
|
|
8
10
|
sunken?: boolean;
|
|
@@ -11,4 +13,4 @@ export interface PanelEmptyProps {
|
|
|
11
13
|
className?: string;
|
|
12
14
|
ref?: Ref<HTMLDivElement>;
|
|
13
15
|
}
|
|
14
|
-
export declare function PanelEmpty({ header, icon, busy, action, sunken, fill, children, className, ref }: PanelEmptyProps): import("react").JSX.Element;
|
|
16
|
+
export declare function PanelEmpty({ header, icon, scene, title, busy, action, sunken, fill, children, className, ref }: PanelEmptyProps): import("react").JSX.Element;
|
package/dist/PanelEmpty.js
CHANGED
|
@@ -3,10 +3,12 @@ import clsx from 'clsx';
|
|
|
3
3
|
import { EmptyState } from "./EmptyState.js";
|
|
4
4
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
5
5
|
export function PanelEmpty(t0) {
|
|
6
|
-
const $ = _c(
|
|
6
|
+
const $ = _c(16);
|
|
7
7
|
const {
|
|
8
8
|
header,
|
|
9
9
|
icon,
|
|
10
|
+
scene,
|
|
11
|
+
title,
|
|
10
12
|
busy: t1,
|
|
11
13
|
action,
|
|
12
14
|
sunken: t2,
|
|
@@ -31,9 +33,11 @@ export function PanelEmpty(t0) {
|
|
|
31
33
|
t6 = $[3];
|
|
32
34
|
}
|
|
33
35
|
let t7;
|
|
34
|
-
if ($[4] !== action || $[5] !== busy || $[6] !== children || $[7] !== icon) {
|
|
36
|
+
if ($[4] !== action || $[5] !== busy || $[6] !== children || $[7] !== icon || $[8] !== scene || $[9] !== title) {
|
|
35
37
|
t7 = /*#__PURE__*/_jsx(EmptyState, {
|
|
36
38
|
icon: icon,
|
|
39
|
+
scene: scene,
|
|
40
|
+
title: title,
|
|
37
41
|
busy: busy,
|
|
38
42
|
action: action,
|
|
39
43
|
children: children
|
|
@@ -42,24 +46,26 @@ export function PanelEmpty(t0) {
|
|
|
42
46
|
$[5] = busy;
|
|
43
47
|
$[6] = children;
|
|
44
48
|
$[7] = icon;
|
|
45
|
-
$[8] =
|
|
49
|
+
$[8] = scene;
|
|
50
|
+
$[9] = title;
|
|
51
|
+
$[10] = t7;
|
|
46
52
|
} else {
|
|
47
|
-
t7 = $[
|
|
53
|
+
t7 = $[10];
|
|
48
54
|
}
|
|
49
55
|
let t8;
|
|
50
|
-
if ($[
|
|
56
|
+
if ($[11] !== header || $[12] !== ref || $[13] !== t6 || $[14] !== t7) {
|
|
51
57
|
t8 = /*#__PURE__*/_jsxs("div", {
|
|
52
58
|
ref: ref,
|
|
53
59
|
className: t6,
|
|
54
60
|
children: [header, t7]
|
|
55
61
|
});
|
|
56
|
-
$[
|
|
57
|
-
$[
|
|
58
|
-
$[
|
|
59
|
-
$[
|
|
60
|
-
$[
|
|
62
|
+
$[11] = header;
|
|
63
|
+
$[12] = ref;
|
|
64
|
+
$[13] = t6;
|
|
65
|
+
$[14] = t7;
|
|
66
|
+
$[15] = t8;
|
|
61
67
|
} else {
|
|
62
|
-
t8 = $[
|
|
68
|
+
t8 = $[15];
|
|
63
69
|
}
|
|
64
70
|
return t8;
|
|
65
71
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ export { ColorWheelPicker, type ColorWheelPickerProps } from './ColorWheelPicker
|
|
|
30
30
|
export { ColumnResizeHandle, type ColumnResizeHandleProps } from './ColumnResizeHandle.tsx';
|
|
31
31
|
export { DisabledReason, type DisabledReasonProps } from './DisabledReason.tsx';
|
|
32
32
|
export { DockShell, type DockShellProps } from './DockShell.tsx';
|
|
33
|
+
export { EmptyScene, type EmptySceneProps } from './EmptyScene.tsx';
|
|
33
34
|
export { EmptyState, type EmptyStateProps } from './EmptyState.tsx';
|
|
34
35
|
export { ErrorBoundary, type ErrorBoundaryProps } from './ErrorBoundary.tsx';
|
|
35
36
|
export { Field, FieldHint, FormError, type FieldHintProps, type FieldProps, type FormErrorProps } from './Field.tsx';
|
package/dist/index.js
CHANGED
|
@@ -27,6 +27,7 @@ export { ColorWheelPicker } from "./ColorWheelPicker.js";
|
|
|
27
27
|
export { ColumnResizeHandle } from "./ColumnResizeHandle.js";
|
|
28
28
|
export { DisabledReason } from "./DisabledReason.js";
|
|
29
29
|
export { DockShell } from "./DockShell.js";
|
|
30
|
+
export { EmptyScene } from "./EmptyScene.js";
|
|
30
31
|
export { EmptyState } from "./EmptyState.js";
|
|
31
32
|
export { ErrorBoundary } from "./ErrorBoundary.js";
|
|
32
33
|
export { Field, FieldHint, FormError } from "./Field.js";
|
package/dist/menu/parts.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ type ItemLook = {
|
|
|
19
19
|
unstyled?: boolean;
|
|
20
20
|
};
|
|
21
21
|
type MenuItemProps = ComponentProps<typeof BaseMenu.Item> & ItemLook;
|
|
22
|
-
export declare function MenuItem({ unstyled, className, ...props }: MenuItemProps): import("react").JSX.Element;
|
|
22
|
+
export declare function MenuItem({ unstyled, className, children, ...props }: MenuItemProps): import("react").JSX.Element;
|
|
23
23
|
export interface MenuCheckProps {
|
|
24
24
|
kind: 'radio' | 'checkbox';
|
|
25
25
|
checked?: boolean;
|
package/dist/menu/parts.js
CHANGED
|
@@ -159,8 +159,33 @@ export function MenuPopup(t0) {
|
|
|
159
159
|
}
|
|
160
160
|
return t8;
|
|
161
161
|
}
|
|
162
|
+
/*
|
|
163
|
+
* Typing in an open menu moves to the first row whose text starts with the letters, read from the
|
|
164
|
+
* row's `label` or else its rendered text. The space JSX keeps between an icon and the name
|
|
165
|
+
* (`<Icon /> {name}`) draws nothing in a row laid out with a gap, but it would start that text and
|
|
166
|
+
* keep the row from ever matching. A row whose text starts with something other than its name,
|
|
167
|
+
* such as initials before it, sets `label`.
|
|
168
|
+
*/
|
|
169
|
+
function withoutLeadingSpace(children) {
|
|
170
|
+
if (typeof children === 'string') {
|
|
171
|
+
return children.trimStart();
|
|
172
|
+
}
|
|
173
|
+
if (!Array.isArray(children)) {
|
|
174
|
+
return children;
|
|
175
|
+
}
|
|
176
|
+
let reached = false;
|
|
177
|
+
return children.map(child => {
|
|
178
|
+
if (reached || typeof child !== 'string') {
|
|
179
|
+
return child;
|
|
180
|
+
}
|
|
181
|
+
const trimmed = child.trimStart();
|
|
182
|
+
reached = trimmed !== '';
|
|
183
|
+
return trimmed;
|
|
184
|
+
});
|
|
185
|
+
}
|
|
162
186
|
export function MenuItem(t0) {
|
|
163
|
-
const $ = _c(
|
|
187
|
+
const $ = _c(15);
|
|
188
|
+
let children;
|
|
164
189
|
let className;
|
|
165
190
|
let props;
|
|
166
191
|
let t1;
|
|
@@ -168,40 +193,54 @@ export function MenuItem(t0) {
|
|
|
168
193
|
({
|
|
169
194
|
unstyled: t1,
|
|
170
195
|
className,
|
|
196
|
+
children,
|
|
171
197
|
...props
|
|
172
198
|
} = t0);
|
|
173
199
|
$[0] = t0;
|
|
174
|
-
$[1] =
|
|
175
|
-
$[2] =
|
|
176
|
-
$[3] =
|
|
200
|
+
$[1] = children;
|
|
201
|
+
$[2] = className;
|
|
202
|
+
$[3] = props;
|
|
203
|
+
$[4] = t1;
|
|
177
204
|
} else {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
205
|
+
children = $[1];
|
|
206
|
+
className = $[2];
|
|
207
|
+
props = $[3];
|
|
208
|
+
t1 = $[4];
|
|
181
209
|
}
|
|
182
210
|
const unstyled = t1 === undefined ? false : t1;
|
|
183
211
|
let t2;
|
|
184
|
-
if ($[
|
|
212
|
+
if ($[5] !== className || $[6] !== unstyled) {
|
|
185
213
|
t2 = unstyled ? className : withClass("menu-item", className);
|
|
186
|
-
$[
|
|
187
|
-
$[
|
|
188
|
-
$[
|
|
214
|
+
$[5] = className;
|
|
215
|
+
$[6] = unstyled;
|
|
216
|
+
$[7] = t2;
|
|
189
217
|
} else {
|
|
190
|
-
t2 = $[
|
|
218
|
+
t2 = $[7];
|
|
191
219
|
}
|
|
192
220
|
let t3;
|
|
193
|
-
if ($[
|
|
194
|
-
t3 =
|
|
221
|
+
if ($[8] !== children || $[9] !== unstyled) {
|
|
222
|
+
t3 = unstyled ? children : withoutLeadingSpace(children);
|
|
223
|
+
$[8] = children;
|
|
224
|
+
$[9] = unstyled;
|
|
225
|
+
$[10] = t3;
|
|
226
|
+
} else {
|
|
227
|
+
t3 = $[10];
|
|
228
|
+
}
|
|
229
|
+
let t4;
|
|
230
|
+
if ($[11] !== props || $[12] !== t2 || $[13] !== t3) {
|
|
231
|
+
t4 = /*#__PURE__*/_jsx(BaseMenu.Item, {
|
|
195
232
|
className: t2,
|
|
196
|
-
...props
|
|
233
|
+
...props,
|
|
234
|
+
children: t3
|
|
197
235
|
});
|
|
198
|
-
$[
|
|
199
|
-
$[
|
|
200
|
-
$[
|
|
236
|
+
$[11] = props;
|
|
237
|
+
$[12] = t2;
|
|
238
|
+
$[13] = t3;
|
|
239
|
+
$[14] = t4;
|
|
201
240
|
} else {
|
|
202
|
-
|
|
241
|
+
t4 = $[14];
|
|
203
242
|
}
|
|
204
|
-
return
|
|
243
|
+
return t4;
|
|
205
244
|
}
|
|
206
245
|
/* One line of the row tall, so a row with a second line keeps the tick beside its first. */
|
|
207
246
|
export function MenuCheck(t0) {
|
|
@@ -281,7 +320,7 @@ export function MenuCheck(t0) {
|
|
|
281
320
|
const checkRow = (kind, unstyled, indicator, children) => unstyled ? children : /*#__PURE__*/_jsxs(_Fragment, {
|
|
282
321
|
children: [indicator === 'start' && /*#__PURE__*/_jsx(MenuCheck, {
|
|
283
322
|
kind: kind
|
|
284
|
-
}), children, indicator === 'end' && /*#__PURE__*/_jsx(MenuCheck, {
|
|
323
|
+
}), withoutLeadingSpace(children), indicator === 'end' && /*#__PURE__*/_jsx(MenuCheck, {
|
|
285
324
|
kind: kind,
|
|
286
325
|
className: "ml-auto"
|
|
287
326
|
})]
|
|
@@ -418,7 +457,7 @@ export function MenuRadioItem(t0) {
|
|
|
418
457
|
return t5;
|
|
419
458
|
}
|
|
420
459
|
export function MenuSubmenuTrigger(t0) {
|
|
421
|
-
const $ = _c(
|
|
460
|
+
const $ = _c(16);
|
|
422
461
|
let children;
|
|
423
462
|
let className;
|
|
424
463
|
let props;
|
|
@@ -451,33 +490,41 @@ export function MenuSubmenuTrigger(t0) {
|
|
|
451
490
|
t2 = $[6];
|
|
452
491
|
}
|
|
453
492
|
let t3;
|
|
454
|
-
if ($[7] !==
|
|
455
|
-
t3 =
|
|
493
|
+
if ($[7] !== children) {
|
|
494
|
+
t3 = withoutLeadingSpace(children);
|
|
495
|
+
$[7] = children;
|
|
496
|
+
$[8] = t3;
|
|
497
|
+
} else {
|
|
498
|
+
t3 = $[8];
|
|
499
|
+
}
|
|
500
|
+
let t4;
|
|
501
|
+
if ($[9] !== chevron) {
|
|
502
|
+
t4 = chevron && /*#__PURE__*/_jsx(Icon, {
|
|
456
503
|
icon: ChevronRight,
|
|
457
504
|
size: 14,
|
|
458
505
|
className: "ml-auto text-text-faint"
|
|
459
506
|
});
|
|
460
|
-
$[
|
|
461
|
-
$[
|
|
507
|
+
$[9] = chevron;
|
|
508
|
+
$[10] = t4;
|
|
462
509
|
} else {
|
|
463
|
-
|
|
510
|
+
t4 = $[10];
|
|
464
511
|
}
|
|
465
|
-
let
|
|
466
|
-
if ($[
|
|
467
|
-
|
|
512
|
+
let t5;
|
|
513
|
+
if ($[11] !== props || $[12] !== t2 || $[13] !== t3 || $[14] !== t4) {
|
|
514
|
+
t5 = /*#__PURE__*/_jsxs(BaseMenu.SubmenuTrigger, {
|
|
468
515
|
className: t2,
|
|
469
516
|
...props,
|
|
470
|
-
children: [
|
|
517
|
+
children: [t3, t4]
|
|
471
518
|
});
|
|
472
|
-
$[
|
|
473
|
-
$[
|
|
474
|
-
$[
|
|
475
|
-
$[
|
|
476
|
-
$[
|
|
519
|
+
$[11] = props;
|
|
520
|
+
$[12] = t2;
|
|
521
|
+
$[13] = t3;
|
|
522
|
+
$[14] = t4;
|
|
523
|
+
$[15] = t5;
|
|
477
524
|
} else {
|
|
478
|
-
|
|
525
|
+
t5 = $[15];
|
|
479
526
|
}
|
|
480
|
-
return
|
|
527
|
+
return t5;
|
|
481
528
|
}
|
|
482
529
|
/* Its first item is the row, every `RowAction` and `RowSubmenuTrigger` after it an item of its own, so the arrow keys reach each. */
|
|
483
530
|
export function MenuRow(t0) {
|
package/dist/theme.css
CHANGED
|
@@ -115,6 +115,16 @@
|
|
|
115
115
|
--file-icon-purple: #a631be;
|
|
116
116
|
--file-icon-pink: #d32a61;
|
|
117
117
|
--file-icon-mauve: #594c5b;
|
|
118
|
+
/* `EmptyScene`: what a drawing of an empty place is made of. */
|
|
119
|
+
--scene-top: #ffffff;
|
|
120
|
+
--scene-bottom: #ececf1;
|
|
121
|
+
--scene-rim: rgb(0 0 0 / 0.09);
|
|
122
|
+
--scene-line: rgb(0 0 0 / 0.12);
|
|
123
|
+
--scene-inset: rgb(0 0 0 / 0.06);
|
|
124
|
+
--scene-text: rgb(0 0 0 / 0.14);
|
|
125
|
+
--scene-lift: drop-shadow(0 1px 1px rgb(0 0 0 / 0.08)) drop-shadow(0 5px 10px rgb(0 0 0 / 0.08));
|
|
126
|
+
/* What lands in a scene overshoots a little and settles. */
|
|
127
|
+
--scene-arrive: cubic-bezier(0.34, 1.5, 0.55, 1);
|
|
118
128
|
}
|
|
119
129
|
|
|
120
130
|
/* The theme attribute sits on `<html>`, the element the light rule above lands on too, so a token
|
|
@@ -191,6 +201,13 @@
|
|
|
191
201
|
--file-icon-purple: #d568ea;
|
|
192
202
|
--file-icon-pink: #ff678d;
|
|
193
203
|
--file-icon-mauve: #79697b;
|
|
204
|
+
--scene-top: #2c2c32;
|
|
205
|
+
--scene-bottom: #1a1a1f;
|
|
206
|
+
--scene-rim: rgb(255 255 255 / 0.08);
|
|
207
|
+
--scene-line: rgb(255 255 255 / 0.1);
|
|
208
|
+
--scene-inset: rgb(0 0 0 / 0.3);
|
|
209
|
+
--scene-text: rgb(255 255 255 / 0.16);
|
|
210
|
+
--scene-lift: drop-shadow(0 1px 0 rgb(0 0 0 / 0.4)) drop-shadow(0 6px 10px rgb(0 0 0 / 0.35));
|
|
194
211
|
}
|
|
195
212
|
|
|
196
213
|
/* Code a person reads as code (an editor, a grid of values, a statement) at one size the app may set on
|
|
@@ -1178,3 +1195,93 @@
|
|
|
1178
1195
|
.ade-scrollbar, .ade-scrollbar::before, .ade-scrollbar-thumb::before { transition: none; }
|
|
1179
1196
|
}
|
|
1180
1197
|
}
|
|
1198
|
+
|
|
1199
|
+
/* The drawing of an empty place (`EmptyScene`): shapes in a soft gradient with a thin rim and one detail
|
|
1200
|
+
in the accent color, on the same 8 second loop. Each rule below only animates: at rest, and under
|
|
1201
|
+
reduced motion, a drawing shows the end of what it plays. */
|
|
1202
|
+
.scene { flex: none; width: 160px; height: 104px; overflow: visible; }
|
|
1203
|
+
.scene-compact { width: 136px; height: 88px; }
|
|
1204
|
+
.scene-shape { fill: var(--scene-fill); stroke: var(--scene-rim); stroke-width: 1; stroke-linejoin: round; }
|
|
1205
|
+
.scene-edge { fill: none; stroke: var(--scene-line); stroke-width: 1.25; stroke-linecap: round; stroke-linejoin: round; }
|
|
1206
|
+
.scene-inset { fill: var(--scene-inset); }
|
|
1207
|
+
.scene-line { fill: none; stroke: var(--text-faint); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
|
|
1208
|
+
.scene-text { fill: none; stroke: var(--scene-text); stroke-width: 4px; stroke-linecap: round; }
|
|
1209
|
+
.scene-hand { fill: none; stroke: var(--text-muted); stroke-width: 2.5; stroke-linecap: round; }
|
|
1210
|
+
.scene-dot { fill: var(--text-faint); }
|
|
1211
|
+
.scene-accent { fill: var(--accent); }
|
|
1212
|
+
.scene-accent-line { fill: none; stroke: var(--accent); stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
|
|
1213
|
+
.scene-lift { filter: var(--scene-lift); }
|
|
1214
|
+
.scene-cursor { fill: var(--text); stroke: var(--surface); stroke-width: 1; stroke-linejoin: round; }
|
|
1215
|
+
.scene [class*="scene-reveal-"] { transform-box: fill-box; transform-origin: center; }
|
|
1216
|
+
.scene [class*="scene-stroke-"], .scene [class*="scene-type-"] { stroke-dasharray: 1; }
|
|
1217
|
+
|
|
1218
|
+
@keyframes scene-loop { 0% { opacity: 0; } 3%, 88% { opacity: 1; } 95%, 100% { opacity: 0; } }
|
|
1219
|
+
@keyframes scene-reveal-0 { 0%, 3% { opacity: 0; transform: translateY(5px) scale(0.94); } 9%, 100% { opacity: 1; transform: none; } }
|
|
1220
|
+
@keyframes scene-stroke-0 { 0%, 3% { stroke-dashoffset: 1; } 10%, 100% { stroke-dashoffset: 0; } }
|
|
1221
|
+
@keyframes scene-reveal-1 { 0%, 9% { opacity: 0; transform: translateY(5px) scale(0.94); } 15%, 100% { opacity: 1; transform: none; } }
|
|
1222
|
+
@keyframes scene-stroke-1 { 0%, 9% { stroke-dashoffset: 1; } 16%, 100% { stroke-dashoffset: 0; } }
|
|
1223
|
+
@keyframes scene-reveal-2 { 0%, 15% { opacity: 0; transform: translateY(5px) scale(0.94); } 21%, 100% { opacity: 1; transform: none; } }
|
|
1224
|
+
@keyframes scene-stroke-2 { 0%, 15% { stroke-dashoffset: 1; } 22%, 100% { stroke-dashoffset: 0; } }
|
|
1225
|
+
@keyframes scene-reveal-3 { 0%, 21% { opacity: 0; transform: translateY(5px) scale(0.94); } 27%, 100% { opacity: 1; transform: none; } }
|
|
1226
|
+
@keyframes scene-stroke-3 { 0%, 21% { stroke-dashoffset: 1; } 28%, 100% { stroke-dashoffset: 0; } }
|
|
1227
|
+
@keyframes scene-reveal-4 { 0%, 27% { opacity: 0; transform: translateY(5px) scale(0.94); } 33%, 100% { opacity: 1; transform: none; } }
|
|
1228
|
+
@keyframes scene-stroke-4 { 0%, 27% { stroke-dashoffset: 1; } 34%, 100% { stroke-dashoffset: 0; } }
|
|
1229
|
+
@keyframes scene-reveal-5 { 0%, 33% { opacity: 0; transform: translateY(5px) scale(0.94); } 39%, 100% { opacity: 1; transform: none; } }
|
|
1230
|
+
@keyframes scene-stroke-5 { 0%, 33% { stroke-dashoffset: 1; } 40%, 100% { stroke-dashoffset: 0; } }
|
|
1231
|
+
@keyframes scene-reveal-6 { 0%, 39% { opacity: 0; transform: translateY(5px) scale(0.94); } 45%, 100% { opacity: 1; transform: none; } }
|
|
1232
|
+
@keyframes scene-stroke-6 { 0%, 39% { stroke-dashoffset: 1; } 46%, 100% { stroke-dashoffset: 0; } }
|
|
1233
|
+
@keyframes scene-reveal-7 { 0%, 45% { opacity: 0; transform: translateY(5px) scale(0.94); } 51%, 100% { opacity: 1; transform: none; } }
|
|
1234
|
+
@keyframes scene-stroke-7 { 0%, 45% { stroke-dashoffset: 1; } 52%, 100% { stroke-dashoffset: 0; } }
|
|
1235
|
+
@keyframes scene-reveal-8 { 0%, 51% { opacity: 0; transform: translateY(5px) scale(0.94); } 57%, 100% { opacity: 1; transform: none; } }
|
|
1236
|
+
@keyframes scene-stroke-8 { 0%, 51% { stroke-dashoffset: 1; } 58%, 100% { stroke-dashoffset: 0; } }
|
|
1237
|
+
@keyframes scene-reveal-9 { 0%, 57% { opacity: 0; transform: translateY(5px) scale(0.94); } 63%, 100% { opacity: 1; transform: none; } }
|
|
1238
|
+
@keyframes scene-stroke-9 { 0%, 57% { stroke-dashoffset: 1; } 64%, 100% { stroke-dashoffset: 0; } }
|
|
1239
|
+
@keyframes scene-reveal-10 { 0%, 63% { opacity: 0; transform: translateY(5px) scale(0.94); } 69%, 100% { opacity: 1; transform: none; } }
|
|
1240
|
+
@keyframes scene-stroke-10 { 0%, 63% { stroke-dashoffset: 1; } 70%, 100% { stroke-dashoffset: 0; } }
|
|
1241
|
+
@keyframes scene-reveal-11 { 0%, 69% { opacity: 0; transform: translateY(5px) scale(0.94); } 75%, 100% { opacity: 1; transform: none; } }
|
|
1242
|
+
@keyframes scene-stroke-11 { 0%, 69% { stroke-dashoffset: 1; } 76%, 100% { stroke-dashoffset: 0; } }
|
|
1243
|
+
@keyframes scene-reveal-12 { 0%, 75% { opacity: 0; transform: translateY(5px) scale(0.94); } 81%, 100% { opacity: 1; transform: none; } }
|
|
1244
|
+
@keyframes scene-stroke-12 { 0%, 75% { stroke-dashoffset: 1; } 82%, 100% { stroke-dashoffset: 0; } }
|
|
1245
|
+
|
|
1246
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
1247
|
+
.scene-loop { animation: scene-loop 8s linear infinite; }
|
|
1248
|
+
.scene-reveal-0 { animation: scene-reveal-0 8s var(--scene-arrive) infinite; }
|
|
1249
|
+
.scene-stroke-0 { animation: scene-stroke-0 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1250
|
+
.scene-type-0 { animation: scene-stroke-0 8s steps(5, jump-none) infinite; }
|
|
1251
|
+
.scene-reveal-1 { animation: scene-reveal-1 8s var(--scene-arrive) infinite; }
|
|
1252
|
+
.scene-stroke-1 { animation: scene-stroke-1 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1253
|
+
.scene-type-1 { animation: scene-stroke-1 8s steps(5, jump-none) infinite; }
|
|
1254
|
+
.scene-reveal-2 { animation: scene-reveal-2 8s var(--scene-arrive) infinite; }
|
|
1255
|
+
.scene-stroke-2 { animation: scene-stroke-2 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1256
|
+
.scene-type-2 { animation: scene-stroke-2 8s steps(5, jump-none) infinite; }
|
|
1257
|
+
.scene-reveal-3 { animation: scene-reveal-3 8s var(--scene-arrive) infinite; }
|
|
1258
|
+
.scene-stroke-3 { animation: scene-stroke-3 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1259
|
+
.scene-type-3 { animation: scene-stroke-3 8s steps(5, jump-none) infinite; }
|
|
1260
|
+
.scene-reveal-4 { animation: scene-reveal-4 8s var(--scene-arrive) infinite; }
|
|
1261
|
+
.scene-stroke-4 { animation: scene-stroke-4 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1262
|
+
.scene-type-4 { animation: scene-stroke-4 8s steps(5, jump-none) infinite; }
|
|
1263
|
+
.scene-reveal-5 { animation: scene-reveal-5 8s var(--scene-arrive) infinite; }
|
|
1264
|
+
.scene-stroke-5 { animation: scene-stroke-5 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1265
|
+
.scene-type-5 { animation: scene-stroke-5 8s steps(5, jump-none) infinite; }
|
|
1266
|
+
.scene-reveal-6 { animation: scene-reveal-6 8s var(--scene-arrive) infinite; }
|
|
1267
|
+
.scene-stroke-6 { animation: scene-stroke-6 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1268
|
+
.scene-type-6 { animation: scene-stroke-6 8s steps(5, jump-none) infinite; }
|
|
1269
|
+
.scene-reveal-7 { animation: scene-reveal-7 8s var(--scene-arrive) infinite; }
|
|
1270
|
+
.scene-stroke-7 { animation: scene-stroke-7 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1271
|
+
.scene-type-7 { animation: scene-stroke-7 8s steps(5, jump-none) infinite; }
|
|
1272
|
+
.scene-reveal-8 { animation: scene-reveal-8 8s var(--scene-arrive) infinite; }
|
|
1273
|
+
.scene-stroke-8 { animation: scene-stroke-8 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1274
|
+
.scene-type-8 { animation: scene-stroke-8 8s steps(5, jump-none) infinite; }
|
|
1275
|
+
.scene-reveal-9 { animation: scene-reveal-9 8s var(--scene-arrive) infinite; }
|
|
1276
|
+
.scene-stroke-9 { animation: scene-stroke-9 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1277
|
+
.scene-type-9 { animation: scene-stroke-9 8s steps(5, jump-none) infinite; }
|
|
1278
|
+
.scene-reveal-10 { animation: scene-reveal-10 8s var(--scene-arrive) infinite; }
|
|
1279
|
+
.scene-stroke-10 { animation: scene-stroke-10 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1280
|
+
.scene-type-10 { animation: scene-stroke-10 8s steps(5, jump-none) infinite; }
|
|
1281
|
+
.scene-reveal-11 { animation: scene-reveal-11 8s var(--scene-arrive) infinite; }
|
|
1282
|
+
.scene-stroke-11 { animation: scene-stroke-11 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1283
|
+
.scene-type-11 { animation: scene-stroke-11 8s steps(5, jump-none) infinite; }
|
|
1284
|
+
.scene-reveal-12 { animation: scene-reveal-12 8s var(--scene-arrive) infinite; }
|
|
1285
|
+
.scene-stroke-12 { animation: scene-stroke-12 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1286
|
+
.scene-type-12 { animation: scene-stroke-12 8s steps(5, jump-none) infinite; }
|
|
1287
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adecore/ui",
|
|
3
|
-
"version": "0.54.
|
|
3
|
+
"version": "0.54.13",
|
|
4
4
|
"description": "React components, a theme, formatters and a settings dialog for desktop-grade apps on React 19, Base UI and Tailwind 4.",
|
|
5
5
|
"license": "FSL-1.1-MIT",
|
|
6
6
|
"author": "Bas Milius",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import { useId, type CSSProperties, type ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
export interface EmptySceneProps {
|
|
5
|
+
/* For a panel: 136 by 88 pixels instead of 160 by 104. */
|
|
6
|
+
compact?: boolean;
|
|
7
|
+
|
|
8
|
+
/* SVG in a 160 by 104 view box, drawn with the `scene-*` classes of the theme. */
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* The drawing an `EmptyState` shows through `scene`. It only decorates, so it stays out of the accessibility tree. */
|
|
15
|
+
export function EmptyScene({ compact = false, children, className }: EmptySceneProps) {
|
|
16
|
+
const gradient = useId();
|
|
17
|
+
const style = { '--scene-fill': `url("#${gradient}")` } as CSSProperties;
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<svg className={clsx('scene', compact && 'scene-compact', className)} viewBox="0 0 160 104" style={style} aria-hidden="true">
|
|
21
|
+
<defs>
|
|
22
|
+
<linearGradient id={gradient} x1="0" y1="0" x2="0" y2="1">
|
|
23
|
+
<stop offset="0" style={{ stopColor: 'var(--scene-top)' }} />
|
|
24
|
+
<stop offset="1" style={{ stopColor: 'var(--scene-bottom)' }} />
|
|
25
|
+
</linearGradient>
|
|
26
|
+
</defs>
|
|
27
|
+
{children}
|
|
28
|
+
</svg>
|
|
29
|
+
);
|
|
30
|
+
}
|
package/src/EmptyState.tsx
CHANGED
|
@@ -11,6 +11,9 @@ export interface EmptyStateProps {
|
|
|
11
11
|
/* A Lucide icon, or a mark of another kind that takes a `size`. */
|
|
12
12
|
icon?: LucideIcon | ReactElement<{ size?: number }>;
|
|
13
13
|
|
|
14
|
+
/* A drawing in place of the icon, usually an `EmptyScene`, for a place a person may not know yet. */
|
|
15
|
+
scene?: ReactNode;
|
|
16
|
+
|
|
14
17
|
/* A `Spinner` in place of the icon. */
|
|
15
18
|
busy?: boolean;
|
|
16
19
|
|
|
@@ -27,10 +30,11 @@ export interface EmptyStateProps {
|
|
|
27
30
|
ref?: Ref<HTMLDivElement>;
|
|
28
31
|
}
|
|
29
32
|
|
|
30
|
-
export function EmptyState({ icon, busy = false, title, children, action, className, ref }: EmptyStateProps) {
|
|
33
|
+
export function EmptyState({ icon, scene, busy = false, title, children, action, className, ref }: EmptyStateProps) {
|
|
31
34
|
return (
|
|
32
35
|
<div ref={ref} className={clsx('flex flex-col items-center justify-center gap-2 px-6 py-8 text-center', className)}>
|
|
33
|
-
{
|
|
36
|
+
{scene && !busy && <div className="mb-2">{scene}</div>}
|
|
37
|
+
{(busy || (icon && !scene)) && (
|
|
34
38
|
<span className="text-text-faint">
|
|
35
39
|
{busy ? (
|
|
36
40
|
<Spinner size={ICON_SIZE} />
|
|
@@ -41,7 +45,7 @@ export function EmptyState({ icon, busy = false, title, children, action, classN
|
|
|
41
45
|
)}
|
|
42
46
|
</span>
|
|
43
47
|
)}
|
|
44
|
-
{title && <p className=
|
|
48
|
+
{title && <p className={clsx('text-text', scene ? 'text-base font-semibold' : 'text-sm font-medium')}>{title}</p>}
|
|
45
49
|
<p className="max-w-[280px] text-xs leading-snug text-text-muted">{children}</p>
|
|
46
50
|
{/* The button is an answer to the sentence, not a third line of it. */}
|
|
47
51
|
{action && <div className="mt-2">{action}</div>}
|
package/src/PanelEmpty.tsx
CHANGED
|
@@ -9,6 +9,11 @@ export interface PanelEmptyProps {
|
|
|
9
9
|
|
|
10
10
|
icon?: LucideIcon;
|
|
11
11
|
|
|
12
|
+
/* A drawing in place of the icon, usually a compact `EmptyScene`. */
|
|
13
|
+
scene?: ReactNode;
|
|
14
|
+
|
|
15
|
+
title?: ReactNode;
|
|
16
|
+
|
|
12
17
|
/* A `Spinner` in place of the icon. */
|
|
13
18
|
busy?: boolean;
|
|
14
19
|
|
|
@@ -25,11 +30,11 @@ export interface PanelEmptyProps {
|
|
|
25
30
|
ref?: Ref<HTMLDivElement>;
|
|
26
31
|
}
|
|
27
32
|
|
|
28
|
-
export function PanelEmpty({ header, icon, busy = false, action, sunken = false, fill = 'grow', children, className, ref }: PanelEmptyProps) {
|
|
33
|
+
export function PanelEmpty({ header, icon, scene, title, busy = false, action, sunken = false, fill = 'grow', children, className, ref }: PanelEmptyProps) {
|
|
29
34
|
return (
|
|
30
35
|
<div ref={ref} className={clsx('grid min-h-0 place-items-center', fill === 'full' ? 'h-full' : 'grow', sunken && 'bg-surface-sunken', className)}>
|
|
31
36
|
{header}
|
|
32
|
-
<EmptyState icon={icon} busy={busy} action={action}>
|
|
37
|
+
<EmptyState icon={icon} scene={scene} title={title} busy={busy} action={action}>
|
|
33
38
|
{children}
|
|
34
39
|
</EmptyState>
|
|
35
40
|
</div>
|
package/src/index.ts
CHANGED
|
@@ -48,6 +48,7 @@ export { ColorWheelPicker, type ColorWheelPickerProps } from './ColorWheelPicker
|
|
|
48
48
|
export { ColumnResizeHandle, type ColumnResizeHandleProps } from './ColumnResizeHandle.tsx';
|
|
49
49
|
export { DisabledReason, type DisabledReasonProps } from './DisabledReason.tsx';
|
|
50
50
|
export { DockShell, type DockShellProps } from './DockShell.tsx';
|
|
51
|
+
export { EmptyScene, type EmptySceneProps } from './EmptyScene.tsx';
|
|
51
52
|
export { EmptyState, type EmptyStateProps } from './EmptyState.tsx';
|
|
52
53
|
export { ErrorBoundary, type ErrorBoundaryProps } from './ErrorBoundary.tsx';
|
|
53
54
|
export { Field, FieldHint, FormError, type FieldHintProps, type FieldProps, type FormErrorProps } from './Field.tsx';
|
package/src/menu/parts.tsx
CHANGED
|
@@ -97,10 +97,44 @@ type ItemLook = {
|
|
|
97
97
|
unstyled?: boolean;
|
|
98
98
|
};
|
|
99
99
|
|
|
100
|
+
/*
|
|
101
|
+
* Typing in an open menu moves to the first row whose text starts with the letters, read from the
|
|
102
|
+
* row's `label` or else its rendered text. The space JSX keeps between an icon and the name
|
|
103
|
+
* (`<Icon /> {name}`) draws nothing in a row laid out with a gap, but it would start that text and
|
|
104
|
+
* keep the row from ever matching. A row whose text starts with something other than its name,
|
|
105
|
+
* such as initials before it, sets `label`.
|
|
106
|
+
*/
|
|
107
|
+
function withoutLeadingSpace(children: ReactNode): ReactNode {
|
|
108
|
+
if (typeof children === 'string') {
|
|
109
|
+
return children.trimStart();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (!Array.isArray(children)) {
|
|
113
|
+
return children;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
let reached = false;
|
|
117
|
+
|
|
118
|
+
return children.map((child: ReactNode) => {
|
|
119
|
+
if (reached || typeof child !== 'string') {
|
|
120
|
+
return child;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const trimmed = child.trimStart();
|
|
124
|
+
reached = trimmed !== '';
|
|
125
|
+
|
|
126
|
+
return trimmed;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
100
130
|
type MenuItemProps = ComponentProps<typeof BaseMenu.Item> & ItemLook;
|
|
101
131
|
|
|
102
|
-
export function MenuItem({ unstyled = false, className, ...props }: MenuItemProps) {
|
|
103
|
-
return
|
|
132
|
+
export function MenuItem({ unstyled = false, className, children, ...props }: MenuItemProps) {
|
|
133
|
+
return (
|
|
134
|
+
<BaseMenu.Item className={unstyled ? className : withClass('menu-item', className)} {...props}>
|
|
135
|
+
{unstyled ? children : withoutLeadingSpace(children)}
|
|
136
|
+
</BaseMenu.Item>
|
|
137
|
+
);
|
|
104
138
|
}
|
|
105
139
|
|
|
106
140
|
export interface MenuCheckProps {
|
|
@@ -147,7 +181,7 @@ const checkRow = (kind: MenuCheckProps['kind'], unstyled: boolean, indicator: In
|
|
|
147
181
|
) : (
|
|
148
182
|
<>
|
|
149
183
|
{indicator === 'start' && <MenuCheck kind={kind} />}
|
|
150
|
-
{children}
|
|
184
|
+
{withoutLeadingSpace(children)}
|
|
151
185
|
{indicator === 'end' && <MenuCheck kind={kind} className="ml-auto" />}
|
|
152
186
|
</>
|
|
153
187
|
);
|
|
@@ -182,7 +216,7 @@ type SubmenuTriggerProps = ComponentProps<typeof BaseMenu.SubmenuTrigger> & {
|
|
|
182
216
|
export function MenuSubmenuTrigger({ className, children, chevron = true, ...props }: SubmenuTriggerProps) {
|
|
183
217
|
return (
|
|
184
218
|
<BaseMenu.SubmenuTrigger className={withClass('menu-item', className)} {...props}>
|
|
185
|
-
{children}
|
|
219
|
+
{withoutLeadingSpace(children)}
|
|
186
220
|
{chevron && <Icon icon={ChevronRight} size={14} className="ml-auto text-text-faint" />}
|
|
187
221
|
</BaseMenu.SubmenuTrigger>
|
|
188
222
|
);
|
package/src/theme.css
CHANGED
|
@@ -115,6 +115,16 @@
|
|
|
115
115
|
--file-icon-purple: #a631be;
|
|
116
116
|
--file-icon-pink: #d32a61;
|
|
117
117
|
--file-icon-mauve: #594c5b;
|
|
118
|
+
/* `EmptyScene`: what a drawing of an empty place is made of. */
|
|
119
|
+
--scene-top: #ffffff;
|
|
120
|
+
--scene-bottom: #ececf1;
|
|
121
|
+
--scene-rim: rgb(0 0 0 / 0.09);
|
|
122
|
+
--scene-line: rgb(0 0 0 / 0.12);
|
|
123
|
+
--scene-inset: rgb(0 0 0 / 0.06);
|
|
124
|
+
--scene-text: rgb(0 0 0 / 0.14);
|
|
125
|
+
--scene-lift: drop-shadow(0 1px 1px rgb(0 0 0 / 0.08)) drop-shadow(0 5px 10px rgb(0 0 0 / 0.08));
|
|
126
|
+
/* What lands in a scene overshoots a little and settles. */
|
|
127
|
+
--scene-arrive: cubic-bezier(0.34, 1.5, 0.55, 1);
|
|
118
128
|
}
|
|
119
129
|
|
|
120
130
|
/* The theme attribute sits on `<html>`, the element the light rule above lands on too, so a token
|
|
@@ -191,6 +201,13 @@
|
|
|
191
201
|
--file-icon-purple: #d568ea;
|
|
192
202
|
--file-icon-pink: #ff678d;
|
|
193
203
|
--file-icon-mauve: #79697b;
|
|
204
|
+
--scene-top: #2c2c32;
|
|
205
|
+
--scene-bottom: #1a1a1f;
|
|
206
|
+
--scene-rim: rgb(255 255 255 / 0.08);
|
|
207
|
+
--scene-line: rgb(255 255 255 / 0.1);
|
|
208
|
+
--scene-inset: rgb(0 0 0 / 0.3);
|
|
209
|
+
--scene-text: rgb(255 255 255 / 0.16);
|
|
210
|
+
--scene-lift: drop-shadow(0 1px 0 rgb(0 0 0 / 0.4)) drop-shadow(0 6px 10px rgb(0 0 0 / 0.35));
|
|
194
211
|
}
|
|
195
212
|
|
|
196
213
|
/* Code a person reads as code (an editor, a grid of values, a statement) at one size the app may set on
|
|
@@ -1178,3 +1195,93 @@
|
|
|
1178
1195
|
.ade-scrollbar, .ade-scrollbar::before, .ade-scrollbar-thumb::before { transition: none; }
|
|
1179
1196
|
}
|
|
1180
1197
|
}
|
|
1198
|
+
|
|
1199
|
+
/* The drawing of an empty place (`EmptyScene`): shapes in a soft gradient with a thin rim and one detail
|
|
1200
|
+
in the accent color, on the same 8 second loop. Each rule below only animates: at rest, and under
|
|
1201
|
+
reduced motion, a drawing shows the end of what it plays. */
|
|
1202
|
+
.scene { flex: none; width: 160px; height: 104px; overflow: visible; }
|
|
1203
|
+
.scene-compact { width: 136px; height: 88px; }
|
|
1204
|
+
.scene-shape { fill: var(--scene-fill); stroke: var(--scene-rim); stroke-width: 1; stroke-linejoin: round; }
|
|
1205
|
+
.scene-edge { fill: none; stroke: var(--scene-line); stroke-width: 1.25; stroke-linecap: round; stroke-linejoin: round; }
|
|
1206
|
+
.scene-inset { fill: var(--scene-inset); }
|
|
1207
|
+
.scene-line { fill: none; stroke: var(--text-faint); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
|
|
1208
|
+
.scene-text { fill: none; stroke: var(--scene-text); stroke-width: 4px; stroke-linecap: round; }
|
|
1209
|
+
.scene-hand { fill: none; stroke: var(--text-muted); stroke-width: 2.5; stroke-linecap: round; }
|
|
1210
|
+
.scene-dot { fill: var(--text-faint); }
|
|
1211
|
+
.scene-accent { fill: var(--accent); }
|
|
1212
|
+
.scene-accent-line { fill: none; stroke: var(--accent); stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
|
|
1213
|
+
.scene-lift { filter: var(--scene-lift); }
|
|
1214
|
+
.scene-cursor { fill: var(--text); stroke: var(--surface); stroke-width: 1; stroke-linejoin: round; }
|
|
1215
|
+
.scene [class*="scene-reveal-"] { transform-box: fill-box; transform-origin: center; }
|
|
1216
|
+
.scene [class*="scene-stroke-"], .scene [class*="scene-type-"] { stroke-dasharray: 1; }
|
|
1217
|
+
|
|
1218
|
+
@keyframes scene-loop { 0% { opacity: 0; } 3%, 88% { opacity: 1; } 95%, 100% { opacity: 0; } }
|
|
1219
|
+
@keyframes scene-reveal-0 { 0%, 3% { opacity: 0; transform: translateY(5px) scale(0.94); } 9%, 100% { opacity: 1; transform: none; } }
|
|
1220
|
+
@keyframes scene-stroke-0 { 0%, 3% { stroke-dashoffset: 1; } 10%, 100% { stroke-dashoffset: 0; } }
|
|
1221
|
+
@keyframes scene-reveal-1 { 0%, 9% { opacity: 0; transform: translateY(5px) scale(0.94); } 15%, 100% { opacity: 1; transform: none; } }
|
|
1222
|
+
@keyframes scene-stroke-1 { 0%, 9% { stroke-dashoffset: 1; } 16%, 100% { stroke-dashoffset: 0; } }
|
|
1223
|
+
@keyframes scene-reveal-2 { 0%, 15% { opacity: 0; transform: translateY(5px) scale(0.94); } 21%, 100% { opacity: 1; transform: none; } }
|
|
1224
|
+
@keyframes scene-stroke-2 { 0%, 15% { stroke-dashoffset: 1; } 22%, 100% { stroke-dashoffset: 0; } }
|
|
1225
|
+
@keyframes scene-reveal-3 { 0%, 21% { opacity: 0; transform: translateY(5px) scale(0.94); } 27%, 100% { opacity: 1; transform: none; } }
|
|
1226
|
+
@keyframes scene-stroke-3 { 0%, 21% { stroke-dashoffset: 1; } 28%, 100% { stroke-dashoffset: 0; } }
|
|
1227
|
+
@keyframes scene-reveal-4 { 0%, 27% { opacity: 0; transform: translateY(5px) scale(0.94); } 33%, 100% { opacity: 1; transform: none; } }
|
|
1228
|
+
@keyframes scene-stroke-4 { 0%, 27% { stroke-dashoffset: 1; } 34%, 100% { stroke-dashoffset: 0; } }
|
|
1229
|
+
@keyframes scene-reveal-5 { 0%, 33% { opacity: 0; transform: translateY(5px) scale(0.94); } 39%, 100% { opacity: 1; transform: none; } }
|
|
1230
|
+
@keyframes scene-stroke-5 { 0%, 33% { stroke-dashoffset: 1; } 40%, 100% { stroke-dashoffset: 0; } }
|
|
1231
|
+
@keyframes scene-reveal-6 { 0%, 39% { opacity: 0; transform: translateY(5px) scale(0.94); } 45%, 100% { opacity: 1; transform: none; } }
|
|
1232
|
+
@keyframes scene-stroke-6 { 0%, 39% { stroke-dashoffset: 1; } 46%, 100% { stroke-dashoffset: 0; } }
|
|
1233
|
+
@keyframes scene-reveal-7 { 0%, 45% { opacity: 0; transform: translateY(5px) scale(0.94); } 51%, 100% { opacity: 1; transform: none; } }
|
|
1234
|
+
@keyframes scene-stroke-7 { 0%, 45% { stroke-dashoffset: 1; } 52%, 100% { stroke-dashoffset: 0; } }
|
|
1235
|
+
@keyframes scene-reveal-8 { 0%, 51% { opacity: 0; transform: translateY(5px) scale(0.94); } 57%, 100% { opacity: 1; transform: none; } }
|
|
1236
|
+
@keyframes scene-stroke-8 { 0%, 51% { stroke-dashoffset: 1; } 58%, 100% { stroke-dashoffset: 0; } }
|
|
1237
|
+
@keyframes scene-reveal-9 { 0%, 57% { opacity: 0; transform: translateY(5px) scale(0.94); } 63%, 100% { opacity: 1; transform: none; } }
|
|
1238
|
+
@keyframes scene-stroke-9 { 0%, 57% { stroke-dashoffset: 1; } 64%, 100% { stroke-dashoffset: 0; } }
|
|
1239
|
+
@keyframes scene-reveal-10 { 0%, 63% { opacity: 0; transform: translateY(5px) scale(0.94); } 69%, 100% { opacity: 1; transform: none; } }
|
|
1240
|
+
@keyframes scene-stroke-10 { 0%, 63% { stroke-dashoffset: 1; } 70%, 100% { stroke-dashoffset: 0; } }
|
|
1241
|
+
@keyframes scene-reveal-11 { 0%, 69% { opacity: 0; transform: translateY(5px) scale(0.94); } 75%, 100% { opacity: 1; transform: none; } }
|
|
1242
|
+
@keyframes scene-stroke-11 { 0%, 69% { stroke-dashoffset: 1; } 76%, 100% { stroke-dashoffset: 0; } }
|
|
1243
|
+
@keyframes scene-reveal-12 { 0%, 75% { opacity: 0; transform: translateY(5px) scale(0.94); } 81%, 100% { opacity: 1; transform: none; } }
|
|
1244
|
+
@keyframes scene-stroke-12 { 0%, 75% { stroke-dashoffset: 1; } 82%, 100% { stroke-dashoffset: 0; } }
|
|
1245
|
+
|
|
1246
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
1247
|
+
.scene-loop { animation: scene-loop 8s linear infinite; }
|
|
1248
|
+
.scene-reveal-0 { animation: scene-reveal-0 8s var(--scene-arrive) infinite; }
|
|
1249
|
+
.scene-stroke-0 { animation: scene-stroke-0 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1250
|
+
.scene-type-0 { animation: scene-stroke-0 8s steps(5, jump-none) infinite; }
|
|
1251
|
+
.scene-reveal-1 { animation: scene-reveal-1 8s var(--scene-arrive) infinite; }
|
|
1252
|
+
.scene-stroke-1 { animation: scene-stroke-1 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1253
|
+
.scene-type-1 { animation: scene-stroke-1 8s steps(5, jump-none) infinite; }
|
|
1254
|
+
.scene-reveal-2 { animation: scene-reveal-2 8s var(--scene-arrive) infinite; }
|
|
1255
|
+
.scene-stroke-2 { animation: scene-stroke-2 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1256
|
+
.scene-type-2 { animation: scene-stroke-2 8s steps(5, jump-none) infinite; }
|
|
1257
|
+
.scene-reveal-3 { animation: scene-reveal-3 8s var(--scene-arrive) infinite; }
|
|
1258
|
+
.scene-stroke-3 { animation: scene-stroke-3 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1259
|
+
.scene-type-3 { animation: scene-stroke-3 8s steps(5, jump-none) infinite; }
|
|
1260
|
+
.scene-reveal-4 { animation: scene-reveal-4 8s var(--scene-arrive) infinite; }
|
|
1261
|
+
.scene-stroke-4 { animation: scene-stroke-4 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1262
|
+
.scene-type-4 { animation: scene-stroke-4 8s steps(5, jump-none) infinite; }
|
|
1263
|
+
.scene-reveal-5 { animation: scene-reveal-5 8s var(--scene-arrive) infinite; }
|
|
1264
|
+
.scene-stroke-5 { animation: scene-stroke-5 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1265
|
+
.scene-type-5 { animation: scene-stroke-5 8s steps(5, jump-none) infinite; }
|
|
1266
|
+
.scene-reveal-6 { animation: scene-reveal-6 8s var(--scene-arrive) infinite; }
|
|
1267
|
+
.scene-stroke-6 { animation: scene-stroke-6 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1268
|
+
.scene-type-6 { animation: scene-stroke-6 8s steps(5, jump-none) infinite; }
|
|
1269
|
+
.scene-reveal-7 { animation: scene-reveal-7 8s var(--scene-arrive) infinite; }
|
|
1270
|
+
.scene-stroke-7 { animation: scene-stroke-7 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1271
|
+
.scene-type-7 { animation: scene-stroke-7 8s steps(5, jump-none) infinite; }
|
|
1272
|
+
.scene-reveal-8 { animation: scene-reveal-8 8s var(--scene-arrive) infinite; }
|
|
1273
|
+
.scene-stroke-8 { animation: scene-stroke-8 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1274
|
+
.scene-type-8 { animation: scene-stroke-8 8s steps(5, jump-none) infinite; }
|
|
1275
|
+
.scene-reveal-9 { animation: scene-reveal-9 8s var(--scene-arrive) infinite; }
|
|
1276
|
+
.scene-stroke-9 { animation: scene-stroke-9 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1277
|
+
.scene-type-9 { animation: scene-stroke-9 8s steps(5, jump-none) infinite; }
|
|
1278
|
+
.scene-reveal-10 { animation: scene-reveal-10 8s var(--scene-arrive) infinite; }
|
|
1279
|
+
.scene-stroke-10 { animation: scene-stroke-10 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1280
|
+
.scene-type-10 { animation: scene-stroke-10 8s steps(5, jump-none) infinite; }
|
|
1281
|
+
.scene-reveal-11 { animation: scene-reveal-11 8s var(--scene-arrive) infinite; }
|
|
1282
|
+
.scene-stroke-11 { animation: scene-stroke-11 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1283
|
+
.scene-type-11 { animation: scene-stroke-11 8s steps(5, jump-none) infinite; }
|
|
1284
|
+
.scene-reveal-12 { animation: scene-reveal-12 8s var(--scene-arrive) infinite; }
|
|
1285
|
+
.scene-stroke-12 { animation: scene-stroke-12 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
|
|
1286
|
+
.scene-type-12 { animation: scene-stroke-12 8s steps(5, jump-none) infinite; }
|
|
1287
|
+
}
|