southpaw 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -0
- package/api/client.ts +83 -0
- package/api/helpers/fs.ts +98 -0
- package/api/helpers/stream.ts +6 -0
- package/api/index.ts +50 -0
- package/api/server.ts +566 -0
- package/constants/fonts.ts +1583 -0
- package/constants/icons.ts +2124 -0
- package/constants/langs.ts +2592 -0
- package/constants/ssr-loading.tsx +17 -0
- package/contexts/dev.tsx +124 -0
- package/hooks/useDebounceCb.ts +21 -0
- package/modules/app.tsx +102 -0
- package/modules/behaviors.ts +161 -0
- package/modules/component.tsx +483 -0
- package/modules/config/index.ts +8 -0
- package/modules/database.ts +25 -0
- package/modules/document.tsx +23 -0
- package/modules/error.tsx +16 -0
- package/modules/page/autozoom.tsx +92 -0
- package/modules/page/browser.tsx +166 -0
- package/modules/page/index.tsx +327 -0
- package/modules/page/insert-modal.tsx +225 -0
- package/modules/page/inspect/index.tsx +237 -0
- package/modules/page/inspect/wrapper.tsx +88 -0
- package/modules/page/knobs/action.tsx +58 -0
- package/modules/page/knobs/color.tsx +78 -0
- package/modules/page/knobs/helpers.ts +71 -0
- package/modules/page/knobs/icon.tsx +85 -0
- package/modules/page/knobs/linker.tsx +188 -0
- package/modules/page/knobs/list-json.tsx +149 -0
- package/modules/page/knobs/list-text.tsx +129 -0
- package/modules/page/knobs/number.tsx +84 -0
- package/modules/page/knobs/segmented.tsx +81 -0
- package/modules/page/knobs/select.tsx +89 -0
- package/modules/page/knobs/size.tsx +106 -0
- package/modules/page/knobs/switch.tsx +75 -0
- package/modules/page/knobs/text.tsx +93 -0
- package/modules/page/left-tabs.tsx +36 -0
- package/modules/page/right-tabs.tsx +31 -0
- package/modules/page/seo.tsx +69 -0
- package/modules/page/tree.tsx +860 -0
- package/modules/state.ts +787 -0
- package/modules/store.ts +37 -0
- package/modules/theme.ts +105 -0
- package/modules/translations.ts +15 -0
- package/package.json +68 -0
- package/scripts/bin.js +607 -0
- package/scripts/test.js +145 -0
- package/themes/base.tsx +8962 -0
- package/themes/index.ts +4 -0
- package/themes/m2.ts +39 -0
- package/themes/newspaper.ts +39 -0
- package/types/api.ts +57 -0
- package/types/fiber_node.ts +69 -0
- package/types/react_element.ts +14 -0
- package/ui/accordion.tsx +70 -0
- package/ui/actionicon.tsx +41 -0
- package/ui/affix.tsx +14 -0
- package/ui/alert.tsx +37 -0
- package/ui/anchor.tsx +52 -0
- package/ui/arrow.tsx +116 -0
- package/ui/aspectratio.tsx +21 -0
- package/ui/autocomplete.tsx +34 -0
- package/ui/avatar.tsx +36 -0
- package/ui/backgroundimage.tsx +16 -0
- package/ui/badge.tsx +28 -0
- package/ui/blockquote.tsx +15 -0
- package/ui/blocks/faq.tsx +145 -0
- package/ui/blocks/features.tsx +167 -0
- package/ui/blocks/footer.tsx +182 -0
- package/ui/blocks/herobanner.tsx +391 -0
- package/ui/blocks/index.ts +44 -0
- package/ui/blocks/leftnav.tsx +141 -0
- package/ui/blocks/pricing.tsx +210 -0
- package/ui/blocks/testimonials.tsx +149 -0
- package/ui/blocks/uidocs.tsx +1429 -0
- package/ui/box.tsx +27 -0
- package/ui/breadcrumbs.tsx +33 -0
- package/ui/burger.tsx +23 -0
- package/ui/button.tsx +85 -0
- package/ui/card.tsx +28 -0
- package/ui/center.tsx +26 -0
- package/ui/checkbox.tsx +35 -0
- package/ui/chip.tsx +32 -0
- package/ui/closebutton.tsx +15 -0
- package/ui/code.tsx +104 -0
- package/ui/collapse.tsx +16 -0
- package/ui/colorinput.tsx +32 -0
- package/ui/colorpicker.tsx +26 -0
- package/ui/colorswatch.tsx +17 -0
- package/ui/combobox.tsx +80 -0
- package/ui/container.tsx +27 -0
- package/ui/dialog.tsx +15 -0
- package/ui/divider.tsx +58 -0
- package/ui/drawer.tsx +28 -0
- package/ui/fieldset.tsx +15 -0
- package/ui/filebutton.tsx +23 -0
- package/ui/fileinput.tsx +36 -0
- package/ui/flex.tsx +139 -0
- package/ui/focustrap.tsx +15 -0
- package/ui/form.tsx +26 -0
- package/ui/grid.tsx +69 -0
- package/ui/highlight.tsx +15 -0
- package/ui/hoverable.tsx +66 -0
- package/ui/hovercard.tsx +45 -0
- package/ui/icon.tsx +76 -0
- package/ui/image.tsx +32 -0
- package/ui/index.ts +1355 -0
- package/ui/indicator.tsx +42 -0
- package/ui/infobox.tsx +200 -0
- package/ui/input.tsx +18 -0
- package/ui/inviewport.tsx +23 -0
- package/ui/jsoninput.tsx +35 -0
- package/ui/kbd.tsx +20 -0
- package/ui/list.tsx +33 -0
- package/ui/loader.tsx +26 -0
- package/ui/loadingoverlay.tsx +22 -0
- package/ui/mark.tsx +15 -0
- package/ui/menu.tsx +89 -0
- package/ui/modal.tsx +27 -0
- package/ui/multiselect.tsx +42 -0
- package/ui/nativeselect.tsx +17 -0
- package/ui/navlink.tsx +40 -0
- package/ui/notification.tsx +25 -0
- package/ui/numberformatter.tsx +15 -0
- package/ui/numberinput.tsx +37 -0
- package/ui/overlay.tsx +15 -0
- package/ui/pagination.tsx +21 -0
- package/ui/paper.tsx +33 -0
- package/ui/passwordinput.tsx +36 -0
- package/ui/pill.tsx +17 -0
- package/ui/pillsinput.tsx +37 -0
- package/ui/pininput.tsx +30 -0
- package/ui/popover.tsx +43 -0
- package/ui/portal.tsx +15 -0
- package/ui/progress.tsx +49 -0
- package/ui/props.ts +91 -0
- package/ui/propsDef.ts +38 -0
- package/ui/radio.tsx +30 -0
- package/ui/rating.tsx +25 -0
- package/ui/ringprogress.tsx +17 -0
- package/ui/scrollarea.tsx +27 -0
- package/ui/segmentedcontrol.tsx +38 -0
- package/ui/select.tsx +43 -0
- package/ui/simplegrid.tsx +23 -0
- package/ui/skeleton.tsx +15 -0
- package/ui/slider.tsx +31 -0
- package/ui/space.tsx +19 -0
- package/ui/spoiler.tsx +23 -0
- package/ui/stepper.tsx +63 -0
- package/ui/switch.tsx +29 -0
- package/ui/table.tsx +93 -0
- package/ui/tabs.tsx +80 -0
- package/ui/tagsinput.tsx +19 -0
- package/ui/terminal.tsx +44 -0
- package/ui/text.tsx +168 -0
- package/ui/textarea.tsx +36 -0
- package/ui/textinput.tsx +34 -0
- package/ui/timeline.tsx +30 -0
- package/ui/title.tsx +42 -0
- package/ui/tooltip.tsx +32 -0
- package/ui/transition.tsx +21 -0
- package/ui/tree.tsx +42 -0
- package/ui/typographystylesprovider.tsx +20 -0
- package/ui/unstyledbutton.tsx +18 -0
- package/ui/video.tsx +16 -0
- package/ui/visuallyhidden.tsx +15 -0
- package/utils/index.ts +76 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Alert } from "@mantine/core";
|
|
2
|
+
import { DynamicOptionsLoadingProps } from "next/dynamic";
|
|
3
|
+
|
|
4
|
+
export const loading: (
|
|
5
|
+
loadingProps: DynamicOptionsLoadingProps
|
|
6
|
+
) => React.ReactNode = (loadingProps) => {
|
|
7
|
+
if (loadingProps.error) {
|
|
8
|
+
return (
|
|
9
|
+
<Alert variant="filled" color="red" title="Loading error">
|
|
10
|
+
{loadingProps.error.message}
|
|
11
|
+
</Alert>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
// TODO: figure out a way to define width and height
|
|
15
|
+
// return <Skeleton visible miw={500} mih={50} />;
|
|
16
|
+
return null;
|
|
17
|
+
};
|
package/contexts/dev.tsx
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Dispatch,
|
|
3
|
+
Context as ContextType,
|
|
4
|
+
createContext,
|
|
5
|
+
FC,
|
|
6
|
+
PropsWithChildren,
|
|
7
|
+
useContext,
|
|
8
|
+
useReducer,
|
|
9
|
+
} from "react";
|
|
10
|
+
import { TreeNodeData } from "@mantine/core";
|
|
11
|
+
|
|
12
|
+
export type TNode = TreeNodeData;
|
|
13
|
+
const initialState = {
|
|
14
|
+
modals: {
|
|
15
|
+
insert: false,
|
|
16
|
+
},
|
|
17
|
+
tree: {
|
|
18
|
+
selectedNode: null as TNode | null,
|
|
19
|
+
menuNode: {
|
|
20
|
+
insertMode: "within",
|
|
21
|
+
node: {},
|
|
22
|
+
} as {
|
|
23
|
+
insertMode: "within" | "before" | "after";
|
|
24
|
+
node: TNode;
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type TActions = {
|
|
30
|
+
TREE_SELECT_NODE: {
|
|
31
|
+
type: "TREE_SELECT_NODE";
|
|
32
|
+
args: { selectedNode: typeof initialState.tree.selectedNode };
|
|
33
|
+
};
|
|
34
|
+
TREE_SET_MENU_NODE: {
|
|
35
|
+
type: "TREE_SET_MENU_NODE";
|
|
36
|
+
args: typeof initialState.tree.menuNode;
|
|
37
|
+
};
|
|
38
|
+
MODALS_OPEN: {
|
|
39
|
+
type: "MODALS_OPEN";
|
|
40
|
+
args: { name: keyof (typeof initialState)["modals"] };
|
|
41
|
+
};
|
|
42
|
+
MODALS_CLOSE: {
|
|
43
|
+
type: "MODALS_CLOSE";
|
|
44
|
+
args: { name: keyof (typeof initialState)["modals"] };
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
function reducer<T extends keyof TActions>(
|
|
48
|
+
state: typeof initialState,
|
|
49
|
+
action: TActions[T]
|
|
50
|
+
) {
|
|
51
|
+
switch (action.type) {
|
|
52
|
+
case "TREE_SELECT_NODE": {
|
|
53
|
+
{
|
|
54
|
+
return {
|
|
55
|
+
...state,
|
|
56
|
+
tree: {
|
|
57
|
+
...state.tree,
|
|
58
|
+
selectedNode: action.args.selectedNode,
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
case "TREE_SET_MENU_NODE": {
|
|
64
|
+
{
|
|
65
|
+
return {
|
|
66
|
+
...state,
|
|
67
|
+
tree: {
|
|
68
|
+
...state.tree,
|
|
69
|
+
menuNode: action.args,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
case "MODALS_OPEN": {
|
|
75
|
+
{
|
|
76
|
+
return {
|
|
77
|
+
...state,
|
|
78
|
+
modals: {
|
|
79
|
+
...state.modals,
|
|
80
|
+
[action.args.name]: true,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
case "MODALS_CLOSE": {
|
|
86
|
+
{
|
|
87
|
+
return {
|
|
88
|
+
...state,
|
|
89
|
+
modals: {
|
|
90
|
+
...state.modals,
|
|
91
|
+
[action.args.name]: false,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
default:
|
|
98
|
+
throw Error("Unknown action");
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
type TContextType = {
|
|
103
|
+
state: typeof initialState;
|
|
104
|
+
dispatch: Dispatch<TActions[keyof TActions]>;
|
|
105
|
+
};
|
|
106
|
+
const Context: ContextType<TContextType> = createContext({} as TContextType);
|
|
107
|
+
|
|
108
|
+
export const useContextDev = () => {
|
|
109
|
+
return useContext(Context);
|
|
110
|
+
};
|
|
111
|
+
export const ContextProviderDev: FC<PropsWithChildren> = ({ children }) => {
|
|
112
|
+
const [state, dispatch] = useReducer(reducer, initialState);
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<Context.Provider
|
|
116
|
+
value={{
|
|
117
|
+
state,
|
|
118
|
+
dispatch,
|
|
119
|
+
}}
|
|
120
|
+
>
|
|
121
|
+
{children}
|
|
122
|
+
</Context.Provider>
|
|
123
|
+
);
|
|
124
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useRef, useCallback } from "react";
|
|
2
|
+
|
|
3
|
+
export function useDebounceCb<T extends (...args: unknown[]) => void>(
|
|
4
|
+
callback: T,
|
|
5
|
+
delay: number
|
|
6
|
+
) {
|
|
7
|
+
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
8
|
+
|
|
9
|
+
const debouncedCallback = useCallback(
|
|
10
|
+
(...args: Parameters<T>) => {
|
|
11
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
12
|
+
|
|
13
|
+
timerRef.current = setTimeout(() => {
|
|
14
|
+
callback(...args);
|
|
15
|
+
}, delay);
|
|
16
|
+
},
|
|
17
|
+
[callback, delay]
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
return debouncedCallback;
|
|
21
|
+
}
|
package/modules/app.tsx
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { AppProps } from "next/app";
|
|
2
|
+
import { useState, useEffect } from "react";
|
|
3
|
+
import { MantineProvider, MantineTheme } from "@mantine/core";
|
|
4
|
+
import { ModalsProvider } from "@mantine/modals";
|
|
5
|
+
|
|
6
|
+
import { m2 } from "../themes";
|
|
7
|
+
import { create_translations } from "./translations";
|
|
8
|
+
import { ThemeBase } from "../themes/base";
|
|
9
|
+
import { ContextProviderDev } from "southpaw/contexts/dev";
|
|
10
|
+
import { useRouter } from "next/router";
|
|
11
|
+
import { Components } from "@/components";
|
|
12
|
+
|
|
13
|
+
type Params = {
|
|
14
|
+
name: string;
|
|
15
|
+
description: string;
|
|
16
|
+
version: string;
|
|
17
|
+
behaviors: Behaviors;
|
|
18
|
+
components: typeof Components;
|
|
19
|
+
theme?: MantineTheme;
|
|
20
|
+
} & Partial<{
|
|
21
|
+
translations: Record<string, ReturnType<typeof create_translations>>;
|
|
22
|
+
}>;
|
|
23
|
+
|
|
24
|
+
export const create_app = (params: Params) => {
|
|
25
|
+
const behaviors = params.behaviors;
|
|
26
|
+
const translations = params.translations!;
|
|
27
|
+
const theme = params.theme || m2;
|
|
28
|
+
// const components = params.components;
|
|
29
|
+
// globalThis.Components = components;
|
|
30
|
+
|
|
31
|
+
const Fn = ({ Component, pageProps }: AppProps) => {
|
|
32
|
+
const router = useRouter();
|
|
33
|
+
const [colorScheme, setColorScheme] = useState<"dark" | "light">("light");
|
|
34
|
+
const [lang, setLang] = useState<(typeof translations)[string]["lang"]>(
|
|
35
|
+
translations[Object.keys(translations)[0]].lang,
|
|
36
|
+
);
|
|
37
|
+
const isIframe = globalThis.window && window.self !== window.top;
|
|
38
|
+
const isTest = navigator.webdriver === true;
|
|
39
|
+
const isDev =
|
|
40
|
+
!Object.keys(router.query).includes("isPreview") &&
|
|
41
|
+
process.env.NODE_ENV === "development" &&
|
|
42
|
+
!isTest;
|
|
43
|
+
const setTransLang = (l: typeof lang) => {
|
|
44
|
+
setLang(l);
|
|
45
|
+
};
|
|
46
|
+
const trans = Object.entries(translations).reduce(
|
|
47
|
+
(acc, [key, value]) => {
|
|
48
|
+
const fn = (name: keyof Translations, ...args: unknown[]) => {
|
|
49
|
+
const fn = value.translations[name];
|
|
50
|
+
const result = fn(...args)[lang];
|
|
51
|
+
return result;
|
|
52
|
+
};
|
|
53
|
+
(acc as Record<string, typeof fn>)[key] = fn;
|
|
54
|
+
return acc;
|
|
55
|
+
},
|
|
56
|
+
{} as Record<
|
|
57
|
+
string,
|
|
58
|
+
(name: keyof Translations, ...args: unknown[]) => string
|
|
59
|
+
>,
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const loadFonts = async () => {
|
|
63
|
+
const WebFont = await import("webfontloader");
|
|
64
|
+
WebFont.load({
|
|
65
|
+
google: {
|
|
66
|
+
families: [
|
|
67
|
+
`${theme.fontFamily}:100,200,300,400,500,600,700,800,900`,
|
|
68
|
+
theme.fontFamilyMonospace,
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
loadFonts();
|
|
76
|
+
if (isDev && !isIframe) {
|
|
77
|
+
}
|
|
78
|
+
}, []);
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<ContextProviderDev>
|
|
82
|
+
<ThemeBase />
|
|
83
|
+
<MantineProvider theme={theme} forceColorScheme={colorScheme}>
|
|
84
|
+
<ModalsProvider>
|
|
85
|
+
{/* {!isIframe && <LoadingOverlay visible={!ragReady} />} */}
|
|
86
|
+
<Component
|
|
87
|
+
{...pageProps}
|
|
88
|
+
behaviors={behaviors}
|
|
89
|
+
trans={trans}
|
|
90
|
+
lang={lang}
|
|
91
|
+
setTransLang={setTransLang}
|
|
92
|
+
colorScheme={colorScheme}
|
|
93
|
+
setColorScheme={setColorScheme}
|
|
94
|
+
/>
|
|
95
|
+
</ModalsProvider>
|
|
96
|
+
</MantineProvider>
|
|
97
|
+
</ContextProviderDev>
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
Fn.displayName = params.name;
|
|
101
|
+
return Fn;
|
|
102
|
+
};
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// TODO: add types for the store and actions
|
|
2
|
+
// NOTE: types are intentionally conservative here to avoid breaking existing apps.
|
|
3
|
+
import ObservableSlim from "./state";
|
|
4
|
+
|
|
5
|
+
const PAGE_UPDATE_EVENT = "--page-update";
|
|
6
|
+
|
|
7
|
+
type StoreType<
|
|
8
|
+
STATE extends Record<string, any>,
|
|
9
|
+
ACTIONS extends Record<string, any>,
|
|
10
|
+
> = {
|
|
11
|
+
state: STATE;
|
|
12
|
+
actions: ACTIONS;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
type BoundActionsType<STATE extends Record<string, any>> = Record<
|
|
16
|
+
string,
|
|
17
|
+
(this: { state: STATE }, ...args: any[]) => Promise<void>
|
|
18
|
+
>;
|
|
19
|
+
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
21
|
+
type DefinitionsType<STORE extends StoreType<{}, {}>> = {
|
|
22
|
+
when: Record<
|
|
23
|
+
string,
|
|
24
|
+
(
|
|
25
|
+
this: {
|
|
26
|
+
store: {
|
|
27
|
+
state: STORE["state"];
|
|
28
|
+
actions: {
|
|
29
|
+
[ACTION_NAME in keyof STORE["actions"]]: OmitThisParameter<
|
|
30
|
+
STORE["actions"][ACTION_NAME]
|
|
31
|
+
>;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
...args: any[]
|
|
36
|
+
) => Promise<void>
|
|
37
|
+
>;
|
|
38
|
+
then: Record<string, (this: { store: STORE }, ...args: any[]) => any>;
|
|
39
|
+
given: Record<
|
|
40
|
+
string,
|
|
41
|
+
(this: { store: STORE }, ...args: any[]) => Promise<void>
|
|
42
|
+
>;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const create_behaviors = <
|
|
46
|
+
STATE extends Record<string, any>,
|
|
47
|
+
ACTIONS extends BoundActionsType<STATE>,
|
|
48
|
+
STORE extends {
|
|
49
|
+
state: STATE;
|
|
50
|
+
actions: ACTIONS;
|
|
51
|
+
},
|
|
52
|
+
DEFINITIONS extends DefinitionsType<STORE>,
|
|
53
|
+
>(
|
|
54
|
+
_store: StoreType<STATE, ACTIONS>,
|
|
55
|
+
definitions: DEFINITIONS,
|
|
56
|
+
) => {
|
|
57
|
+
const $$typeof = Symbol("southpaw.behaviors");
|
|
58
|
+
const state: STORE["state"] = ObservableSlim.create(
|
|
59
|
+
{ ..._store.state, __isProxy: false, __getTarget: _store.state },
|
|
60
|
+
false,
|
|
61
|
+
function (changes: any) {
|
|
62
|
+
const event = new CustomEvent(PAGE_UPDATE_EVENT, { detail: changes });
|
|
63
|
+
document.dispatchEvent(event);
|
|
64
|
+
},
|
|
65
|
+
) as unknown as STORE["state"];
|
|
66
|
+
const actions = Object.keys(_store.actions).reduce((acc, name) => {
|
|
67
|
+
(acc as Record<string, any>)[name] = (
|
|
68
|
+
_store.actions[
|
|
69
|
+
name
|
|
70
|
+
] as (typeof _store.actions)[keyof typeof _store.actions]
|
|
71
|
+
).bind({ state }) as OmitThisParameter<
|
|
72
|
+
(typeof _store.actions)[keyof typeof _store.actions]
|
|
73
|
+
>;
|
|
74
|
+
return acc;
|
|
75
|
+
}, {} as ACTIONS);
|
|
76
|
+
const store = {
|
|
77
|
+
state,
|
|
78
|
+
actions,
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
$$typeof,
|
|
82
|
+
definitions,
|
|
83
|
+
given<NAME extends keyof DEFINITIONS["given"]>(
|
|
84
|
+
name: NAME,
|
|
85
|
+
...args: Parameters<DEFINITIONS["given"][NAME]>
|
|
86
|
+
) {
|
|
87
|
+
const fn = (definitions.given as DEFINITIONS["given"])[name];
|
|
88
|
+
const condition = fn.bind({ store: store as STORE })(...args);
|
|
89
|
+
return condition;
|
|
90
|
+
},
|
|
91
|
+
when<NAME extends keyof DEFINITIONS["when"]>(name: NAME) {
|
|
92
|
+
const fn = (definitions.when as DEFINITIONS["when"])[name];
|
|
93
|
+
const cb = (...args: Parameters<DEFINITIONS["when"][NAME]>) =>
|
|
94
|
+
fn.bind({
|
|
95
|
+
store: {
|
|
96
|
+
state: store.state,
|
|
97
|
+
actions: actions as {
|
|
98
|
+
[ACTION_NAME in keyof STORE["actions"]]: OmitThisParameter<
|
|
99
|
+
STORE["actions"][ACTION_NAME]
|
|
100
|
+
>;
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
})(...args);
|
|
104
|
+
return cb;
|
|
105
|
+
},
|
|
106
|
+
then<NAME extends keyof DEFINITIONS["then"]>(
|
|
107
|
+
name: NAME,
|
|
108
|
+
...args: Parameters<OmitThisParameter<DEFINITIONS["then"][NAME]>>
|
|
109
|
+
): {
|
|
110
|
+
get: () => ReturnType<DEFINITIONS["then"][NAME]>;
|
|
111
|
+
ifEqual: (value: any) => boolean;
|
|
112
|
+
shouldEqual: (
|
|
113
|
+
value: ReturnType<DEFINITIONS["then"][NAME]>,
|
|
114
|
+
) => Promise<string>;
|
|
115
|
+
} {
|
|
116
|
+
const fn = (definitions.then as DEFINITIONS["then"])[name];
|
|
117
|
+
const value = fn.bind({ store: store as STORE })(...args);
|
|
118
|
+
return {
|
|
119
|
+
get() {
|
|
120
|
+
return value as ReturnType<DEFINITIONS["then"][NAME]>;
|
|
121
|
+
},
|
|
122
|
+
ifEqual(equals: any) {
|
|
123
|
+
const condition = value === equals;
|
|
124
|
+
return condition;
|
|
125
|
+
},
|
|
126
|
+
shouldEqual(equals: any) {
|
|
127
|
+
const condition = value === equals;
|
|
128
|
+
if (condition) {
|
|
129
|
+
return Promise.resolve("Test passed !");
|
|
130
|
+
}
|
|
131
|
+
throw new Error(
|
|
132
|
+
`Expected "${String(name)}" to equal ${equals}, received ${value}`,
|
|
133
|
+
);
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
},
|
|
137
|
+
do<NAME extends keyof DEFINITIONS["when"]>(name: NAME) {
|
|
138
|
+
const fn = (definitions.when as DEFINITIONS["when"])[name];
|
|
139
|
+
const cb = (...args: Parameters<DEFINITIONS["when"][NAME]>) =>
|
|
140
|
+
fn.bind({
|
|
141
|
+
store: {
|
|
142
|
+
state: store.state,
|
|
143
|
+
actions: actions as {
|
|
144
|
+
[ACTION_NAME in keyof STORE["actions"]]: OmitThisParameter<
|
|
145
|
+
STORE["actions"][ACTION_NAME]
|
|
146
|
+
>;
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
})(...args);
|
|
150
|
+
return cb;
|
|
151
|
+
},
|
|
152
|
+
get<NAME extends keyof DEFINITIONS["then"]>(
|
|
153
|
+
name: NAME,
|
|
154
|
+
...args: Parameters<OmitThisParameter<DEFINITIONS["then"][NAME]>>
|
|
155
|
+
): ReturnType<DEFINITIONS["then"][NAME]> {
|
|
156
|
+
const fn = (definitions.then as DEFINITIONS["then"])[name];
|
|
157
|
+
const value = fn.bind({ store: store as STORE })(...args);
|
|
158
|
+
return value as ReturnType<DEFINITIONS["then"][NAME]>;
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
};
|