elbe-ui 2.0.12 → 2.0.15

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.
@@ -84,7 +84,7 @@ export function _makeBitProvider(context, bitP) {
84
84
  if (streamCancel)
85
85
  streamCancel();
86
86
  const cancel = _bit.stream(p, _partCtrl);
87
- setStreamCancel(() => cancel);
87
+ setStreamCancel(() => cancel());
88
88
  return;
89
89
  }
90
90
  catch (e) {
@@ -107,14 +107,14 @@ export function _makeBitProvider(context, bitP) {
107
107
  if (state.v.type === "data") {
108
108
  return _isFn(onData)
109
109
  ? onData(state.v.value)
110
- : (_a = onData) !== null && _a !== void 0 ? _a : null;
110
+ : ((_a = onData) !== null && _a !== void 0 ? _a : null);
111
111
  }
112
112
  if (state.v.type === "error") {
113
113
  return _isFn(onError)
114
114
  ? onError(state.v.value)
115
- : (_b = onError) !== null && _b !== void 0 ? _b : null;
115
+ : ((_b = onError) !== null && _b !== void 0 ? _b : null);
116
116
  }
117
- return _isFn(onLoading) ? onLoading() : (_c = onLoading) !== null && _c !== void 0 ? _c : null;
117
+ return _isFn(onLoading) ? onLoading() : ((_c = onLoading) !== null && _c !== void 0 ? _c : null);
118
118
  }
119
119
  function mapUI(onData, onError, onLoading) {
120
120
  return map((d) => onData(d), (e) => (onError !== null && onError !== void 0 ? onError : ((e) => _jsx(ErrorView, { error: e, retry: () => _reload(false) })))(e), () => (onLoading !== null && onLoading !== void 0 ? onLoading : (() => _jsx(_LoadView, {})))());
package/dist/index.d.ts CHANGED
@@ -47,7 +47,9 @@ export * from "./ui/components/section_card";
47
47
  export * from "./ui/components/spinner";
48
48
  export * from "./ui/components/table";
49
49
  export * from "./ui/components/text";
50
+ export * from "./ui/components/tooltip";
50
51
  export * from "./ui/app/app";
52
+ export * from "./ui/app/app_ctxt";
51
53
  export * from "./ui/components/dev/todo";
52
54
  export * from "./ui/theme/subthemes/color/colors/colors";
53
55
  export * from "./ui/theme/theme";
package/dist/index.js CHANGED
@@ -49,7 +49,9 @@ export * from "./ui/components/section_card";
49
49
  export * from "./ui/components/spinner";
50
50
  export * from "./ui/components/table";
51
51
  export * from "./ui/components/text";
52
+ export * from "./ui/components/tooltip";
52
53
  export * from "./ui/app/app";
54
+ export * from "./ui/app/app_ctxt";
53
55
  export * from "./ui/components/dev/todo";
54
56
  export * from "./ui/theme/subthemes/color/colors/colors";
55
57
  export * from "./ui/theme/theme";
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useMemo, useState } from "react";
3
- import { Box, DialogsProvider, isMenuRoute, omit, ToastProvider, Wouter, } from "../..";
3
+ import { Box, DialogsProvider, Icons, isMenuRoute, omit, PrettyErrorView, Route, ToastProvider, WithL10nOrDefault, Wouter, } from "../..";
4
4
  import { Menu } from "../components/layout/menu";
5
5
  import { unwrapFragments } from "../util/_util";
6
6
  import { AppContext } from "./app_ctxt";
@@ -91,43 +91,48 @@ function _App(p) {
91
91
  const menuItems = _extractMenuItems(children);
92
92
  return { children, menuItems };
93
93
  }, [p.children]);
