elbe-ui 0.2.26 → 0.2.30

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.
Files changed (64) hide show
  1. package/dist/elbe.css +621 -0
  2. package/dist/index.d.ts +1548 -17
  3. package/dist/index.js +63 -18577
  4. package/package.json +15 -13
  5. package/dist/bit/bit.d.ts +0 -34
  6. package/dist/bit/ctrl_bit.d.ts +0 -30
  7. package/dist/service/s_api.d.ts +0 -30
  8. package/dist/ui/color_theme.d.ts +0 -5
  9. package/dist/ui/components/badge.d.ts +0 -25
  10. package/dist/ui/components/box.d.ts +0 -1027
  11. package/dist/ui/components/button.d.ts +0 -23
  12. package/dist/ui/components/card.d.ts +0 -14
  13. package/dist/ui/components/dialog.d.ts +0 -8
  14. package/dist/ui/components/error_view.d.ts +0 -15
  15. package/dist/ui/components/flex.d.ts +0 -11
  16. package/dist/ui/components/icon_button.d.ts +0 -19
  17. package/dist/ui/components/input/checkbox.d.ts +0 -6
  18. package/dist/ui/components/input/input_field.d.ts +0 -22
  19. package/dist/ui/components/input/range.d.ts +0 -8
  20. package/dist/ui/components/input/select.d.ts +0 -10
  21. package/dist/ui/components/input/text_area.d.ts +0 -10
  22. package/dist/ui/components/padded.d.ts +0 -25
  23. package/dist/ui/components/scaffold.d.ts +0 -23
  24. package/dist/ui/components/spinner.d.ts +0 -3
  25. package/dist/ui/components/text.d.ts +0 -33
  26. package/dist/ui/components/toggle_button.d.ts +0 -12
  27. package/dist/ui/components/util.d.ts +0 -3
  28. package/dist/ui/util/confirm_dialog.d.ts +0 -10
  29. package/dist/ui/util/error_view.d.ts +0 -1
  30. package/dist/ui/util/toast.d.ts +0 -5
  31. package/dist/ui/util/util.d.ts +0 -19
  32. package/elbe.scss +0 -100
  33. package/src/bit/bit.tsx +0 -128
  34. package/src/bit/ctrl_bit.tsx +0 -112
  35. package/src/index.tsx +0 -29
  36. package/src/service/s_api.ts +0 -102
  37. package/src/ui/color_theme.ts +0 -24
  38. package/src/ui/components/badge.tsx +0 -78
  39. package/src/ui/components/box.tsx +0 -49
  40. package/src/ui/components/button.tsx +0 -61
  41. package/src/ui/components/card.tsx +0 -45
  42. package/src/ui/components/dialog.tsx +0 -51
  43. package/src/ui/components/error_view.tsx +0 -72
  44. package/src/ui/components/flex.tsx +0 -64
  45. package/src/ui/components/icon_button.tsx +0 -56
  46. package/src/ui/components/input/checkbox.tsx +0 -32
  47. package/src/ui/components/input/input_field.tsx +0 -57
  48. package/src/ui/components/input/range.tsx +0 -37
  49. package/src/ui/components/input/select.tsx +0 -29
  50. package/src/ui/components/input/text_area.tsx +0 -45
  51. package/src/ui/components/padded.tsx +0 -62
  52. package/src/ui/components/scaffold.tsx +0 -79
  53. package/src/ui/components/spinner.tsx +0 -11
  54. package/src/ui/components/text.tsx +0 -78
  55. package/src/ui/components/toggle_button.tsx +0 -52
  56. package/src/ui/components/util.tsx +0 -3
  57. package/src/ui/util/confirm_dialog.ts +0 -53
  58. package/src/ui/util/error_view.tsx +0 -16
  59. package/src/ui/util/toast.ts +0 -14
  60. package/src/ui/util/util.ts +0 -36
  61. package/style/color_style.scss +0 -149
  62. package/style/components.scss +0 -476
  63. package/style/root.scss +0 -50
  64. package/style/type_style.scss +0 -22
