create-warlock 5.40.0 → 5.41.0
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/CHANGELOG.md +14 -0
- package/esm/commands/create-new-app/index.mjs +12 -7
- package/esm/commands/create-new-app/index.mjs.map +1 -1
- package/esm/commands/create-new-app/types.d.mts +2 -0
- package/esm/commands/create-warlock-app/index.mjs +5 -2
- package/esm/commands/create-warlock-app/index.mjs.map +1 -1
- package/esm/features/features-map.mjs +6 -0
- package/esm/features/features-map.mjs.map +1 -1
- package/esm/features/ui-kit.mjs +39 -0
- package/esm/features/ui-kit.mjs.map +1 -0
- package/esm/flags/definitions.mjs +5 -0
- package/esm/flags/definitions.mjs.map +1 -1
- package/esm/flags/seed-from-flags.mjs +7 -2
- package/esm/flags/seed-from-flags.mjs.map +1 -1
- package/esm/helpers/app.mjs +8 -2
- package/esm/helpers/app.mjs.map +1 -1
- package/esm/index.mjs +5 -1
- package/esm/index.mjs.map +1 -1
- package/esm/prompts/ask-stack.mjs +5 -0
- package/esm/prompts/ask-stack.mjs.map +1 -1
- package/esm/prompts/ask-ui-kit.mjs +27 -0
- package/esm/prompts/ask-ui-kit.mjs.map +1 -0
- package/llms-full.txt +6 -1
- package/package.json +2 -2
- package/skills/SKILL.md +6 -1
- package/templates/design-system/src/web/design-system/components/radio-input.tsx +2 -1
- package/templates/design-system/src/web/design-system/hooks/use-calendar-day-button.ts +3 -1
- package/templates/design-system/src/web/design-system/hooks/use-control.ts +3 -2
- package/templates/design-system/src/web/design-system/hooks/use-date-control.ts +14 -5
- package/templates/design-system/src/web/design-system/hooks/use-file-control.ts +3 -1
- package/templates/design-system/src/web/design-system/hooks/use-select-control.ts +11 -4
- package/templates/design-system-mantine/SOURCES.md +23 -0
- package/templates/design-system-mantine/package.json +16 -0
- package/templates/design-system-mantine/src/web/design-system/components/checkbox-input.tsx +19 -0
- package/templates/design-system-mantine/src/web/design-system/components/date-picker-input.tsx +22 -0
- package/templates/design-system-mantine/src/web/design-system/components/date-time-picker-input.tsx +32 -0
- package/templates/design-system-mantine/src/web/design-system/components/email-input.tsx +21 -0
- package/templates/design-system-mantine/src/web/design-system/components/field-frame.tsx +65 -0
- package/templates/design-system-mantine/src/web/design-system/components/file-input.tsx +32 -0
- package/templates/design-system-mantine/src/web/design-system/components/multi-select-input.tsx +28 -0
- package/templates/design-system-mantine/src/web/design-system/components/paginated-table.tsx +94 -0
- package/templates/design-system-mantine/src/web/design-system/components/password-input.tsx +20 -0
- package/templates/design-system-mantine/src/web/design-system/components/radio-input.tsx +34 -0
- package/templates/design-system-mantine/src/web/design-system/components/select-input.tsx +24 -0
- package/templates/design-system-mantine/src/web/design-system/components/submit-button.tsx +24 -0
- package/templates/design-system-mantine/src/web/design-system/components/switch-input.tsx +19 -0
- package/templates/design-system-mantine/src/web/design-system/components/text-input.tsx +21 -0
- package/templates/design-system-mantine/src/web/design-system/components/textarea-input.tsx +21 -0
- package/templates/design-system-mantine/src/web/design-system/components/time-picker-input.tsx +19 -0
- package/templates/design-system-mantine/src/web/design-system/confirm.ts +40 -0
- package/templates/design-system-mantine/src/web/design-system/hooks/use-control.ts +30 -0
- package/templates/design-system-mantine/src/web/design-system/hooks/use-date-control.ts +51 -0
- package/templates/design-system-mantine/src/web/design-system/hooks/use-file-control.ts +26 -0
- package/templates/design-system-mantine/src/web/design-system/hooks/use-select-control.ts +85 -0
- package/templates/design-system-mantine/src/web/design-system/hooks/use-submit-control.ts +13 -0
- package/templates/design-system-mantine/src/web/design-system/mantine-theme.ts +32 -0
- package/templates/design-system-mantine/src/web/design-system/notify.ts +72 -0
- package/templates/design-system-mantine/src/web/design-system/provider.tsx +28 -0
- package/templates/design-system-mantine/src/web/design-system/types/control-props.ts +46 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useSubmitButton } from "@mongez/react-form";
|
|
2
|
+
import { useControl } from "./use-control";
|
|
3
|
+
import type { ControlProps } from "../types/control-props";
|
|
4
|
+
|
|
5
|
+
export function useSubmitControl(props: ControlProps) {
|
|
6
|
+
const field = useControl(props, "submit");
|
|
7
|
+
const submit = useSubmitButton();
|
|
8
|
+
return {
|
|
9
|
+
...field,
|
|
10
|
+
disabled: field.disabled || submit.disabled || submit.isSubmitting,
|
|
11
|
+
isSubmitting: submit.isSubmitting,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { createTheme, type MantineColorScheme } from "@mantine/core";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The design tokens of this app. Edit this file; everything Mantine renders
|
|
5
|
+
* reads it through `DesignSystemProvider`.
|
|
6
|
+
*
|
|
7
|
+
* `primaryColor` takes any key of Mantine's palette (`blue`, `violet`, `teal`
|
|
8
|
+
* and so on) or a custom palette you add under `colors`.
|
|
9
|
+
*/
|
|
10
|
+
export const theme = createTheme({
|
|
11
|
+
primaryColor: "blue",
|
|
12
|
+
defaultRadius: "md",
|
|
13
|
+
fontFamily: 'system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
14
|
+
fontFamilyMonospace: 'ui-monospace, "Cascadia Code", Consolas, "Liberation Mono", monospace',
|
|
15
|
+
headings: {
|
|
16
|
+
fontFamily: 'system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
17
|
+
},
|
|
18
|
+
spacing: {
|
|
19
|
+
xs: "0.625rem",
|
|
20
|
+
sm: "0.75rem",
|
|
21
|
+
md: "1rem",
|
|
22
|
+
lg: "1.25rem",
|
|
23
|
+
xl: "2rem",
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* `auto` follows the visitor's system preference. The same value feeds the
|
|
29
|
+
* `ColorSchemeScript` in the root and the provider, so the first paint and the
|
|
30
|
+
* hydrated page agree.
|
|
31
|
+
*/
|
|
32
|
+
export const defaultColorScheme: MantineColorScheme = "auto";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { notifications } from "@mantine/notifications";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
type Message = ReactNode;
|
|
5
|
+
|
|
6
|
+
function show(color: string, message: Message, title?: ReactNode) {
|
|
7
|
+
return notifications.show({ color, message, title });
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** Toast helpers on top of `@mantine/notifications`. Call them from event handlers and callbacks. */
|
|
11
|
+
export const notify = {
|
|
12
|
+
success: (message: Message, title?: ReactNode) => show("green", message, title),
|
|
13
|
+
error: (message: Message, title?: ReactNode) => show("red", message, title),
|
|
14
|
+
info: (message: Message, title?: ReactNode) => show("blue", message, title),
|
|
15
|
+
warning: (message: Message, title?: ReactNode) => show("yellow", message, title),
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/** The first human-readable message in an HTTP result, a page-action payload or an Error. */
|
|
19
|
+
export function messageFrom(value: unknown): string | undefined {
|
|
20
|
+
if (!value || typeof value !== "object") {
|
|
21
|
+
return typeof value === "string" ? value : undefined;
|
|
22
|
+
}
|
|
23
|
+
const source = value as {
|
|
24
|
+
message?: unknown;
|
|
25
|
+
formErrors?: unknown;
|
|
26
|
+
error?: { body?: unknown; message?: unknown };
|
|
27
|
+
data?: unknown;
|
|
28
|
+
};
|
|
29
|
+
if (Array.isArray(source.formErrors) && typeof source.formErrors[0] === "string") {
|
|
30
|
+
return source.formErrors[0];
|
|
31
|
+
}
|
|
32
|
+
const body = source.error?.body ?? source.data;
|
|
33
|
+
const nested =
|
|
34
|
+
body && typeof body === "object" ? (body as { message?: unknown }).message : undefined;
|
|
35
|
+
for (const candidate of [nested, source.error?.message, source.message]) {
|
|
36
|
+
if (typeof candidate === "string" && candidate !== "") {
|
|
37
|
+
return candidate;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type SubmitMessages = {
|
|
44
|
+
success: Message | ((result: unknown) => Message);
|
|
45
|
+
error?: Message | ((result: unknown) => Message);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Spread the result into `useSubmitForm` or `useSubmitAction` to show a toast
|
|
50
|
+
* when the submission succeeds or fails:
|
|
51
|
+
*
|
|
52
|
+
* `useSubmitForm({ route: "contact.send", ...notifyOnSubmit({ success: "Sent" }) })`
|
|
53
|
+
*
|
|
54
|
+
* Without an `error` message the server's own message is shown, falling back to
|
|
55
|
+
* a generic line.
|
|
56
|
+
*/
|
|
57
|
+
export function notifyOnSubmit(messages: SubmitMessages) {
|
|
58
|
+
const resolve = (message: Message | ((result: unknown) => Message), result: unknown) =>
|
|
59
|
+
typeof message === "function" ? (message as (result: unknown) => Message)(result) : message;
|
|
60
|
+
return {
|
|
61
|
+
onSuccess: (result: unknown) => {
|
|
62
|
+
notify.success(resolve(messages.success, result));
|
|
63
|
+
},
|
|
64
|
+
onError: (result: unknown) => {
|
|
65
|
+
notify.error(
|
|
66
|
+
messages.error !== undefined
|
|
67
|
+
? resolve(messages.error, result)
|
|
68
|
+
: (messageFrom(result) ?? "Something went wrong. Please try again."),
|
|
69
|
+
);
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ColorSchemeScript, MantineProvider } from "@mantine/core";
|
|
2
|
+
import { ModalsProvider } from "@mantine/modals";
|
|
3
|
+
import { Notifications } from "@mantine/notifications";
|
|
4
|
+
import type { ReactNode } from "react";
|
|
5
|
+
import { defaultColorScheme, theme } from "./mantine-theme";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Mounts Mantine's theme, the modals manager and the notifications host around
|
|
9
|
+
* the page. Render it once in `src/web/root.tsx`, around `#vessel`.
|
|
10
|
+
*/
|
|
11
|
+
export default function DesignSystemProvider({ children }: { children: ReactNode }) {
|
|
12
|
+
return (
|
|
13
|
+
<MantineProvider theme={theme} defaultColorScheme={defaultColorScheme}>
|
|
14
|
+
<ModalsProvider>
|
|
15
|
+
<Notifications />
|
|
16
|
+
{children}
|
|
17
|
+
</ModalsProvider>
|
|
18
|
+
</MantineProvider>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Sets the stored or system colour scheme on `<html>` before first paint, so a
|
|
24
|
+
* dark-mode visitor never sees a light flash. Render it inside `<head>`.
|
|
25
|
+
*/
|
|
26
|
+
export function DesignSystemColorScheme({ nonce }: { nonce?: string }) {
|
|
27
|
+
return <ColorSchemeScript defaultColorScheme={defaultColorScheme} nonce={nonce} />;
|
|
28
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { FormControlProps } from "@mongez/react-form";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
export type ControlProps = Pick<
|
|
5
|
+
FormControlProps,
|
|
6
|
+
| "name"
|
|
7
|
+
| "rules"
|
|
8
|
+
| "schema"
|
|
9
|
+
| "validate"
|
|
10
|
+
| "validateOn"
|
|
11
|
+
| "onChange"
|
|
12
|
+
| "onError"
|
|
13
|
+
| "errors"
|
|
14
|
+
| "errorKeys"
|
|
15
|
+
| "disabled"
|
|
16
|
+
| "readOnly"
|
|
17
|
+
| "required"
|
|
18
|
+
> & {
|
|
19
|
+
id: string;
|
|
20
|
+
label: ReactNode;
|
|
21
|
+
hint?: ReactNode;
|
|
22
|
+
error?: ReactNode;
|
|
23
|
+
value?: unknown;
|
|
24
|
+
defaultValue?: unknown;
|
|
25
|
+
placeholder?: string;
|
|
26
|
+
className?: string;
|
|
27
|
+
dir?: "ltr" | "rtl";
|
|
28
|
+
autoComplete?: string;
|
|
29
|
+
rows?: number;
|
|
30
|
+
accept?: string;
|
|
31
|
+
multiple?: boolean;
|
|
32
|
+
};
|
|
33
|
+
export type Choice = { value: string; label: string; disabled?: boolean };
|
|
34
|
+
export type SelectProps = ControlProps & {
|
|
35
|
+
options: readonly Choice[];
|
|
36
|
+
searchLabel?: string;
|
|
37
|
+
emptyLabel?: string;
|
|
38
|
+
clearLabel?: string;
|
|
39
|
+
};
|
|
40
|
+
export type RadioProps = ControlProps & { options: readonly Choice[] };
|
|
41
|
+
export type CheckProps = ControlProps & { checked?: boolean; defaultChecked?: boolean };
|
|
42
|
+
export type DateProps = ControlProps & {
|
|
43
|
+
clearLabel?: string;
|
|
44
|
+
closeLabel?: string;
|
|
45
|
+
timeLabel?: string;
|
|
46
|
+
};
|