94
- return (_jsx(p.themeContext.WithTheme, { theme: themeSelected, children: _jsx(AppContext.Provider, { value: {
95
- appConfig: p.config,
96
- _appThemeContext: p.themeContext,
97
- router: {
98
- goBack: (steps = 1) => {
99
- if (history.length === 0)
100
- return;
101
- const targetIndex = Math.max(0, history.length - 1 - steps);
102
- const target = history[targetIndex];
103
- setHistory((h) => h.slice(0, targetIndex + 1));
104
- navigate(target, { replace: true });
94
+ return (_jsx(p.themeContext.WithTheme, { theme: themeSelected, children: _jsx(WithL10nOrDefault, { children: _jsx(AppContext.Provider, { value: {
95
+ appConfig: p.config,
96
+ _appThemeContext: p.themeContext,
97
+ router: {
98
+ goBack: (steps = 1) => {
99
+ if (history.length === 0)
100
+ return;
101
+ const targetIndex = Math.max(0, history.length - 1 - steps);
102
+ const target = history[targetIndex];
103
+ setHistory((h) => h.slice(0, targetIndex + 1));
104
+ navigate(target, { replace: true });
105
+ },
106
+ go: (p, replace) => {
107
+ setHistory((h) => {
108
+ if (replace === "all")
109
+ return [p];
110
+ const repl = Math.max(0, replace !== null && replace !== void 0 ? replace : 0);
111
+ if (repl === 0)
112
+ return [...h, p];
113
+ return [...h.slice(0, -repl), p];
114
+ });
115
+ navigate(p, { replace: (replace !== null && replace !== void 0 ? replace : 0) !== 0 });
116
+ },
117
+ history: history,
118
+ location: location,
105
119
  },
106
- go: (p, replace) => {
107
- setHistory((h) => {
108
- if (replace === "all")
109
- return [p];
110
- const repl = Math.max(0, replace !== null && replace !== void 0 ? replace : 0);
111
- if (repl === 0)
112
- return [...h, p];
113
- return [...h.slice(0, -repl), p];
114
- });
115
- navigate(p, { replace: (replace !== null && replace !== void 0 ? replace : 0) !== 0 });
116
- },
117
- history: history,
118
- location: location,
119
- },
120
- menu: menuItems.length === 0
121
- ? undefined
122
- : {
123
- isOpen: menuOpen,
124
- setOpen: (s) => setMenuOpen(s),
125
- },
126
- }, children: _jsx(ToastProvider, { children: _jsx(DialogsProvider, { children: _jsxs(Box, { typeLabel: "app_base", scheme: "primary", style: {
127
- display: "flex",
128
- width: "100%",
129
- minHeight: "100vh",
130
- }, children: [menuItems.length > 0 && _jsx(Menu, { items: menuItems }), _jsx("div", { style: { flex: 1, width: "0px" }, children: _jsx(Wouter.Switch, { children: children }) })] }) }) }) }) }));
120
+ menu: menuItems.length === 0
121
+ ? undefined
122
+ : {
123
+ isOpen: menuOpen,
124
+ setOpen: (s) => setMenuOpen(s),
125
+ },
126
+ }, children: _jsx(ToastProvider, { children: _jsx(DialogsProvider, { children: _jsxs(Box, { typeLabel: "app_base", scheme: "primary", style: {
127
+ display: "flex",
128
+ width: "100%",
129
+ minHeight: "100vh",
130
+ }, children: [menuItems.length > 0 && _jsx(Menu, { items: menuItems }), _jsx("div", { style: {
131
+ flex: 1,
132
+ width: "0px",
133
+ display: "flex",
134
+ flexDirection: "column",
135
+ }, children: _jsxs(Wouter.Switch, { children: [children, ",", _jsx(_404Route, {})] }) })] }) }) }) }) }) }));
131
136
  }
132
137
  function _extractMenuItems(children) {
133
138
  if (!children)
@@ -140,3 +145,14 @@ function _extractMenuItems(children) {
140
145
  }
141
146
  return items;
142
147
  }