@@ -1,23 +0,0 @@
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
- label: string;
11
- } | {
12
- icon: IconChild;
13
- label?: 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
- }
@@ -1,14 +0,0 @@
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;
@@ -1,8 +0,0 @@
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;
@@ -1,15 +0,0 @@
1
- import { type ApiError } from "../../service/s_api";
2
- export declare function ErrorView({ error, retry, debug, }: {
3
- error: any;
4
- retry?: () => any;
5
- debug?: boolean;
6
- }): import("preact").JSX.Element;
7
- export declare function PrettyErrorView({ apiError, retry, labels, }: {
8
- apiError: ApiError;
9
- retry?: () => any;
10
- labels?: {
11
- retry?: string;
12
- home?: string;
13
- details?: string;
14
- };
15
- }): import("preact").JSX.Element;
@@ -1,11 +0,0 @@
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;
@@ -1,19 +0,0 @@
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
- }
@@ -1,6 +0,0 @@
1
- import { type ElbeProps } from "../box";
2
- export declare function Checkbox({ value, label, onChange, ...elbe }: {
3
- value: boolean;
4
- label?: string;
5
- onChange?: ((checked: boolean) => void) | null;
6
- } & ElbeProps): import("preact").JSX.Element;
@@ -1,22 +0,0 @@
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
- }
@@ -1,8 +0,0 @@
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;
@@ -1,10 +0,0 @@
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;
@@ -1,10 +0,0 @@
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;
@@ -1,25 +0,0 @@
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
- }
@@ -1,23 +0,0 @@
1
- type HeaderParams = {
2
- title?: string;
3
- back: null | "close" | "back";
4
- actions?: any;
5
- };
6
- /**
7
- * Header is a layout component that provides a header for a page.
8
- * It is used to create a consistent header for pages.
9
- * @param back - The back button type. If null, no back button is shown. If "close", a close button is shown. If "back", a back button is shown.
10
- * @param title - The title of the page.
11
- * @param actions - The actions to show on the right side of the header.
12
- */
13
- export declare function Header({ back, title, actions }: HeaderParams): import("preact/compat").JSX.Element;
14
- /**
15
- * Scaffold is a layout component that provides a header and a content area.
16
- * It is used to create a consistent layout for pages.
17
- */
18
- export declare function Scaffold({ children, limited, gap, ...header }: {
19
- limited?: boolean;
20
- children: any;
21
- gap?: number;
22
- } & HeaderParams): import("preact/compat").JSX.Element;
23
- export {};
@@ -1,3 +0,0 @@
1
- export declare function Spinner({ padding }: {
2
- padding?: number;
3
- }): import("preact").JSX.Element;
@@ -1,33 +0,0 @@
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
- }
@@ -1,12 +0,0 @@
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;
@@ -1,3 +0,0 @@
1
- export declare function Spaced({ amount }: {
2
- amount?: number | undefined;
3
- }): import("preact").JSX.Element;
@@ -1,10 +0,0 @@
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>;
@@ -1 +0,0 @@
1
- export declare function _ElbeErr(msg: string): import("preact").JSX.Element;
@@ -1,5 +0,0 @@
1
- /**
2
- * show a toast message at the bottom of the screen
3
- * @param message the message to show
4
- */
5
- export declare function showToast(message: string): void;
@@ -1,19 +0,0 @@
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 DELETED
@@ -1,100 +0,0 @@
1
- /* BUILD CSS BY:
2
- - npm install -g sass
3
- - sass style/elbe.scss dist/elbe.css
4
- */
5
-
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:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap");
8
- @import url("https://fonts.googleapis.com/css2?family=Calistoga&display=swap");
9
- @import url("https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&display=swap");
10
-
11
- // COPY OF THE FUNCTION IN COLOR_STYLE
12
- @function inter($colorA, $colorB: #888888, $weight: 50%) {
13
- @return mix($colorA, $colorB, $weight);
14
- }
15
-
16
- $g-radius: 9px !default;
17
- $c-accent: #1a396f !default;
18
- $t-font-body: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif !default;
19
- $t-font-accent: Calistoga, $t-font-body !default;
20
-
21
- $c-modes: (
22
- primary: (
23
- back: #ffffff,
24
- front: #222222,
25
- border: #22222218,
26
- ),
27
- inverse: (
28
- back: #222222,
29
- front: #ffffff,
30
- border: #ffffff14,
31
- ),
32
- secondary: (
33
- back: inter($c-accent, #ffffff, 7%),
34
- front: #222222,
35
- border: #22222214,
36
- ),
37
- ) !default;
38
-
39
- $c-styles: (
40
- accent: (
41
- back: $c-accent,
42
- ),
43
- error: (
44
- back: #f34343,
45
- ),
46
- warning: (
47
- back: #ffbf00,
48
- front: #222222,
49
- ),
50
- success: (
51
- back: #29ac5e,
52
- ),
53
- info: (
54
- back: #2463aa,
55
- ),
56
- //TODO: Button Styles
57
- loud:
58
- (
59
- back: $c-accent,
60
- border: transparent,
61
- ),
62
- action: (
63
- back: transparent,
64
- front: $c-accent,
65
- border: transparent,
66
- ),
67
- integrated: (
68
- back: transparent,
69
- border: transparent,
70
- ),
71
- ) !default;
72
-
73
- $t-styles: (
74
- "s": 0.7rem,
75
- "m": 1rem,
76
- "l": 1.2rem,
77
- "huge": 4rem,
78
- ) !default;
79
-
80
- $t-headers: (
81
- "6": 1.1rem,
82
- "5": 1.2rem,
83
- "4": 1.4rem,
84
- "3": 1.5rem,
85
- "2": 1.8rem,
86
- "1": 2rem,
87
- ) !default;
88
-
89
- // CSS Variables
90
- :root {
91
- --g-radius: #{$g-radius};
92
- --c-accent: #{$c-accent};
93
- --t-font-body: #{$t-font-body};
94
- --t-font-accent: #{$t-font-accent};
95
- }
96
-
97
- @import "./style/root.scss";
98
- @import "./style/color_style.scss";
99
- @import "./style/type_style.scss";
100
- @import "./style/components.scss";
package/src/bit/bit.tsx DELETED
@@ -1,128 +0,0 @@
1
- import { Signal, useSignal } from "@preact/signals";
2
- import { type PreactContext, createContext } from "preact";
3
- import { useContext } from "preact/hooks";
4
- import { ErrorView } from "../ui/components/error_view";
5
- import { Spinner } from "../ui/components/spinner";
6
-
7
- export interface BitUseInterface<C, T> {
8
- signal: Signal<BitState<T>>;
9
- ctrl: C;
10
- map: <D>(m: TriMap<T, D>) => D | preact.JSX.Element;
11
- onData: (f: (d: T) => any) => any;
12
- }
13
-
14
- interface BitData<C, T> {
15
- ctrl: C;
16
- state: Signal<BitState<T>>;
17
- }
18
-
19
- export interface BitState<T> {
20
- loading?: boolean;
21
- error?: any;
22
- data?: T;
23
- }
24
-
25
- export type BitContext<T, C> = PreactContext<BitData<T, C> | null>;
26
-
27
- export interface TriMap<T, D> {
28
- onLoading?: () => D;
29
- onError?: (e: string) => D;
30
- onData?: (value: T) => D;
31
- }
32
-
33
- export interface TWParams<T> {
34
- emit: (t: T) => void;
35
- emitLoading: () => void;
36
- emitError: (e: any) => void;
37
- map: <D>(m: TriMap<T, D>) => D;
38
- signal: Signal<BitState<T>>;
39
- }
40
-
41
- export function makeBit<C, T>(name: string): BitContext<C, T> {
42
- const c = createContext<BitData<C, T> | null>(null);
43
- c.displayName = name;
44
- return c;
45
- }
46
-
47
- export function ProvideBit<I, C, T>(
48
- context: BitContext<C, T>,
49
- parameters: I,
50
- worker: (p: I, d: TWParams<T>, ctrl: C) => void,
51
- ctrl: (p: I, d: TWParams<T>) => C,
52
- children: any
53
- ) {
54
- const s = useSignal<BitState<T>>({ loading: true });
55
-
56
- const _set = (n: BitState<T>) => {
57
- try {
58
- if (JSON.stringify(n) === JSON.stringify(s.peek())) return;
59
- } catch (e) {}
60
- s.value = n;
61
- };
62
-
63
- const emit = (data: T) => _set({ data });
64
- const emitLoading = () => _set({ loading: true });
65
- const emitError = (error: any) => {
66
- console.warn(`BIT: ${context.displayName} emitted ERROR`, error);
67
- return _set({ error });
68
- };
69
-
70
- function map<D>(m: TriMap<T, D>) {
71
- const st = s.value;
72
- if (st.loading) return m.onLoading!();
73
- if (st.error) return m.onError!(st.error);
74
- return m.onData!(st.data ?? (null as any));
75
- }
76
-
77
- const c = ctrl(parameters, { emit, emitLoading, emitError, map, signal: s });
78
- worker(parameters, { emit, emitLoading, emitError, map, signal: s }, c);
79
-
80
- return (
81
- <context.Provider value={{ ctrl: c, state: s }}>
82
- {children}
83
- </context.Provider>
84
- );
85
- }
86
-
87
- export function useBit<C, T>(context: BitContext<C, T>): BitUseInterface<C, T> {
88
- try {
89
- const { ctrl, state } = useContext(context)!;
90
- const v = state.value;
91
-
92
- function map<D>(m: TriMap<T, D>) {
93
- if (v.loading) return (m.onLoading || (() => <Spinner />))();
94
- if (v.error)
95
- return (
96
- m.onError ||
97
- ((e) => <ErrorView error={e} retry={(ctrl as any).reload ?? null} />)
98
- )(v.error);
99
- return m.onData!(v.data ?? (null as any));
100
- }
101
-
102
- return {
103
- signal: state,
104
- ctrl,
105
- map,
106
- /**
107
- * this is a quality of life function that allows
108
- * you to chain the map function with the onData function
109
- * @param f the builder function
110
- * @returns the built component
111
- */
112
- onData: (f: (d: T) => void) => map({ onData: f }),
113
- };
114
- } catch (e) {
115
- const err = `BIT ERROR: NO ${context.displayName} PROVIDED`;
116
- console.error(err, e);
117
- return {
118
- map: (_: any) => <div>{err}</div>,
119
- ctrl: null as any,
120
- signal: null as any,
121
- onData: () => <div>{err}</div>,
122
- };
123
- }
124
- }
125
-
126
- function BitSpinner({ name }: { name: string }) {
127
- return <Spinner />;
128
- }
@@ -1,112 +0,0 @@
1
- import { useEffect } from "preact/hooks";
2
- import type { JSX } from "preact/jsx-runtime";
3
- import type { BitContext, BitUseInterface, TWParams } from "./bit";
4
- import { makeBit as mb, ProvideBit, useBit } from "./bit";
5
-
6
- abstract class BitControl<I, DT> {
7
- p: I;
8
- bit: TWParams<DT>;
9
-
10
- constructor(p: I, bit: TWParams<DT>) {
11
- this.bit = bit;
12
- this.p = p;
13
- }
14
-
15
- act(fn: (b: DT) => Promise<void>) {
16
- this.bit.map({
17
- onData: async (d) => {
18
- try {
19
- await fn(d);
20
- } catch (e: any) {
21
- if (e && e.code && e.message)
22
- console.error(`[BitERROR] act: ${e.code} (${e.message})`);
23
- else console.error("[BitERROR] act: ", e);
24
- }
25
- },
26
- });
27
- }
28
-
29
- /**
30
- * Clean up resources. This is called once
31
- * the element is removed from the DOM.
32
- */
33
- dispose() {}
34
- }
35
-
36
- export abstract class WorkerControl<I, DT> extends BitControl<I, DT> {
37
- reload: (() => Promise<void>) | null = null;
38
-
39
- abstract worker(): Promise<DT>;
40
- }
41
-
42
- export abstract class StreamControl<I, DT, Stream> extends BitControl<I, DT> {
43
- protected stream: Stream | null = null;
44
- abstract listen(): Stream;
45
-
46
- dispose(): void {
47
- if (this.stream) this.disposeStream(this.stream);
48
- }
49
- abstract disposeStream(stream: Stream): void;
50
- }
51
-
52
- function make<I, DT, C extends BitControl<I, DT>>(
53
- name: string
54
- ): BitContext<C, DT> {
55
- return mb<C, DT>(name);
56
- }
57
-
58
- function use<I, DT, C extends BitControl<I, DT>>(
59
- b: BitContext<C, DT>
60
- ): BitUseInterface<C, DT> {
61
- return useBit<C, DT>(b);
62
- }
63
-
64
- export function CtrlBit<I, DT, C extends BitControl<I, DT>>(
65
- ctrl: (p: I, d: TWParams<DT>) => C,
66
- name?: string
67
- ): {
68
- Provide: (props: I & { children: React.ReactNode }) => JSX.Element;
69
- use: () => BitUseInterface<C, DT>;
70
- } {
71
- const context = make<I, DT, C>((name || "Unknown") + "Bit");
72
-
73
- function Provide({ children, ...p }: { children: React.ReactNode } & I) {
74
- return ProvideBit(
75
- context,
76
- p,
77
- async (p, b, c) => {
78
- b.emitLoading();
79
-
80
- try {
81
- if (c instanceof WorkerControl) {
82
- if (c.reload) await c.reload();
83
- }
84
- if (c instanceof StreamControl) {
85
- (c as any).stream = c.listen();
86
- }
87
- } catch (e) {
88
- b.emitError(e);
89
- }
90
- },
91
-
92
- (p, b) => {
93
- const c = ctrl(p as I, b);
94
- // clean up on unmount
95
- useEffect(() => () => c.dispose(), []);
96
- if (c instanceof WorkerControl) {
97
- c.reload = async () => {
98
- b.emitLoading();
99
- try {
100
- b.emit(await c.worker());
101
- } catch (e) {
102
- b.emitError(e);
103
- }
104
- };
105
- }
106
- return c;
107
- },
108
- children
109
- );
110
- }
111
- return { Provide: Provide, use: () => use<I, DT, C>(context) };
112
- }