148
+ function _404Route() {
149
+ return (_jsx(Route, { path: "*", children: _jsx(PrettyErrorView, { flex: true, error: {
150
+ icon: Icons.Frown,
151
+ code: "404",
152
+ message: "404 - Not Found",
153
+ description: "The requested page could not be found.",
154
+ }, retry: () => {
155
+ //set browser location to / manuall:
156
+ window.location.href = "/";
157
+ } }) }));
158
+ }
@@ -45,7 +45,7 @@ function _btn(_a) {
45
45
  borderRadius: elbe.sharp ? 0 : "3rem",
46
46
  height: "3rem",
47
47
  width: "3rem",
48
- }), { title: elbe.tooltip ? undefined : (_b = elbe.ariaLabel) !== null && _b !== void 0 ? _b : undefined, onClick: (e) => {
48
+ }), { title: elbe.tooltip ? undefined : ((_b = elbe.ariaLabel) !== null && _b !== void 0 ? _b : undefined), onClick: (e) => {
49
49
  e.stopPropagation();
50
50
  onTap && onTap(e);
51
51
  }, children: _jsx(Icon, { icon: icon }) })) }) }));
@@ -11,7 +11,7 @@ export declare function ErrorView({ error, retry, debug, }: {
11
11
  retry?: () => any;
12
12
  debug?: boolean;
13
13
  }): import("react/jsx-runtime").JSX.Element;
14
- export declare function PrettyErrorView({ error, retry, labels, }: {
14
+ export declare function PrettyErrorView({ error, retry, labels, flex, }: {
15
15
  error: ElbeError;
16
16
  retry?: () => any;
17
17
  labels?: {
@@ -19,4 +19,5 @@ export declare function PrettyErrorView({ error, retry, labels, }: {
19
19
  home?: L10nInlinePlain;
20
20
  details: L10nInlinePlain;
21
21
  };
22
+ flex?: boolean;
22
23
  }): import("react/jsx-runtime").JSX.Element;
@@ -44,9 +44,9 @@ export function PrettyErrorView({ error, retry, labels = {
44
44
  it: "dettagli dell'errore",
45
45
  pt: "detalhes do erro",
46
46
  },
47
- }, }) {
47
+ }, flex = false, }) {
48
48
  var _a, _b, _c, _d, _e, _f, _g, _h;
49
49
  const l10n = _maybeL10n();
50
50
  const [open, setOpen] = useState(false);
51
- return (_jsxs(Column, { cross: "center", style: { margin: "1rem 0", padding: "1rem" }, children: [_jsx(Icon, { icon: (_a = error.icon) !== null && _a !== void 0 ? _a : icons.OctagonAlert }), _jsx(Text.h4, { v: (_b = l10n === null || l10n === void 0 ? void 0 : l10n.inline(error.message)) !== null && _b !== void 0 ? _b : "error" }), _jsx(Text, { align: "center", v: (_c = l10n === null || l10n === void 0 ? void 0 : l10n.inline(error.description)) !== null && _c !== void 0 ? _c : "", style: { cursor: "pointer" }, native: { onClick: () => setOpen(true) } }), retry && (_jsx(Button.flat, { ariaLabel: (_d = l10n === null || l10n === void 0 ? void 0 : l10n.inline(labels.retry)) !== null && _d !== void 0 ? _d : "retry", label: (_e = l10n === null || l10n === void 0 ? void 0 : l10n.inline(labels.retry)) !== null && _e !== void 0 ? _e : "retry", icon: Icons.RotateCcw, onTap: () => retry() })), error.code === 404 && (_jsx(Button.flat, { ariaLabel: (_f = l10n === null || l10n === void 0 ? void 0 : l10n.inline(labels.home)) !== null && _f !== void 0 ? _f : "go home", label: (_g = l10n === null || l10n === void 0 ? void 0 : l10n.inline(labels.home)) !== null && _g !== void 0 ? _g : "go home", icon: Icons.House, onTap: () => (window.location.href = "/") })), _jsx(Dialog, { title: (_h = l10n === null || l10n === void 0 ? void 0 : l10n.inline(labels.details)) !== null && _h !== void 0 ? _h : "error details", open: open, onClose: () => setOpen(false), children: _jsx("pre", { children: `code: ${error.code}\n\n` + JSON.stringify(error.details, null, 2) }) })] }));
51
+ return (_jsxs(Column, { cross: "center", main: "center", flex: flex, style: { margin: "1rem 0", padding: "1rem" }, children: [_jsx(Icon, { icon: (_a = error.icon) !== null && _a !== void 0 ? _a : icons.OctagonAlert }), _jsx(Text.h4, { v: (_b = l10n === null || l10n === void 0 ? void 0 : l10n.inline(error.message)) !== null && _b !== void 0 ? _b : "error" }), _jsx(Text, { align: "center", v: (_c = l10n === null || l10n === void 0 ? void 0 : l10n.inline(error.description)) !== null && _c !== void 0 ? _c : "", style: { cursor: "pointer" }, native: { onClick: () => setOpen(true) } }), retry && (_jsx(Button.flat, { ariaLabel: (_d = l10n === null || l10n === void 0 ? void 0 : l10n.inline(labels.retry)) !== null && _d !== void 0 ? _d : "retry", label: (_e = l10n === null || l10n === void 0 ? void 0 : l10n.inline(labels.retry)) !== null && _e !== void 0 ? _e : "retry", icon: Icons.RotateCcw, onTap: () => retry() })), error.code === 404 && (_jsx(Button.flat, { ariaLabel: (_f = l10n === null || l10n === void 0 ? void 0 : l10n.inline(labels.home)) !== null && _f !== void 0 ? _f : "go home", label: (_g = l10n === null || l10n === void 0 ? void 0 : l10n.inline(labels.home)) !== null && _g !== void 0 ? _g : "go home", icon: Icons.House, onTap: () => (window.location.href = "/") })), _jsx(Dialog, { title: (_h = l10n === null || l10n === void 0 ? void 0 : l10n.inline(labels.details)) !== null && _h !== void 0 ? _h : "error details", open: open, onClose: () => setOpen(false), children: _jsx("pre", { children: `code: ${error.code}\n\n` + JSON.stringify(error.details, null, 2) }) })] }));
52
52
  }
@@ -21,7 +21,7 @@ export function Footer({ left, right, copyright, version, legal, marginTop, }) {
21
21
  borderLeftStyle: "none",
22
22
  borderRightStyle: "none",
23
23
  borderBottomStyle: "none",
24
- borderTopLeftRadius: layoutMode.isWide
24
+ borderTopLeftRadius: layoutMode.isWide && !theme.color.isContrast
25
25
  ? `${theme.geometry.radius}rem`
26
26
  : undefined,
27
27
  /*color: theme.color.currentColor.front
@@ -38,5 +38,7 @@ function _FlexLayout(row, p, elbe, wraps) {
38
38
  overflowX: !row ? undefined : p.scroll ? "auto" : undefined,
39
39
  overflowY: row ? undefined : p.scroll ? "auto" : undefined,
40
40
  flex: ((_c = elbe.flex) !== null && _c !== void 0 ? _c : p.scroll) ? 1 : undefined,
41
+ minWidth: 0,
42
+ minHeight: 0,
41
43
  }), { children: p.children })));
42
44
  }
@@ -37,7 +37,10 @@ export function SectionCard(p) {
37
37
  }, children: [_jsx(Dialog, { title: p.title + " - Info", open: hintOpen, maxWidth: 35, onClose: () => setHintOpen(false), children: typeof p.hint === "string" ? (_jsx("div", { className: "elbe-hint-markdown", children: _jsx(Markdown, { children: p.hint, allowElement: () => true }) })) : (p.hint) }), _jsxs(Column, { children: [_jsxs(Card, { onTap: collapsed === undefined
38
38
  ? undefined
39
39
  : () => setCollapsed(!collapsed), margin: -1, padding: 1, className: collapsed === undefined ? undefined : "hoverable_card", style: {
40
- border: "none",
40
+ borderLeftStyle: "none",
41
+ borderTopStyle: "none",
42
+ borderRightStyle: "none",
43
+ borderBottomStyle: "none",
41
44
  display: "flex",
42
45
  alignItems: "center",
43
46
  backgroundColor: "transparent",
@@ -1,5 +1,8 @@
1
1
  import { ElbeChildren } from "../util/types";
2
2
  export declare function WithTooltip(p: {
3
- tooltip?: string;
3
+ tooltip?: string | ElbeChildren;
4
+ delay?: number;
5
+ alignHorizontal?: "left" | "center" | "right" | "auto";
6
+ alignVertical?: "top" | "center" | "bottom" | "auto";
4
7
  children?: ElbeChildren;
5
8
  }): import("react/jsx-runtime").JSX.Element;
@@ -12,10 +12,37 @@ export function WithTooltip(p) {
12
12
  const { theme } = _appThemeContext.useTheme().useWith((c) => ({
13
13
  color: Object.assign(Object.assign({}, c.color), { selection: Object.assign(Object.assign({}, c.color.selection), { scheme: "inverse", kind: "accent", manner: "plain", state: "neutral" }) }),
14
14
  }), []);
15
+ const align = useMemo(() => {
16
+ var _a, _b;
17
+ let xVals = { xOffset: -12, xTransform: "-100%" };
18
+ let yVals = { yOffset: -12, yTransform: "-100%" };
19
+ let xAlign = (_a = p.alignHorizontal) !== null && _a !== void 0 ? _a : "auto";
20
+ let yAlign = (_b = p.alignVertical) !== null && _b !== void 0 ? _b : "auto";
21
+ // if center-center, align above cursor to avoid covering it
22
+ if (xAlign === "center" && yAlign === "center") {
23
+ console.warn("Center-Center alignment may cause the tooltip" +
24
+ " to cover the cursor. Aligning to top-center instead.");
25
+ yAlign = "top";
26
+ }
27
+ if (xAlign === "auto")
28
+ xAlign = coords.left ? "right" : "left";
29
+ if (yAlign === "auto")
30
+ yAlign = coords.top ? "bottom" : "top";
31
+ if (xAlign === "center")
32
+ xVals = { xOffset: 0, xTransform: "-50%" };
33
+ if (xAlign === "right")
34
+ xVals = { xOffset: 12, xTransform: "0%" };
35
+ if (yAlign === "center")
36
+ yVals = { yOffset: 0, yTransform: "-50%" };
37
+ if (yAlign === "bottom")
38
+ yVals = { yOffset: 12, yTransform: "0%" };
39
+ return Object.assign(Object.assign({}, xVals), yVals);
40
+ }, [p.alignHorizontal, coords.left]);
15
41
  if (!p.tooltip)
16
42
  return _jsx(_Fragment, { children: p.children });
17
43
  return (_jsxs("span", { onMouseEnter: () => {
18
- timeoutRef.current = window.setTimeout(() => setVisible(true), 1000);
44
+ var _a;
45
+ timeoutRef.current = window.setTimeout(() => setVisible(true), (_a = p.delay) !== null && _a !== void 0 ? _a : 1000);
19
46
  }, onMouseLeave: () => {
20
47
  console.log("leave");
21
48
  if (timeoutRef.current) {
@@ -31,18 +58,14 @@ export function WithTooltip(p) {
31
58
  left: e.clientX > window.innerWidth / 2,
32
59
  });
33
60
  }, style: { display: "contents" }, children: [p.children, visible &&
34
- createPortal(_jsx("div", { role: "tooltip", className: "elbe_tooltip", style: {
35
- position: "fixed",
36
- pointerEvents: "none",
37
- zIndex: 1001,
38
- top: coords.y + (coords.top ? -12 : 12), // offset below cursor
39
- left: coords.x + (coords.left ? -12 : 12), // offset right of cursor
40
- background: theme.color.currentColor.back
41
- .inter(theme.color.currentColor.front, 0.2)
42
- .asCss(),
43
- color: theme.color.currentColor.front.asCss(),
44
- padding: ".125rem .3rem",
45
- borderRadius: ".25rem",
46
- transform: `translate(${coords.left ? "-100%" : "0"}, ${coords.top ? "-100%" : "0"})`,
47
- }, children: p.tooltip }), rootDOM)] }));
61
+ createPortal(_jsx("div", { role: "tooltip", className: "elbe_tooltip", style: Object.assign({ position: "fixed", pointerEvents: "none", zIndex: 1001, top: coords.y + align.yOffset, left: coords.x + align.xOffset, transform: `translate(${align.xTransform}, ${align.yTransform})` }, (typeof p.tooltip === "string"
62
+ ? {
63
+ background: theme.color.currentColor.back
64
+ .inter(theme.color.currentColor.front, 0.2)
65
+ .asCss(),
66
+ color: theme.color.currentColor.front.asCss(),
67
+ padding: ".125rem .3rem",
68
+ borderRadius: ".25rem",
69
+ }
70
+ : {})), children: p.tooltip }), rootDOM)] }));
48
71
  }
@@ -19,7 +19,7 @@ const _makeSecondary = ({ base, seed }) => LayerColor.new({
19
19
  border: base.border,
20
20
  });
21
21
  const _makeInverse = ({ base }) => base.mirrorBrightnessLayer();
22
- const _makeMajor = ({ style, path }) => {
22
+ const _makeMajor = ({ style }) => {
23
23
  return LayerColor.fromBack(style.back, { border: style.back });
24
24
  };
25
25
  const _makeMinor = ({ base, style }) => {
@@ -23,4 +23,7 @@ export declare function makeL10n<T extends _L10nData>(fallback: {
23
23
  L10n: React.FunctionComponent<_L10nProps>;
24
24
  useL10n: () => _L10nState<T>;
25
25
  };
26
+ export declare function WithL10nOrDefault(p: {
27
+ children: ElbeChildren;
28
+ }): import("react/jsx-runtime").JSX.Element;
26
29
  export {};
@@ -1,6 +1,6 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useEffect, useState } from "react";
3
- import { _bestMatch, _L10nContext, _useL10n, } from "./_l10n_util";
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useState } from "react";
3
+ import { _bestMatch, _L10nContext, _maybeL10n, _useL10n, } from "./_l10n_util";
4
4
  /**
5
5
  * L10nBase is a function that creates a localization context provider and a hook to use the localization context.
6
6
  * @param fallback this is the fallback locale, which is used if no other locale is found. It is the basis for the locale type and must thus be complete.
@@ -44,3 +44,10 @@ function _l10nInlineResolver(locale) {
44
44
  return (_d = (_c = value[bestMatch !== null && bestMatch !== void 0 ? bestMatch : anyEnglish]) !== null && _c !== void 0 ? _c : value[locales[0]]) !== null && _d !== void 0 ? _d : "";
45
45
  };
46
46
  }
47
+ export function WithL10nOrDefault(p) {
48
+ const l10n = useMemo(() => makeL10n({ en: {} }, {}), []);
49
+ const existing = _maybeL10n();
50
+ if (!!existing)
51
+ return _jsx(_Fragment, { children: p.children });
52
+ return _jsx(l10n.L10n, { children: p.children });
53
+ }
@@ -4,9 +4,9 @@
4
4
  */
5
5
  export function showToast(message) {
6
6
  // find the 'elbe' element
7
- const elbe = document.getElementById("elbe-app");
7
+ const elbe = document.getElementById("elbe_app");
8
8
  if (!elbe) {
9
- console.warn("could not show legacy toast, no base element with '#elbe-app' found");
9
+ console.warn("could not show legacy toast, no base element with '#elbe_app' found");
10
10
  return;
11
11
  }
12
12
  const toast = document.createElement("div");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "elbe-ui",
3
- "version": "2.0.12",
3
+ "version": "2.0.15",
4
4
  "author": "Robin Naumann",
5
5
  "license": "MIT",
6
6
  "repository": {